Subsections


3.10 The Packet Filter

The Linux kernel used by fli4l provides a packet filter which controls who is allowed to communicate with or through the Router. Furthermore, things like port forwarding (a packet addressed to the router is forwarded to another internal computer) and masquerading (packets sent from a computer behind the router are changed to look as if they came from the router itself) can be realized.

The structure of the packet filter is shown in Figure 3.1.

Packets arrive over a network interface and pass through the PREROUTING-chain. Here the packets addressed to the router are passed to another computer by changing destination address and destination port. If the packet is addressed to the router it is sent to the INPUT-chain, if not, to the FORWARD-chain. Both chains will check if the packet is permitted. If the packet is accepted, it is delivered to the local destination process or passed via the POSTROUTING-chain (in which packet masquerading is done) to the network interface by which it can reach its target. Locally generated packets are filtered in the OUTPUT-chain and finally (if successfully) also pass through the POSTROUTING-chain to the correct network interface.

Figure 3.1: Packet Filter Structure
\includegraphics[width=\columnwidth]{firewall}

With the packet filter configuration, the individual chains of the packet filter can be modified directly. An individual array exists for each chain, one for the INPUT-chain (PF_INPUT_%), one for the FORWARD-chain (PF_FORWARD_%), one for the OUTPUT-chain (PF_OUTPUT_%), one for the PREROUTING-chain (managing port forwarding) (PF_PREROUTING_%), and one for the POSTROUTING-chain, managing packet masquerading (PF_POSTROUTING_%).

An entry in one of these arrays consists mainly of an action (see below) which can be restricted by additional conditions. These conditions relate to properties of the considered packet. A packet contains information about its origin (source PC that has sent the packet), its target (to which PC and which application should the packet be delivered) and much more. Conditions can refer to the following properties of a packet:

If a packet comes in, the entries resp. the resulting rules generated are processed from top to bottom and the first action to which all conditions apply is performed. If none of the rules matches, the default action is executed, which may be specified for (almost) any table.

An entry has the following format, bearing in mind that all restrictions are optional:

    restriction{0,} [[source] [destination]] action [BIDIRECTIONAL|LOG|NOLOG]

At all points where networks, IP addresses or hosts need to be specified, you can also refer to IP_NET_%, IP_NET_%_IPADDR or via @hostname to a host from HOST_%. If OPT_DNS is enabled, then outside of actions via @fqdn also hosts which are nicht mentioned in HOST_% can be referenced by their names. This is particularly useful if dealing with external hosts which also possess many (and changing) IP addresses.


3.10.1 Packet Filter Actions

The following actions appy:

Table 3.5: Packet Filter Actions
Action chain(s) Meaning
     
ACCEPT all Accept the packet.
DROP
 INPUT  
 FORWARD  
 OUTPUT  
Drop the packet (the sender recognizes that just because no answer and no error message comes back).
REJECT
 INPUT  
 FORWARD  
 OUTPUT  
Reject the packet (the sender gets a corresponding error message).
LOG all Log the packet and proceed to the next rule. To distinguish log entries a prefix may be used, specified by LOG:log-prefix. The maximum length of this prefix is 28 characters and it may contain letters, numbers, hyphens (-), and underscores (_).
MASQUERADE POSTROUTING Mask the packet: Replace the source address of the packet by the own one and make sure that replies for this connection are redirected to the correct computer.
SNAT POSTROUTING Replace source address and source port of the packet by the address specified as a parameter for SNAT (for all packets belonging to the connection in consideration).
DNAT PREROUTING Replace destination address and destination port of the packet by the address specified as a parameter for SNAT (for all packets belonging to the connection in consideration).
REDIRECT
 PREROUTING  
 OUTPUT  
Replace destination port of the packet by the address specified as a parameter for SNAT (for all packets belonging to the connection in consideration).
NETMAP
 PREROUTING  
 POSTROUTING  
Copy destination resp. source address of the packet to the range specified as a parameter for NETMAP; the ports stay unchanged (for all packets belonging to the connection in consideration; while changing the destination address in the PREROUTING-chain and the source address of the POSTROUTING-chain).
   

Some of these actions may be modified in behaviour by using the options BIDIRECTIONAL, LOG or NOLOG. BIDIRECTIONAL generates the same rule a second time with source and destination adresse exchanged (and source and destination port exchanged and/or in- and outbound network interface exchanged if specified). LOG/NOLOG activates resp. deactivates logging for this rule.


3.10.2 Restrictions For Rules

Restrictions may be defined by constraints explained in the following sections. You may use any at any place where you don't want restrictions but want/have to specify something. Constraints can be specified in any order if they have a preceding prefix. This applies to all restrictions, except for specifying a source or destination address which must always be placed directly in front of the action, other constraints must be specified before. Restrictions can also be negated, simply prefix them by a !.

3.10.2.1 Constraints For Source And Target

Each packet contains source and target informations in a tuple of an IP address and ports.3.2 This source resp. target can serve as a constraint and may be addressed like this:

Table 3.6: Constraints For Source And Target In Paket Filter Rules
Expression Meaning
   
