FireHOL, Adding new services to FireHOL.
Author: Costa Tsaousis
Description: Home for FireHOL, an iptables stateful packet filtering firewall builder for Linux (kernel 2.4), supporting NAT, SNAT, DNAT, REDIRECT, MASQUERADE, DMZ, dual-homed, multi-homed and router setups, protecting and securing hosts and LANs in all kinds of topologies. Configuration is done using simple client and server statements while it can detect (and produce) its configuration automatically. FireHOL is extremely easy to understand, configure and audit.
Keywords: iptables, netfilter, filter, firewall, stateful, port, secure, security, NAT, DMZ, DNAT, DSL, SNAT, redirect, router, rule, rules, automated, bash, block, builder, cable, complex, configuration, dual-homed, easy, easy configuration, example, fast, features, flexible, forward, free, gpl, helpme mode, human, intuitive, language, linux, masquerade, modem, multi-homed, open source, packet, panic mode, protect, script, service, system administration, wizard

It is very simple to extend FireHOL for simple single socket services. There are two different ways to do it.

The service definition syntax

The first needs a small service definition somewhere at the beginning of the FireHOL configuration file.

For example the following:

    	server_myservice_ports="proto/sports"
    	client_myservice_ports="cports"

Where:

- myservice is the name of the service,
- proto is either tcp, udp, icmp - or whatever else iptables accepts as protocol, including numeric representations of protocols
- sports is the port number (or port name or port range) the server is listening at. To specify port ranges use the iptables syntax: i.e. 1000:1010 will match all ports from 1000 to 1010 inclusive.
  The special keyword any will match any server port.
- cports is the port (or port name or port range or space separated list of ports) clients might use to connect to the server. There are two keywords that can be used for cports:
  - any is a keyword that matches any client port.
  - default is a keyword that matches the default client ports and it resolves to:
    - if it is used for a localhost client (i.e. client within an interface), it resolves to a list of ports as set by the Linux kernel and controlled by the sysctl variable net.ipv4.ip_local_port_range (or /proc/sys/net/ipv4/ip_local_port_range),
    - if it is used for a client running at remote host (i.e. server within an interface or any kind within a router), it resolves to the contents of the FireHOL variable DEFAULT_CLIENT_PORTS.

Just the above two lines will allow you to use (for example):

    	interface eth0 internet
    		server myservice accept
    		client myservice reject

    	router myrouter
    		route myservice drop

later in the configuration file.

As an example, assuming that the IMAP4 service was not defined in FireHOL you would have to write:

    	version 5

    	server_imap_ports="tcp/143"
    	client_imap_ports="default"

    	interface eth0 lan0
    		server imap accept

    	interface eth1 lan1
    		client imap reject

    	router lan2lan inface eth0 outface eth1
    		route imap accept

The inline service definition syntax

The second way is to use the inline service definition syntax:

    		server custom myservice proto/sports cports accept

All the parameters are the same with the one presented above, in the previous section.

The IMAP4 service example above, now becomes:

    	version 5

    	interface eth0 lan0
    		server custom imap tcp/143 default accept

    	interface eth1 lan1
    		client custom imap tcp/143 default reject

    	router lan2lan inface eth0 outface eth1
    		route custom imap tcp/143 default accept

So, if you are only going to need a service just once in your firewall, it might be convenient to use the inline syntax, while if you are going to need it many times, it would be easier to use the service definition syntax.
Personally, I always prefer to use the service definition syntax and to avoid the inline one (I always forget that the inline one requires a service name too...).

Multi-socket, but simple servers

Both of the expressions, given above for defining more services, accept multiple arguments.

Fox example, assume there is a service named serveme that listens at two ports, port 1234 TCP and 1234 UDP. The expected client ports are the default random ports a system may choose, plus the same port numbers the server is listening at.

To define this service you will have to write:

    	version 5

    	server_serveme_ports="tcp/1234 udp/1234"
    	client_serveme_ports="default 1234"

    	interface eth0 lan0
    		server serveme accept

    	interface eth1 lan1
    		client serveme reject

    	router lan2lan inface eth0 outface eth1
    		route serveme accept

In this situation, FireHOL simply produces all the combinations between client and server ports and generates multiple iptables statements to accomplish them.

This is also the reason why the protocol cannot be defined in client ports.

Requiring kernel modules

Each service can be configured to require two sets of kernel modules depending whether NAT is enabled or not. This is done on a per service basis, so that if a service is not used in a configuration, FireHOL will not load the module.

The general format is:

    	require_service_modules="some_module"
    	require_service_nat_modules="some_module_for_nat"

As an example you can see the complete IRC definition within FireHOL:

    	server_irc_ports="tcp/ircd"
    	client_irc_ports="default"

    	require_irc_modules="ip_conntrack_irc"
    	require_irc_nat_modules="ip_nat_irc"

    	ALL_SHOULD_ALSO_RUN="${ALL_SHOULD_ALSO_RUN} irc"

The last statement in the above example says to FireHOL, that if the configuration is using the all service, FireHOL should indirectly also setup the irc service with all the optional rule parameters of the all service.

Complex services

Complex services are those that use multiple sockets initiated on both directions (where the client becomes a server and vice versa) of the communication, and possibly involving protocols beyond TCP and UDP.

Currently you will have also to consider as complex all the services that you would prefer not to implement using the connection tracker of iptables (i.e. stateless). In the future, and if there is enough demand, I might expand simple services to handle stateless services too.

To write a complex service you will have to write a BASH function. It is not hard, but it is not two lines of code too, and most probably I am going to change the interface to those functions in the future, as FireHOL evolves. So, if you write one, please sumbit a patch so that I will be able to change your function if and when I change the interface to those functions.

Note however that there are a few types of currently complex services that I'll try to avoid. These are all those services that in order to be implemented in a stateful way there must exist a kernel module for them. If I support these services now, FireHOL will loose its beauty since it will have to have ranges of ports completely open to everyone just in case your service wants them. There are plenty of such kernel modules in an experimental state, which you can use if you decide to patch and recompile your kernel. If you do this, I'll be glad to support your stateful rules about them. If you try to allow such services in a stateless maner by, for example, allowing uncodintionally all traffic at high numbered ports... you are on your own.

If you decide to write a complex service, open FireHOL in your favorite editor and find all the functions that start with rules_. All these functions define rules for the complex services currently supported. If you know the basics of BASH programming, the existing functions will give you a clear idea of what you have to do to write your own.

Distribution of services with third party packages

FireHOL v1.213 and above includes a feature that allows third parties to install new service definitions in the directory /etc/firehol/services. The purpose of this feature is to allow the distributors of third party packages (like proxy servers, dns servers, etc) automatically install their service definitions in your system when their applications are installed.

To install a service definition, just create a file with any name, but with extension .conf in the directory /etc/firehol/services. The file itself must be a BASH script with any logic in it. The only requirements are:

- The script sets up one or more service definitions, either in simple or complex form.
- The first line of the script looks like this:

  #FHVER: 1:213

  The two numbers are the major and minor versions of the FireHOL service definition API. In fact, the major number (1) is increased if the API logic is changed, and the minor (213) is the minimum version of FireHOL the service is expected to work with.

  FireHOL will deny to run the service if the major number is different or if the installed version of FireHOL is older than the one expected by the service.

| $Id: adding.html,v 1.10 2004/10/31 23:43:25 ktsaou Exp $ FireHOL, a firewall for humans... © Copyright 2004 Costa Tsaousis <costa@tsaousis.gr>