14.2. Firewall or Packet Filtering
A firewall is a filtering network gateway and is only effective on packets that must go through it. Therefore, it can only be effective when going through the firewall is the only route for these packets.
The lack of a standard configuration (and the “process, not product” motto) explains the lack of a turn-key solution. There are, however, tools that make it simpler to configure the netfilter firewall, with a graphical representation of the filtering rules. fwbuilder
is undoubtedly among the best of them.
The Linux kernel embeds the netfilter firewall. It can be controlled from user-space with the iptables
and ip6tables
commands. The difference between these two commands is that the former acts on the IPv4 network, whereas the latter acts on IPv6. Since both network protocol stacks will probably be around for many years, both tools will need to be used in parallel.
14.2.1. Netfilter Behavior
netfilter uses four distinct tables which store rules regulating three kinds of operations on packets:
filter
concerns filtering rules (accepting, refusing or ignoring a packet);
nat
concerns translation of source or destination addresses and ports of packages; note that this table only exists for IPv4;
mangle
concerns other changes to the IP packets (including the ToS — Type of Service — field and options);
raw
allows other manual modifications on packets before they reach the connection tracking system.
Each table contains lists of rules called chains. The firewall uses standard chains to handle packets based on predefined circumstances. The administrator can create other chains, which will only be used when referred to by one of the standard chains (either directly or indirectly).
The filter
table has three standard chains:
INPUT
: concerns packets whose destination is the firewall itself;
OUTPUT
: concerns packets emitted by the firewall;
FORWARD
: concerns packets transiting through the firewall (which is neither their source nor their destination).
The nat
table also has three standard chains:
PREROUTING
: to modify packets as soon as they arrive;
POSTROUTING
: to modify packets when they are ready to go on their way;
OUTPUT
: to modify packets generated by the firewall itself.
Each chain is a list of rules; each rule is a set of conditions and an action to execute when the conditions are met. When processing a packet, the firewall scans the appropriate chain, one rule after another; when the conditions for one rule are met, it “jumps” (hence the -j
option in the commands) to the specified action to continue processing. The most common behaviors are standardized, and dedicated actions exist for them. Taking one of these standard actions interrupts the processing of the chain, since the packet's fate is already sealed (barring an exception mentioned below):
ACCEPT
: allow the packet to go on its way;
REJECT
: reject the packet with an ICMP error packet (the --reject-with type
option to iptables
allows selecting the type of error);
DROP
: delete (ignore) the packet;
LOG
: log (via syslogd
) a message with a description of the packet; note that this action does not interrupt processing, and the execution of the chain continues at the next rule, which is why logging refused packets requires both a LOG and a REJECT/DROP rule;
ULOG
: log a message via ulogd
, which can be better adapted and more efficient than syslogd
for handling large numbers of messages; note that this action, like LOG, also returns processing to the next rule in the calling chain;
chain_name: jump to the given chain and evaluate its rules;
RETURN
: interrupt processing of the current chain, and return to the calling chain; in case the current chain is a standard one, there's no calling chain, so the default action (defined with the -P
option to iptables
) is executed instead;
SNAT
(only in the nat
table, therefore only in IPv4 on Wheezy — NAT support for IPv6 appeared in the Linux 3.7 kernel): apply Source NAT (extra options describe the exact changes to apply);
DNAT
(only in the nat
table, therefore only in IPv4 on Wheezy): apply Destination NAT (extra options describe the exact changes to apply);
MASQUERADE
(only in the nat
table, therefore only in IPv4 on Wheezy): apply masquerading (a special case of Source NAT);
REDIRECT
(only in the nat
table, therefore only in IPv4 on Wheezy): redirect a packet to a given port of the firewall itself; this can be used to set up a transparent web proxy that works with no configuration on the client side, since the client thinks it connects to the recipient whereas the communications actually go through the proxy.
Other actions, particularly those concerning the mangle
table, are outside the scope of this text. The iptables(8) and ip6tables(8) have a comprehensive list.
14.2.2. Syntax of iptables
and ip6tables
The iptables
and ip6tables
commands allow manipulating tables, chains and rules. Their -t table
option indicates which table to operate on (by default, filter
).
The -N chain
option creates a new chain. The -X chain
deletes an empty and unused chain. The -A chain rule
adds a rule at the end of the given chain. The -I chain rule_num rule
option inserts a rule before the rule number rule_num. The -D chain rule_num
(or -D chain rule
) option deletes a rule in a chain; the first syntax identifies the rule to be deleted by its number, while the latter identifies it by its contents. The -F chain
option flushes a chain (deletes all its rules); if no chain is mentioned, all the rules in the table are deleted. The -L chain
option lists the rules in the chain. Finally, the -P chain action
option defines the default action, or “policy”, for a given chain; note that only standard chains can have such a policy.
Each rule is expressed as conditions -j action action_options
. If several conditions are described in the same rule, then the criterion is the conjunction (logical and) of the conditions, which is at least as restrictive as each individual condition.
The -p protocol
condition matches the protocol field of the IP packet. The most common values are tcp
, udp
, icmp
, and icmpv6
. Prefixing the condition with an exclamation mark negates the condition, which then becomes a match for “any packets with a different protocol than the specified one”. This negation mechanism is not specific to the -p
option and it can be applied to all other conditions too.
The -s address
or -s network/mask
condition matches the source address of the packet. Correspondingly, -d address
or -d network/mask
matches the destination address.
The -i interface
condition selects packets coming from the given network interface. -o interface
selects packets going out on a specific interface.
There are more specific conditions, depending on the generic conditions described above. For instance, the -p tcp
condition can be complemented with conditions on the TCP ports, with clauses such as --source-port port
and --destination-port port
.
The --state state
condition matches the state of a packet in a connection (this requires the ipt_conntrack
kernel module, for connection tracking). The NEW
state describes a packet starting a new connection; ESTABLISHED
matches packets belonging to an already existing connection, and RELATED
matches packets initiating a new connection related to an existing one (which is useful for the ftp-data
connections in the “active” mode of the FTP protocol).
The previous section lists available actions, but not their respective options. The LOG
action, for instance, has the following options:
--log-priority
, with default value warning
, indicates the syslog
message priority;
--log-prefix
allows specifying a text prefix to differentiate between logged messages;
--log-tcp-sequence
, --log-tcp-options
and --log-ip-options
indicate extra data to be integrated into the message: respectively, the TCP sequence number, TCP options, and IP options.
The DNAT
action provides the --to-destination address:port
option to indicate the new destination IP address and/or port. Similarly, SNAT
provides --to-source address:port
to indicate the new source IP address and/or port.
The REDIRECT
action (only available if NAT is available — on Wheezy, this means IPv4 only) provides the --to-ports port(s)
option to indicate the port, or port range, where the packets should be redirected.
Each rule creation requires one invocation of iptables
/ip6tables
. Typing these commands manually can be tedious, so the calls are usually stored in a script so that the same configuration is set up automatically every time the machine boots. This script can be written by hand, but it can also be interesting to prepare it with a high-level tool such as fwbuilder
.
The principle is simple. In the first step, one needs to describe all the elements that will be involved in the actual rules:
the firewall itself, with its network interfaces;
the networks, with their corresponding IP ranges;
the servers;
the ports belonging to the services hosted on the servers.
The rules are then created with simple drag-and-drop actions on the objects. A few contextual menus can change the condition (negating it, for instance). Then the action needs to be chosen and configured.
As far as IPv6 is concerned, one can either create two distinct rulesets for IPv4 and IPv6, or create only one and let fwbuilder
translate the rules according to the addresses assigned to the objects.
fwbuilder
can then generate a script configuring the firewall according to the rules that have been defined. Its modular architecture gives it the ability to generate scripts targeting different systems (iptables
for Linux, ipf
for FreeBSD and pf
for OpenBSD).
Versions of the fwbuilder package since Squeeze contain both the graphical interface and the modules for each firewall system (these were previously split over several packages, one for each target system):
#
aptitude install fwbuilder
14.2.4. Installing the Rules at Each Boot
If the firewall is meant to protect an intermittent PPP network connection, the simplest way to deploy the script is to install it as /etc/ppp/ip-up.d/0iptables
(note that only files without a dot in their name are taken into account). The firewall will thus be reloaded every time a PPP connection is established.
In other cases, the recommended way is to register the configuration script in an up
directive of the /etc/network/interfaces
file. In the following example, the script is stored under /usr/local/etc/arrakis.fw
.
Example 14.1. interfaces
file calling firewall script
auto eth0
iface eth0 inet static
address 192.168.0.1
network 192.168.0.0
netmask 255.255.255.0
broadcast 192.168.0.255
up /usr/local/etc/arrakis.fw