Linux 2.4's Netfilter Dramatically Improves Linux Packet Filtering
Stephen Fromm
stephenf@ns.uoregon.edu
If you've been using Linux's packet-filter ipchains or ipfwadm, you may want
to consider upgrading to kernel 2.4 to gain the advantages of its new packet
filtering system. While 2.4 does contain backward compatibility support for
ipchains and ipfwadm, you can only gain the advantages of the new packet filtering
subsystem by using Netfilter (http://netfilter.kernelnotes.org).
Briefly, a packet-filter is a program that uses a set of rules to determine
how to handle a received (or about-to-be-sent) packet, and each rule describes
specific packet characteristics (e.g., one rule might describe a packet from
outside the UO network that is headed to port 25 on your machine). Each rule
also has a target, specifying what to do with the packet in the event of a match,
either allowing or denying further processing. If a packet fails to match a
specific rule, the default policy for that set of rules dictates how to handle
the packet.
Netfilter's biggest advantage is its ability to maintain "state,"
or knowledge of connections going in and out of the system. Many older firewall
technologies inspect packets individually, without regard to the overall connection
they're a part of. In contrast, Netfilter's "stateful" inspection
is a much more powerful form of packet filtering because it is aware of the
ongoing connection and the state it is in. States that provide connection-tracking
analysis include New, Established, Related, and Invalid. You can see open connections
in /proc/ip_conntrack, e.g.:
tcp 6 431990 ESTABLISHED src=192.168.10.36 dst=192.168.10.13
sport=32922 dport=80 src=192.168.10.13 dst=192.168.10.36 sport=80
dport=32922 [ASSURED] use=1
udp 17 170 src=192.168.10.36 dst=192.168.10.35 sport=32768
dport=53
src=192.168.10.35 dst=192.168.10.36 sport=53 dport=32768 [ASSURED] use=1
tcp 6 431962 ESTABLISHED src=192.168.10.36 dst=192.168.10.13
sport=935 dport=22 src=192.168.10.13 dst=192.168.10.36 sport=22
dport=935 [ASSURED] use=1
Netfilter can use this list of connections as another way of inspecting packets.
Its ability to maintain state makes it much easier to write filtering rules
under 2.4. An obvious example is FTP. Before 2.4, clumsy, complicated rules
had to be written to allow FTP traffic, whereas Netfilter can recognize a related
connection and allow it to pass through. Consider the following example:
# iptables -P INPUT DROP
# iptables -A INPUT -m state Ñstate ESTABLISHED,RELATED \
-i eth0 -s ! 192.168.10.36 -d 192.168.10.36 -j ACCEPT
In this example, we specified a default policy of 'DROP' for anything on the INPUT chain. Next, we accepted anything on the INPUT chain that's part of an existing (or related) connection whose source is anything but the ip address of the destination computer. This takes care of everything: there is no need to write complicated rules to allow DNS, client-based, or other kinds of traffic. To take advantage of this feature, you will want to make sure the appropriate modules are loaded:
# modprobe ip_conntrack
# modprobe ip_conntrack_ftp
Netfilter's modular design allows you to extend its capabilities with other
modules as they become available, or you can write your own (see http://netfilter.kernelnotes.org/unreliable-guides/netfilter-hacking-HOWTO/index.html).
By default, the maximum number of connections that Netfilter will track depends
on the amount of memory available. On my test machine with 256MB, this was 16376.
However, this can be changed with the sysctl interface. The timeout for a given
connection depends on the protocol (TCP, UDP, or ICMP) and, if it's TCP, the
current state of the connection (e.g. SYN_SENT, ESTABLISHED, TIME_WAIT). While
the timeouts cannot be configured at runtime, you can modify the source code
as appropriate (e.g., see the timeouts for TCP state tracking specified in the
file /usr/src/linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c under the variable
tcp_timeouts).
Other Notable Features
Aside from its ability to track connections, Netfilter offers some other interesting
new features, including the ability to match any TCP flag, specify more LOG
options, and limit rules.
Matching TCP flags. You can now match any TCP flag, an operation that
could be useful in detecting certain types of scans. Suppose you're trying to
detect Nmap's XMAS scan, where the FIN, URG, and PSH flags are set. With Netfilter,
you can write a rule to detect it:
# iptables -A INPUT -p tcp -tcp-flags ALL FIN,URG,PSH
\
-j LOG Ñlog-level warning -log-prefix "XMAS scan detected"
We specify that ALL flags should be examined, but only FIN, URG, and PSH should be set. This would then yield the following message to syslog:
Feb 23 17:45:50 bizarro kernel: XMAS scan detected IN+eth) OUT-
MAC=00:10:4b:32:14:4f:00:29:lc:de:12:08:00 src=192.168.10.46
DST=192.268.10.36 LEN=40 TOS=)x00 PREC=)x00 TTL=50 ID=59590 PROTO=TCP
SPT=40862 DPT=27 WINDOW=3072 RES=0X00 URG PSH FIN URGP=0
(For those feeling especially adventurous, there currently is a module in CVS
that attempts to detect a port scan.)
More LOG options. The above example, which uses the target LOG, also
highlights Netfilter's new logging mechanism. Among other options with LOG,
you can specify the log-level (debug, info, notice, warning, etc.) and a prefix
to the log message so as to distinguish one match from others.
Rate limiting. Lastly, Netfilter gives you the ability to limit the
rate at which a packet can match a given rule. Remember, a packet traverses
a chain of rules until it finds a match (or, failing that, follows the default
policy for the chain). Once a match is found, it performs the targeted action.
With the ability to limit the rate that a specific rule can be matched, you
can now say "Once a packet matches this rule n times, stop performing the
targeted action." You can specify the maximum number of matches allowed
per second, minute, hour, or day. You can also specify the maximum burst before
the limit is reached. The default is three matches per hour, with a burst limit
of five. This feature can be used in conjunction with the LOG target to limit
the number of logs generated for a specific match.
This feature may best be highlighted with two examples. Suppose we wanted to block and log NetBIOS traffic, but we don't want to log every NetBIOS packet we receive. We could use a rule such as:
# iptables -A INPUT -1 eth0 - s 128.223.0.0/16 -p udp.tcp --dport 137.139\
-m limit -j LOG --log-level info --log-prefix "Unwanted NetBIOS"
By using the "limit" module, this rule will log the first five NetBIOS
packets and then begin enforcing the limit of three matches per hour. If more
than three NetBIOS packets are received per hour, they will not be logged. This
feature can also be used to limit incoming or outgoing traffic. For example,
we could limit the number of pings we accept:
# iptables -A INPUT -p icmp --icmp-type echo-request
\
-m limit --limit 1/s -j ACCEPT
This rule will be enforced once the limit-burst of five packets is reached.
Afterwards, only one echo-request per second will be accepted. We can change
the limit-burst value with the '--limit-burst' option.
These are just a sample of some of the useful features I've discovered when
working with Netfilter. I encourage you to investigate Netfilter and the advantages
it may have for you over ipchains and ipfwadm.
References
For more information on Netfilter and network security, see:
Below is a list of the modules you can compile in support of Netfilter when
compiling Linux 2.4 (this is from 2.4.2).
CONFIG_IP_NF_MATCH_LIMIT - allows you to control
the rate at which a rule can be matched. Mainly useful in combination with the
LOG target (see "LOG target support" below) and to avoid some Denial
of Service attacks.
CONFIG_IP_NF_MATCH_MAC - allows you to match packets
based on the source ethernet address of the packet.
CONFIG_IP_NF_MATCH_MARK - allows you to match
packets based on the 'nfmark' value in the packet. This can be set by the MARK
target (see below).
CONFIG_IP_NF_MATCH_TOS - allows you to match packets
based on the Type Of Service fields of the IP packet.
CONFIG_IP_NF_MATCH_STATE - allows you to match
packets based on their relationship to a tracked connection (i.e. previous packets).
This is a powerful tool for packet classification.
CONFIG_IP_NF_MATCH_UNCLEAN - matches any strange
or invalid packets by looking at a series of fields in the IP, TCP, UDP and
ICMP headers.
CONFIG_IP_NF_MATCH_OWNER - allows you to match
locally generated packets based on who created them: the user, group, process
or session.
CONFIG_IP_NF_FILTER - packet filtering defines
a table 'filter', which has a series of rules for simple packet filtering at
local input, forwarding and local output. See the man page for iptables(8)
CONFIG_IP_NF_TARGET_REJECT - the REJECT target
allows a filtering rule to specify that an ICMP error should be issued in response
to an incoming packet, rather than silently being dropped.
CONFIG_IP_NF_TARGET_MIRROR - the MIRROR target
allows a filtering rule to specify that an incoming packet should be bounced
back to the sender.
CONFIG_IP_NF_TARGET_MASQUERADE - all outgoing
connections are changed to look as if they come from a particular interface's
address, and if the interface goes down, those connections are lost. This is
only useful for dialup accounts with dynamic IP address (i.e. your IP address
will be different on next dialup).
CONFIG_IP_NF_TARGET_REDIRECT - all incoming connections
are mapped onto the incoming interface's address, causing the packets to come
to the local machine instead of passing through. This is useful for transparent
proxies.
CONFIG_IP_NF_MANGLE - adds a 'mangle' table to
iptables: see the man page for iptables(8). This table is used for various packet
alterations which can effect how the packet is routed.
CONFIG_IP_NF_TARGET_TOS - adds a 'TOS' target,
which allows you to create rules in the 'mangle' table that alter the Type Of
Service field of an IP packet prior to routing.
CONFIG_IP_NF_TARGET_MARK - adds a 'MARK' target,
allowing you to create rules in the 'mangle' table that alter the netfilter
mark (nfmark) field associated with the packet prior to routing. This can change
the routing method (see "IP: use netfilter MARK value as routing key")
and can also be used by other subsystems to change their behavior.
CONFIG_IP_NF_TARGET_LOG - adds a 'LOG' target, which allows you to create rules in any iptables table that records the packet header to the syslog.