ip a simple IP address
network a network declaration in the form of <ip>/<netmask>
port[-port] a port resp. a port range
IP_NET_x_IPADDR the IP address of the x router's interface
IP_NET_x the x router's subnet
IP_ROUTE_x the subnet x specified in the route (default routes can't be used, they would match any and are excluded precautiously)
@name one of the names or aliases set via HOST_%_*; the associated IP address will be filled in here
<ip oder netzwerk>:port[-port] Host- resp. network address in one of the variants above, combined with a port resp. port range
   

Example: '192.168.6.2 any DROP'

If two of these lines shine up the first will be considered as source and the second as target. Hence, in this example we drop the packets originating from the computer with the IP address 192.168.6.2, regardless of where they are targeted.

If only one line exists the decision if target or source is meant will be made depending on the value, which is quite easy:

If you would like to shorten the example above you could write '192.168.6.2 DROP'. No port is mentioned, hence the constraint is valid for the source (the machine the packet originated from).

If we were to allow communication with the ssh-deamon, we could write 'any any:22 ACCEPT' (packets from any machine to ssh-port 22 of any machine will be accepted) or even shorter '22 ACCEPT'. Only a port is mentioned, hence we address the target and thus all packets targeted to port 22.

For simplification you may append BIDIRECTIONAL to the action to express that the rule is valid for both communication directions. Then rules will be generated with source and target addresses and if applicable ports and network interfaces exchanged while leaving the rest untouched.

Examples:


  127.0.0.1 ACCEPT local communication (source 127.0.0.1) is allowed  
  any 192.168.12.1 DROP packets to address 192.168.12.1 will be dropped  
  any 192.168.12.1 DROP LOG packets to address 192.168.12.1 will be dropped and logged additionally  
  any 192.168.12.1 DROP NOLOG packets to address 192.168.12.1 will be dropped but not logged  
  22 ACCEPT packets to port 22 (ssh) will be accepted  
  IP_NET_1_NET ACCEPT packets from the subnet connected to the first interface will be accepted  
  IP_NET_1_NET IP_NET_2_NET communication between the subnets connected to the first and second  
  ACCEPT BIDIRECTIONAL interface are allowed  

3.10.2.2 Interface Constraints

A rule can be restricted concerning the Interface on which a packet was received resp. will be transmitted. The format is as follows: if:in:out

In the INPUT-chain the interface for outbound packets is not restrictable (the packet does not leave anyway), in the POSTROUTING-chain the interface for received packets is not restrictable, because the informations about it do not exist anymore. Only in the FORWARD-chain constraints for both can be defined.

Possible values for in resp. out:

3.10.2.3 Protocol Constraints

A rule can be restricted concerning the protocol a packet belongs to. The format is as follows: prot:protocol resp. prot:icmp:icmp-type. protocol can be set to one of the following values:

If such a constraint does not exists, but port numbers should be used in a rule, then the rule is generated twice, once for the tcp and once for the udp protocol.

3.10.2.4 MAC-Address Constraints

Via mac:mac-address constraints based on the MAC address may be specified.

3.10.2.5 Packet State Constraints

fli4l's packet filter gathers informations on the state of connections. This informations can be used to filter packets, i.e let only packets pass that belong to connections already existing. The state of a connection can take this values:3.3

Table 3.7: Packet State Constraints in Packet Filter Rules
State Meaning
   
INVALID The packet does not belong to a know connection.
ESTABLISHED The packet belongs to a connection, where packets have already been transmitted in both directions.
NEW The packet has established a new connection or belongs to a connection that did not have packets transmitted in both directions.
RELATED The packet establishes a new connection, but has a relation to an already existing connection (i.e. ftp establishes a separate connection for data transfer).
   

States are defined as follows: state:state(s). If you want to specify more than one state they have to be separated by commas. I.e. to let packets pass that belong directly or indirectly to established connections write state:ESTABLISHED,RELATED (this makes sense in INPUT- or FORWARD-chain).

3.10.2.6 Constraints Based On The Frequency Of Actions

Under certain circumstances you may wish to restrict the frequency of actions, i.e. allow only one ICMP-Echo request per second. This may be reached with limit-constraints, which look like this: limit:Frequency:Burst. The frequency is specified as n/time units (second, minute, hour, day), however, events may also occur in rapid succession (Burst). limit:3/minute:5 for example means that a maximum of three events per minute is allowed, but also five events in rapid succession will be accepted.


3.10.3 Using Templates With The Packet Filter

To simplify dealing with the packet filter you may summarize rules frequently occuring in templates. Thus, it is possible to provide a wide range of packet filtering rules and combine them in a collection with a symbolic name. Instead of directly using protocols and port numbers, you may then use entries such as tmpl:ssh if you want to use the ssh protocol in a rule. How to deal with templates is shown here using the example of ssh.

If you want to reach your fli4l from the Internet via ssh, write into an entry in the array variable PF_input_% the corresponding service name (here ssh) preceded by tmpl and the action to apply for this service. Example:

    PF_INPUT_2='tmpl:ssh ACCEPT'

tmpl: means that the rule should be based on a template. Specify the name of the service after the `:', adapted to our example hence ssh. At last you have to set an action to be bound to the service. Since we want to acces the fli4l over the internet, we allow the connection with ACCEPT. Restrictions for IP-addresses or nets are not provided so the ssh-service will be accessible on all interfaces from all networks. If you want to invoke further restrictions for accessing the ssh-service you may use the packet filter notation already explained above.

For which services rules are predefined (e.g. templates exist) can be seen in the template file at opt/etc/fwrules.tmpl/templates. A list in a table follows (see table 3.8).

Table 3.8: Templates Included With fli4l
Template Protocol Port(s)
dhcp udp 67-68
dns tcp/udp 53
elster tcp 159.154.8.2:21
elster tcp 159.154.8.35:21
elster tcp 193.109.238.26:8000
elster tcp 193.109.238.27:8000
elster tcp 193.109.238.58:80
elster tcp 193.109.238.59:80
elster tcp 62.157.211.58:8000
elster tcp 62.157.211.59:8000
elster tcp 62.157.211.60:8000
elster tcp 80.146.179.2:80
elster tcp 80.146.179.3:80
ftp tcp 21
http tcp 80
https tcp 443
hylafax tcp 4559
imap tcp 143
imaps tcp 993
imond tcp 5000
ipmi tcp 22
ipmi tcp 2937
ipmi tcp 443
ipmi tcp 5120
ipmi tcp 5123
ipmi tcp 5900
ipmi tcp 5901
ipmi tcp 80
ipmi tcp 8889
ipmi udp 623
irc tcp 6667
ldap tcp/udp 389
mail tcp 110
mail tcp 143
mail tcp 25
mail tcp 465
mail tcp 587
mail tcp 993
mail tcp 995
mysql tcp 3306
nfs tcp/udp 111
nfs tcp/udp 2049
nntp tcp 119
ntp udp 123
oracle tcp 1521
pcanywhere tcp 5631-5632
ping icmp:0
ping icmp:8
pop3 tcp 110
pop3s tcp 995
privoxy tcp 8118
proxmox tcp 8006
proxmox tcp 5900
proxmox tcp 3128
rdp tcp 3389
rsync tcp 873
samba tcp 139
samba tcp 445
samba udp 137-138
sip tcp/udp 5060-5061
smtp tcp 25
snmp tcp/udp 161
socks tcp 1080
squid tcp 3128
ssh tcp 22
ssmtp tcp 465
submission tcp 587
svn tcp 3690
syslog udp 514
teamspeak tcp 14534
teamspeak tcp 51234
teamspeak udp 8767
telmond tcp 5001
telnet tcp 23
teredo udp 3544
tftp udp 69
time tcp/udp 37
traceroute udp 33404-33464
vdr tcp 6419
vnc tcp 5900
whois tcp 43
xbl tcp/udp 3074
xbl udp 88
xmppclient tcp 5222
xmppserver tcp 5269

The Syntax for this kind of packet filter rules is

    tmpl:<Name of the service> <Constraint> <Action>

<Constraint> allows everything mentioned at 3.10.2. Possible values for <Action> are listed and described in 3.10.1.

Some more examples should clarify the process. At first let's have a look at PF_PREROUTING:

    PF_PREROUTING_N='2'
    PF_PREROUTING_1='tmpl:xbl dynamic DNAT:@xbox'
    PF_PREROUTING_2='tmpl:https dynamic DNAT:192.168.193.250'

The rule PF_PREROUTING_1 supplies the Xbox with everything necessary for Xbox Live. By the use of tmpl:xbl all ports and protocols used for Xbox Live will be forwarded to the xbox. Instead of using an IP address we use an entry from the HOST_%_NAME-array. dynamic tells the fli4l to forward all ports from the internet interface.

The second rule forwards the https-protocol to a webserver in a DMZ (Demilitarized Zone).

No let's have a look at PF_INPUT:

    PF_INPUT_N='3'
    PF_INPUT_1='if:IP_NET_1_DEV:any ACCEPT'
    PF_INPUT_2='if:pppoe:any prot:tcp 113 ACCEPT'
    PF_INPUT_3='if:br0:any tmpl:dns @xbox IP_NET_1_IPADDR ACCEPT'

The first rule allows access to the router for everyone from the net defined in IP_NET_1. The second rule opens the ident-port needed for package oident. The third rule allows the xbox to access fli4l's DNS server. Notice the use of a host alias here.

PF_FORWARD and PF_POSTROUTING do not provide tmpl-specific content.

Figure 3.2: Directory Structure fli4l
Image etc_fwrules_tmpl_dir

It is also possible to create templates yourself or for other packages to provide their own ones. To create a template you only need to create a text file with the rules in it and name it like the template. For a private template file use the directory etc/fwrules.tmpl (create it if necessary) under your config directory as shown in picture 3.2. Package developers or users needing templates for more than one configuration may place their template files directly in opt/etc/fwrules.tmpl. The templates in the user's config directory override other settings, though. The templates included in fli4l will be interpreted as the last ones. This enables you to override fli4l's templates when providing templates by the same name in your config-directory.

If, for example you like to create the template vpn_friends, create a file by the name vpn_friends. The template should contain the services ssh, smtp, dns and samba. Hence you write the following to vpn_friends:

    prot:tcp 22
    prot:tcp 25
    53
    prot:udp 137-138
    prot:tcp 139
    prot:tcp 445

Every time you use the template vpn_friends rules will be created for all contained protocols and ports. PF_FORWARD_x='tmpl:vpn_friends ACCEPT' will create theses FORWARD-rules:

    prot:tcp 22 ACCEPT
    prot:tcp 25 ACCEPT
    53 ACCEPT
    prot:udp 137-138 ACCEPT
    prot:tcp 139 ACCEPT
    prot:tcp 445 ACCEPT

3.10.4 Configuration Of The Packet Filter

The packet filter is mainly configured by four array-variables:

For all chains following applies the setting of the protocol level in PF_LOG_LEVEL, which may be set to one of these values: debug, info, notice, warning, err, crit, alert, emerg.

3.10.4.1 Then INPUT-Chain

The INPUT-chain defines who is allowed to access the router. If no rule of the INPUT-chain matches, the default action handles the packet and the protocol variable decides wheter a rejection will be written to the system-protocol or not.

The following restrictions apply to the parameters:

PF_INPUT_POLICY
This variable describes the default action to be taken if no other rule applies. Possible values:

PF_INPUT_ACCEPT_DEF
If this variable is set to `yes' default rules will be generated needed for the correct function of the router. Use `yes' as a default here.

If you want to configure the router's behaviour completely yourself you may enter `no' here but you will have to define all rules on your own then. An equivalent to the default behaviour would look like this (the explanation of user defined chains can be found here):

    PF_INPUT_ACCEPT_DEF='no'
    #
    # limit ICMP echo requests - use a separate chain
    #
    PF_USR_CHAIN_N='1'
    PF_USR_CHAIN_1_NAME='usr-in-icmp'
    PF_USR_CHAIN_1_RULE_N='2'
    PF_USR_CHAIN_1_RULE_1='prot:icmp:echo-request length:0-150 limit:1/second:5 ACCEPT'
    PF_USR_CHAIN_1_RULE_2='state:RELATED ACCEPT'

    PF_INPUT_N='4'
    PF_INPUT_1='prot:icmp usr-in-icmp'
    PF_INPUT_2='state:ESTABLISHED,RELATED ACCEPT'
    PF_INPUT_3='if:lo:any ACCEPT'
    PF_INPUT_4='state:NEW 127.0.0.1 DROP BIDIRECTIONAL'

The first rule branches to the rate limited ``usr-in-icmp''-chain. The second only accepts packets belonging to established connections (packets that have either the state ESTABLISHED or RELATED), and the third one allows local communication (if:lo:any ACCEPT). The fourth filters packets that pretend to be local communication but are not accepted by the rules defined before.

If you work with OpenVPN, the rules have to be enhanced to enable packets used by the chains there.

    PF_INPUT_N='5'
    ...
    PF_INPUT_5='ovpn-chain'

PF_INPUT_LOG
Defines if rejected packets should be logged by the kernel. Log output can be directed to the syslog deamon by activating OPT_KLOGD.

PF_INPUT_LOG_LIMIT
Defines how often log entries will be generated. The frequency is described as n/time units with bursts in analog to the limit constraints, e.g. 3/minute:5. If this entry is empty a default of 1/second:5 is used, if set to none, the limit constraints are disabled.

PF_INPUT_REJ_LIMIT PF_INPUT_UDP_REJ_LIMIT
Specifies how often a REJECT-packet is generated when rejecting incoming packets. The frequency is described as n/time units with bursts in analog to the limit constraints, e.g. 3/minute:5. If this entry is empty a default of 1/second:5 is used, if set to none, the limit constraints are disabled.

PF_INPUT_ICMP_ECHO_REQ_LIMIT
Defines how often fli4l should react to a ICMP-Echo-request.The frequency is described as n/time units with bursts in analog to the limit constraints, e.g. 3/minute:5. If the limit is reached packets will be ignored (DROP). If this entry is empty a default of 1/second:5 is used, if set to none, the limit constraints are disabled.

PF_INPUT_ICMP_ECHO_REQ_SIZE
Defines the allowed size of an ICMP-Echo-request (in bytes). The packet header has to be included in this setting besides the pure data. The default is 150 bytes.

PF_INPUT_N PF_INPUT_x PF_INPUT_x_COMMENT
A list of rules that describe which packets the router should accept resp. reject.

3.10.4.2 The FORWARD-Chain

By using the FORWARD-chain will be configured which packets are forwarded by the router. If no rule of the FORWARD-chain matches, the default action handles the packet and the protocol variable decides wheter a rejection will be written to the system-protocol or not.

With the used parameters the restriction applies that only the actions ACCEPT, DROP and REJECT are allowed.

PF_FORWARD_POLICY
This variable describes the default action to be taken if no other rule applies. Possible values:

PF_FORWARD_ACCEPT_DEF
Determines if the router accepts packets belonging to established connections. If this variable is set to `yes', fli4l generates a rule for accepting packets of the according state automatically:

'state:ESTABLISHED,RELATED ACCEPT',

aswell as a rule to drop packets of unknown state:

'state:INVALID DROP'.

and at last a rule to drop packets with faked IP addresses:

'state:NEW 127.0.0.1 DROP BIDIRECTIONAL'.

In addition the other subsystems will generate some default rules - a configuration without default rules with port forwarding and OpenVPN would contain at least the following rules:

    PF_FORWARD_ACCEPT_DEF='no'
    PF_FORWARD_N='5'
    PF_FORWARD_1='state:ESTABLISHED,RELATED ACCEPT'
    PF_FORWARD_2='state:INVALID DROP'
    PF_FORWARD_3='state:NEW 127.0.0.1 DROP BIDIRECTIONAL'
    PF_FORWARD_4='pfwaccess-chain'
    PF_FORWARD_5='ovpn-chain'

PF_FORWARD_LOG
Defines if rejected packets should be logged by the kernel. Log output can be directed to the syslog deamon by activating OPT_KLOGD.

PF_FORWARD_LOG_LIMIT
Defines how often log entries will be generated. The frequency is described as n/time units with bursts in analog to the limit constraints, e.g. 3/minute:5. If this entry is empty a default of 1/second:5 is used, if set to none, the limit constraints are disabled.

PF_FORWARD_REJ_LIMIT PF_FORWARD_UDP_REJ_LIMIT
Specifies how often a REJECT-packet is generated when rejecting incoming packets. The frequency is described as n/time units with bursts in analog to the limit constraints, e.g. 3/minute:5. If this entry is empty a default of 1/second:5 is used, if set to none, the limit constraints are disabled.

PF_FORWARD_N PF_FORWARD_x PF_FORWARD_x_COMMENT
A list of rules that describe which packets the router should forward resp. reject.

3.10.4.3 The OUTPUT-Chain

The OUTPUT-chain configures what the router is allowed to access. If no rule of the OUTPUT-chain matches, the default action handles the packet and the protocol variable decides wheter a rejection will be written to the system-protocol or not.

With the used parameters the following restrictions apply:

PF_OUTPUT_POLICY
This variable describes the default action to be taken if no other rule applies. Possible values:

PF_OUTPUT_ACCEPT_DEF
If this variable is set to `yes' default rules necessary for correct function of the router will be generated. Use `yes' as a default here.

If you want to configure the router's behaviour completely yourself you may enter `no' here but you will have to define all rules on your own then. An equivalent to the default behaviour would look like this:

    PF_OUTPUT_ACCEPT_DEF='no'

    PF_OUTPUT_N='1'
    PF_OUTPUT_1='state:ESTABLISHED,RELATED ACCEPT'

This single rule accepts only packets belonging to established connections (e.g. packets of the state ESTABLISHED or RELATED).

PF_OUTPUT_LOG
Defines if rejected packets should be logged by the kernel. Log output can be directed to the syslog deamon by activating OPT_KLOGD.

PF_OUTPUT_LOG_LIMIT
Defines how often log entries will be generated. The frequency is described as n/time units with bursts in analog to the limit constraints, e.g. 3/minute:5. If this entry is empty a default of 1/second:5 is used, if set to none, the limit constraints are disabled.

PF_OUTPUT_REJ_LIMIT PF_OUTPUT_UDP_REJ_LIMIT
Specifies how often a REJECT-packet is generated when rejecting incoming packets. The frequency is described as n/time units with bursts in analog to the limit constraints, e.g. 3/minute:5. If the limit is exceeded packets will be ignored (DROP). If this entry is empty a default of 1/second:5 is used, if set to none, the limit constraints are disabled.

PF_OUTPUT_N PF_OUTPUT_x PF_OUTPUT_x_COMMENT
A list of rules that describe which packets the router should transmit resp. drop.


3.10.4.4 User Defined Lists

In several cases you may want to establish own chains to filter packets in detail there. These chains can be defined and filled with rules via PF_USR_CHAIN_%. The names of the chains have to start with usr- and after their definition can be used everywhere in the INPUT- or FORWARD-chain as actions. The ICMP-filter chain used before will serve as an example here:

    PF_USR_CHAIN_N='1'
    #
    # create usr-in-icmp
    #
    PF_USR_CHAIN_1_NAME='usr-in-icmp'
    #
    # add rule to usr-in-icmp
    #
    PF_USR_CHAIN_1_RULE_N='2'
    PF_USR_CHAIN_1_RULE_1='prot:icmp:echo-request length:0-150 limit:1/second:5 ACCEPT'
    PF_USR_CHAIN_1_RULE_2='state:RELATED ACCEPT'
    #
    # use chain in PF_INPUT
    #
    PF_INPUT_2='prot:icmp usr-in-icmp'

PF_USR_CHAIN_N
Defines the number of user defined chains.

PF_USR_CHAIN_x_NAME
Defines the name of an user defined chain. The name has to be prefixed by usr-.

PF_USR_CHAIN_x_RULE_N
PF_USR_CHAIN_x_RULE_x
PF_USR_CHAIN_x_RULE_x_COMMENT
These variables define the rules to be inserted in the user defined chain. All rules may be used that are also valid for the FORWARD-chain. If no rule of the user defined chains matches, the router will return to the parent chain and check the next rule after the branching to the user defined rules.

3.10.4.5 The NAT-Chains (Network Address Translation)

Packets still can be changed after the routing decision. For example they may get a new target address to be forwarded to another computer (port forwarding) or a new source address may be inserted to mask the network behind the router. Masquerading is used i.e. to provide internet access for a private net over one public IP or a in DMZ-setup to hide the structure of the local net from computers in the DMZ.

Configuration is done with two chains, PREROUTING- and POSTROUTING-chain.
By the POSTROUTING-chain the packets are defined that have to be masked by the router. If no rule of the POSTROUTING-chain matches, the packets will be forwarded unmasked.

Two variants exist for masquerading: one for network interfaces that do get an IP address allocated on dialin (MASQUERADE) and one for network interfaces with static IP address (SNAT). SNAT in addition expects the source IP address to be inserted into the packet. It may be specified as an:

For both SNAT and MASQUERADE a port or port range may be set to which the source port may be redirected. Usually this notation is necessary because the kernel can choose the ports on its own. But there exist applications that desire the source port unchanged (and thus require 1:1-NAT) or which forbid PAT (Port Address Translation) or NAPT (Network Address and Port Translation). The port range is simply added to the end, like this: SNAT:IP_NET_1_IPADDR:4000-8000.

With the POSTROUTING-chain only ACCEPT, SNAT, NETMAP and MASQUERADE may be used as actions.

PF_POSTROUTING_N PF_POSTROUTING_x PF_POSTROUTING_x_COMMENT

A list of rules that describe which packets the router should mask resp. forward unmasked. If packets should be excluded from masking an ACCEPT-rule for these packets may be put in front of the MASQUERADE rule.

The PREROUTING-chain configures which packets should be transferred to another computer. If no rule of the PREROUTING-chain matches the packets will be processed further without changes. The action DNAT expects the IP address to be inserted as the target address. It may be specified as an:

At last a port or port range may be set to which the target port may be redirected. This is only necessary if the target port should be changed. The port (range) is simply added to the end, like this: DNAT:@server:21.

REDIRECT behaves like DNAT, except for that the Destination IP address is always set to the (primary) IP address of the interface on which the packet came in so the packet is delivered locally. This is needed i.e. for transparent proxies, see OPT_TRANSPROXY.

If you want a port forwarded to an interface with a dynamic address you do not know to which IP the packet should be sent (at the time of configuration). Thus you can use dynamic in the PREROUTING-chain as a wildcard for the IP address assigned later on, like this:

    'dynamic:80  DNAT:1.2.3.4'           # forward http-packets to
                                         # IP address 1.2.3.4
    'prot:gre any dynamic DNAT:1.2.3.4'  # forward gre-packets (part of the  PPTP-
                                         # protocol) to IP address 1.2.3.4

Only ACCEPT, DNAT, NETMAP and REDIRECT may be used as actions with the PREROUTING-chain.

For further examples on port forwarding see the next paragraph.

PF_PREROUTING_N PF_PREROUTING_x PF_PREROUTING_x_COMMENT

A list of rules that describe which packets should be forwarded to another target by the router.

3.10.5 Example

Below see some examples of the packet filter configuration.

3.10.5.1 The fli4l Default Configuration

fli4l's default configuration for the INPUT-chain looks like this:

    PF_INPUT_POLICY='REJECT'
    PF_INPUT_ACCEPT_DEF='yes'
    PF_INPUT_LOG='no'
    PF_INPUT_N='1'
    PF_INPUT_1='IP_NET_1 ACCEPT'

By this we accomplish that

The FORWARD-chain looks alike: Only packets of our local net and packets belonging to connections that were established by machines in our local net should be forwarded. In addition NetBIOS- and CIFS-packets will be dropped.

    PF_FORWARD_POLICY='REJECT'
    PF_FORWARD_ACCEPT_DEF='yes'
    PF_FORWARD_LOG='no'
    PF_FORWARD_N='2'
    PF_FORWARD_1='tmpl:samba DROP'
    PF_FORWARD_2='IP_NET_1 ACCEPT'

Note the dependance on the order of rules: At first the NetBIOS-packets are dropped and afterwards the packets of the local net are accepted.

The local net may communicate with the router, its packets get forwarded, only the masking which is necessary for the internet access of a local network is still missing:

    PF_POSTROUTING_N='1'
    PF_POSTROUTING_1='IP_NET_1 MASQUERADE'

3.10.5.2 Trusted Nets

If we do want to have several local subnets which should communicate with each other free and unmasked we have to ensure that packets between those nets don't get dropped or masked. In order to achieve this we add a rule or edit the existing one.

Let's assume we have a DSL connection over PPPoE and the two subnets are IP_NET_1 (192.168.6.0/24) and IP_NET_2 (192.168.7.0/24). In this case the configuration would be as follows:

    PF_FORWARD_POLICY='REJECT'
    PF_FORWARD_ACCEPT_DEF='yes'
    PF_FORWARD_LOG='no'
    PF_FORWARD_N='4'
    PF_FORWARD_1='IP_NET_1 IP_NET_2 ACCEPT BIDIRECTIONAL'
    PF_FORWARD_2='tmpl:samba DROP'
    PF_FORWARD_3='IP_NET_1 ACCEPT'
    PF_FORWARD_4='IP_NET_2 ACCEPT'

    PF_POSTROUTING_N='3'
    PF_POSTROUTING_1='IP_NET_1 IP_NET_2 ACCEPT BIDIRECTIONAL'
    PF_POSTROUTING_2='IP_NET_1 MASQUERADE'
    PF_POSTROUTING_3='IP_NET_2 MASQUERADE'

The first rule ensures forwarding of packets between both subnets without further processing. The third and fourth rule ensure that both subnets also have Internet access. The first rule of the POSTROUTING-chain provides unmasked communication between both subnets.

In other words we could say that only packets transferred over the pppoe-interface have to be masked:

    PF_POSTROUTING_N='1'
    PF_POSTROUTING_1='if:any:pppoe MASQUERADE'

We could as well have restricted the port filtering to the pppoe-interface and combined both subnets to one, as seen here:

    PF_FORWARD_POLICY='REJECT'
    PF_FORWARD_ACCEPT_DEF='yes'
    PF_FORWARD_LOG='no'
    PF_FORWARD_N='2'
    PF_FORWARD_1='if:any:pppoe tmpl:samba DROP'
    PF_FORWARD_2='192.168.6.0/23 ACCEPT'

    PF_POSTROUTING_N='1'
    PF_POSTROUTING_1='if:any:pppoe MASQUERADE'

Packets going out over the pppoe-interface and those addressed to udp-ports 137-138 or to tcp-ports 139 and 445 will be dropped (rule 1), all other packets from subnet 192.168.6.0/23 will be forwarded (rule 2).

3.10.5.3 Route Network

Let's add a net 10.0.0.0/24 (i.e. a dial-in network) which we want to communicate with unmasked, but packets to udp-ports 137-138 and to tcp-Ports 139 and 445 should be dropped:

    PF_FORWARD_POLICY='REJECT'
    PF_FORWARD_ACCEPT_DEF='yes'
    PF_FORWARD_LOG='no'
    PF_FORWARD_N='4'
    PF_FORWARD_1='IP_NET_1 IP_NET_2 ACCEPT BIDIRECTIONAL'
    PF_FORWARD_2='tmpl:samba DROP'
    PF_FORWARD_3='192.168.6.0/23 ACCEPT'
    PF_FORWARD_4='10.0.0.0/24 ACCEPT'

    PF_POSTROUTING_N='2'
    PF_POSTROUTING_1='10.0.0.0/24 ACCEPT BIDIRECTIONAL'
    PF_POSTROUTING_2='192.168.6.0/23 MASQUERADE'

An alternative:

    PF_POSTROUTING_N='1'
    PF_POSTROUTING_1='if:any:pppoe MASQUERADE'

This rule enables masking only for packets going out over the pppoe-interface.

3.10.5.4 Blacklists, Whitelists

Blacklists (a machine in this list is forbidden to do something) and Whitelists (a machine in this list is allowed to do something) are defined in a very similarl way. Rules are written that are very special at the beginning and to the end are becoming more universal. With a blacklist rules are defined that at the beginning forbid something and at the end allow something to all not previously mentioned. With a Whitelist it is exactly the other way round.

Example 1: All machines in subnet 192.168.6.0/24 except number 12 are allowed to access the Internet as long as they don't use CIFS Ports 137-138 (udp), 139 and 445 (tcp) to communicate:

    PF_FORWARD_POLICY='REJECT'
    PF_FORWARD_ACCEPT_DEF='yes'
    PF_FORWARD_LOG='no'
    PF_FORWARD_N='3'
    PF_FORWARD_1='192.168.6.12 DROP'
    PF_FORWARD_2='tmpl:samba DROP'
    PF_FORWARD_3='192.168.6.0/23 ACCEPT'

    PF_POSTROUTING_N='1'
    PF_POSTROUTING_2='192.168.6.0/24 MASQUERADE'

Example 2: Only machine 12 has Internet access (with exception of the ports mentioned above...), all others are only allowed to communicate with another local subnet:

    PF_FORWARD_POLICY='REJECT'
    PF_FORWARD_ACCEPT_DEF='yes'
    PF_FORWARD_LOG='no'
    PF_FORWARD_N='3'
    PF_FORWARD_1='192.168.6.0/24 192.168.7.0/24 ACCEPT BIDIRECTIONAL'
    PF_FORWARD_2='tmpl:samba DROP'
    PF_FORWARD_3='192.168.6.12 ACCEPT'

    PF_POSTROUTING_N='1'
    PF_POSTROUTING_1='if:any:pppoe MASQUERADE'

3.10.6 Default Configurations

3.10.6.1 Simple Router Masking A Net Behind Itself

#
# Access to the router
#
PF_INPUT_POLICY='REJECT'
PF_INPUT_ACCEPT_DEF='yes'
PF_INPUT_LOG='no'
PF_INPUT_N='1'
PF_INPUT_1='IP_NET_1 ACCEPT'   # all hosts of the local net are allowed
                               # to access the router

#
# Internet access
#
PF_FORWARD_POLICY='REJECT'
PF_FORWARD_ACCEPT_DEF='yes'
PF_FORWARD_LOG='no'

PF_FORWARD_N='2'
PF_FORWARD_1='tmpl:samba DROP' # Samba-packets, that want to leave the
                               # net are dropped
PF_FORWARD_2='IP_NET_1 ACCEPT' # all other packets are allowed
                               # to leave the local net

#
# Maskieren des lokalen Netzes
#
PF_POSTROUTING_N='1'
PF_POSTROUTING_1='IP_NET_1 MASQUERADE'  # mask packets leaving the
                                        # subnet

3.10.6.2 Simple Router Masking Two Nets Behind Itself

#
# Access to the router
#
PF_INPUT_POLICY='REJECT'
PF_INPUT_ACCEPT_DEF='yes'
PF_INPUT_LOG='no'
PF_INPUT_N='2'
PF_INPUT_1='IP_NET_1 ACCEPT'   # all hosts of the local net are allowed
                               # to access the router
PF_INPUT_2='IP_NET_2 ACCEPT'   # all hosts of the local net are allowed
                               # to access the router

#
# Internet access
#
PF_FORWARD_POLICY='REJECT'
PF_FORWARD_ACCEPT_DEF='yes'
PF_FORWARD_LOG='no'

#
# Free communication between the nets
#
PF_FORWARD_N='4'
PF_FORWARD_1='IP_NET_1 IP_NET_2 ACCEPT BIDIRECTIONAL'
PF_FORWARD_2='tmpl:samba DROP' # Samba-packets, that want to leave the
                               # net are dropped
PF_FORWARD_3='IP_NET_1 ACCEPT' # all other packets are allowed
                               # to leave the local net
PF_FORWARD_4='IP_NET_2 ACCEPT' # all other packets are allowed
                               # to leave the local net

#
# Masking of local nets, unmasked communication between those nets
#
PF_POSTROUTING_N='3'
PF_POSTROUTING_1'IP_NET_1 IP_NET_2 ACCEPT BIDIRECTIONAL'
PF_POSTROUTING_2='IP_NET_1 MASQUERADE'  # mask packets leaving the
                                        # subnet
PF_POSTROUTING_3='IP_NET_2 MASQUERADE'  # mask packets leaving the
                                        # subnet

3.10.6.3 Masking DSL-Router With Two Nets Behind It And SSH/HTTP-Access From the Internet

#
# Access to the router
#
PF_INPUT_POLICY='REJECT'
PF_INPUT_ACCEPT_DEF='yes'
PF_INPUT_LOG='no'
PF_INPUT_N='4'
PF_INPUT_1='IP_NET_1 ACCEPT'   # all hosts of the local net are allowed
                               # to access the router
PF_INPUT_2='IP_NET_2 ACCEPT'   # all hosts of the local net are allowed
                               # to access the router
PF_INPUT_3='tmpl:ssh ACCEPT'   # allow access to the SSH service
                               # from everywhere
PF_INPUT_4='tmpl:http 1.2.3.4/24 ACCEPT'  # allow machines from
                               # a defined subnet access to the
                               # HTTP service


#
# Internet access
#
PF_FORWARD_POLICY='REJECT'
PF_FORWARD_ACCEPT_DEF='yes'
PF_FORWARD_LOG='no'

#
# No communication between the nets, both nets have
# Internet access, Samba-packets are dropped
#
PF_FORWARD_N='2'
PF_FORWARD_1='tmpl:samba if:any:pppoe DROP' # Samba-packets, that want to leave the
                               # net are dropped
PF_FORWARD_2='if:any:pppoe ACCEPT' # all other packets are allowed
                               # to leave the local net

#
# Masking of local nets, unmasked communication between those nets
#
PF_POSTROUTING_N='1'
PF_POSTROUTING_1='if:any:pppoe MASQUERADE'  # mask packets leaving the
                                            # subnet

3.10.6.4 Port Forwarding

Port forwarding can be accomplished with the PREROUTING-rules like this (TARGET refers to the original target address (optional) and the original target port, NEW_TARGET refers to the new target address and new target port (optional), PROTOCOL refers to the protocol in use):

    TARGET='<port>'
    NEW_TARGET='<ip>'
    PROTOCOL='<proto>'
    PF_PREROUTING_x='prot:<proto> dynamic:<port> DNAT:<ip>'

    TARGET='<port1>-<port2>'
    NEW_TARGET='<ip>'
    PROTOCOL='<proto>'
    PF_PREROUTING_x='prot:<proto> dynamic:<port1>-<port2> DNAT:<ip>'

    TARGET='<ip>:<port-a>'
    NEW_TARGET='<ip>:<port-b>'
    PROTOCOL='<proto>'
    PF_PREROUTING_x='prot:<proto> any <ip>:<port-a> DNAT:<ip>:<port-b>'

3.10.6.5 Transparent Proxy

If access to the Internet should only be allowed over a local proxy you may force this behaviour by the help of the PREROUTING- and POSTROUTING-chains without the client noticing it. In priciple you need to do this in three steps:

  1. Redirect all HTTP-port-request to the Proxy except for its own ones (PREROUTING).
  2. Change the redirected packets in a way that fools the proxy to think they all come from the router so it will return its answers there (POSTROUTING).
  3. Allow the packets to pass the FORWARD-chain, as far as an entry like

    PF_FORWARD_x='IP_NET_1 ACCEPT'
    
    does not exist (FORWARD).

Example 1: Let's assume we only have one net IP_NET_1, a squid proxy is running there on a host by the name of proxy and the whole http-traffic should be processed by it. Squid listens on port 3128. For simplicity we refer via @proxy to the host entered in HOST_1_NAME='proxy' (see Domain Configuration).

Here are the resulting rules:

...
  PF_PREROUTING_x='@proxy ACCEPT'
      # packets from the proxy should not be redirected

  PF_PREROUTING_x='prot:tcp IP_NET_1 80 DNAT:@proxy:3128'
      # HTTP-packets from IP_NET_1 will be redirected to @proxy, Port 3128
      # independet of the target

  PF_POSTROUTING_x='any @proxy:3128 SNAT:IP_NET_1_IPADDR'
      # change all packets to port 3128 in a way as if they came from
      # fli4l (IP_NET_1_IPADDR)

  PF_FORWARD_x='prot:tcp @proxy 80 ACCEPT'
      # let HTTP-packets from the proxy pass the FORWARD-chain (if necessary)
...

If more nets or conflicting port forwardings (which are also DNAT-rules) exist, the rules may have to be more differentiated.

Example 2: Our proxy by the name of proxy resides in IP_NET_1, listens to port 3128 and should only serve clients from IP_NET_1. IP_NET_1 is reachabel over IP_NET_1_DEV. Packets from other nets should not be considered.

...
  PF_PREROUTING_x='if:IP_NET_1_DEV:any !@proxy 80 DNAT:@proxy:3128'
      # Redirect queries to the HTTP-port that do not emerge from the proxy but
      # come in on an internal interface (IP_NET_1_DEV) to the proxy's port.
      # At this point it is important to check with if:IP_NET_1_DEV:any that the 
      # packets are coming from inside because otherwise packets from outside 
      # would also be redirected (security breakage)

  PF_POSTROUTING_x='prot:tcp IP_NET_1 @proxy:3128 SNAT:IP_NET_1_IPADDR'
      # Change HTTP-packets originating from IP_NET_1 and destinated to proxy-port 3128
      # in a way as if they came from fli4l (IP_NET_1_IPADDR)

  PF_FORWARD_x='prot:tcp @proxy 80 ACCEPT'
      # let HTTP-packets from the proxy pass the FORWARD-chain (if necessary)
...

Example 3: To ease our live and shorten the rules we may use templates (see Using Templates With The Packet Filter). At this point tmpl:http, translated in prot:tcp any any:80 is of advantage. tmpl:http IP_NET_1 DNAT:@proxy:3128 then changes to prot:tcp IP_NET_1 80 DNAT:@proxy:3128.

Both IP_NET_1 and IP_NET_2 should be redirected transparently over the proxy. Simplified you could write:

...
  PF_PREROUTING_x='tmpl:http @proxy   ACCEPT'
      # HTTP-packets from the proxy should not be redirected

  PF_PREROUTING_x='tmpl:http IP_NET_1 DNAT:@proxy:3128'
      # HTTP-packets from IP_NET_1 should be redirected

  PF_PREROUTING_x='tmpl:http IP_NET_2 DNAT:@proxy:3128'
      # HTTP-packets from IP_NET_2 should be redirected

  PF_POSTROUTING_x='IP_NET_1 @proxy:3128 SNAT:IP_NET_1_IPADDR'
  PF_POSTROUTING_x='IP_NET_2 @proxy:3128 SNAT:IP_NET_2_IPADDR'

  PF_FORWARD_x='tmpl:http @proxy ACCEPT'
...

You may continue here forever...


3.10.7 DMZ - Demilitarized Zone

fli4l may also serve to build a DMZ. As this is only another additional ruleset for the router please refer to the wiki at https://ssl.nettworks.org/wiki for the time being.


3.10.8 Conntrack-Helpers

Using IP-Masquerading has the advantage that a bunch of machines in the LAN can be routed over only one official IP-address. However, there are also disadvantages that you have to take into account.

A big problem for example is that no machine from outside can contact the machines in the LAN. This may be desired for security reasons but certain protocols will not work anymore because they require a connection from outside.

A classic example is FTP. Beside a communication channel to exchange commands and answers another channel is needed (an IP-port) to transfer the actual data. fli4l uses certain conntrack-helpers for this in order to open such ports instantaneously and redirect them to the machine in question when needed. The conntrack-helper ``listens'' to the data stream to recognize when such an additional port is needed.

Typical applications for conntrack-helpers are i.e. chat-protocols and Internet games.

Conntrack-helper are activated over rules in two special arrays. The array PF_PREROUTING_CT_% contains helper-assignments to packets coming from outside, the array PF_OUTPUT_CT_% contains helper-assignments to packets generated on the router. Some practical examples help to illustrate this.

Example 1: If active FTP from the LAN should be allowed this is, from the router's view, a connection from outside the router, thus an entry in PF_PREROUTING_CT_% has to be created:

    PF_PREROUTING_CT_N='1'
    PF_PREROUTING_CT_1='tmpl:ftp IP_NET_1 HELPER:ftp'

The ftp-helper module will be loaded for all TCP connections from the local network (IP_NET_1) to any other addresses' port 21 (which is the ftp-Port). This module will allow the FTP server to establish a data transfer connection back to the client during this connection by opening a ``hole'' in the firewall temporarily.

Example 2: If you want to enable passive ftp for a FTP server on the LAN (the data connection is established from the outside to the inside, so that a hole in the firewall must be opened here as well), this is also seen as a connection from outside by the router. Here we see the rule as for this:

    PF_PREROUTING_CT_N='1'
    PF_PREROUTING_CT_1='tmpl:ftp any dynamic HELPER:ftp'

By this rule it is expressed that all FTP connections to the dynamic address of the router are associated to the FTP conntrack helper. Here dynamic was used because it is assumed that the router is responsible for dialing in to the Internet and thus has an external IP address. If the router performs dial-in via DSL, the rule can also be written as:

    PF_PREROUTING_CT_N='1'
    PF_PREROUTING_CT_1='tmpl:ftp if:pppoe:any HELPER:ftp'

By this rule it is expressed that all FTP connections coming from the DSL interface (pppoe) are associated to the conntrack helper.

If the router is not dialing, but e.g. is behind another router (Fritz! box, cable modem, a.s.o.) the following rules can be used:

    PF_PREROUTING_CT_N='1'
    PF_PREROUTING_CT_1='tmpl:ftp if:IP_NET_2_DEV:any HELPER:ftp'

It is assumed in the Example, that the connection to the other router is performed over the interface associated with the second subnet (IP_NET_2_DEV).

Remember that of course an additional configuration of the FORWARD-chain is needed to really forward the FTP-packets. A typical rule would be

    PF_PREROUTING_1='tmpl:ftp any dynamic DNAT:@ftpserver'

assuming that the host running the FTP-server has the name ftpserver.

Example 3: If you like to use active FTP directly from fli4l (perhaps with the help of the ftp program from the Tools-package) the firewall has to be prepared, this time in the OUTPUT-chain by using the array PF_output_CT_%:

    PF_OUTPUT_CT_N='1'
    PF_OUTPUT_CT_1='tmpl:ftp HELPER:ftp'

This rule is not necessary if FTP_PF_ENABLE_ACTIVE='yes' is used - see the documentation for the ftp-OPT in the tools-package.

Following is an overview over the existing conntrack-helpers:

Table 3.9: Available Conntrack Helpers In The Packet Filter
Helper Explanation
   
ftp File Transfer Protocol
h323 H.323 (Voice over IP)
irc Internet Relay Chat
pptp PPTP Masquerading (By the use of this module it is possible to run more than one PPTP-Client behind the fli4l router at the same time.)
sip Session Initiation Protocol
sane SANE Network Procotol
snmp Simple Network Management Protocol
tftp Trivial File Transfer Protocol
 

Here is an overview over the variables to configure:

PF_PREROUTING_CT_ACCEPT_DEF
If this variable is set to `yes', default rules are generated that are necessary for proper functioning of the router. By default, you should use `yes' here.

PF_PREROUTING_CT_N PF_PREROUTING_CT_x PF_PREROUTING_CT_x_COMMENT
List of rules that describe which incoming packets are associated with conntrack helpers by the router.

PF_OUTPUT_CT_ACCEPT_DEF
If this variable is set to `yes', default rules are generated that are necessary for proper functioning of the router. By default, you should use `yes' here.

PF_OUTPUT_CT_N PF_OUTPUT_CT_x PF_OUTPUT_CT_x_COMMENT

List of rules that describe which packets generated on the router are associated with conntrack helpers by the router.



Footnotes

... ports.3.2
A port only exists for TCP- and UDP-packets.
... values:3.3
see http://www.sns.ias.edu/~jns/files/iptables_talk/x38.htm for a detailed description
© 2001-2019 The fli4l-Team - 28 April 2019