I was reading a message on the firewall-wizards mailing list recently wherein a fellow wanted to stop all TCP packets
with the SYN and FIN bits set coming into his firewall. This is a desirable thing to do. Here's why: The TCP specification says that a TCP packet has six flag bits SYN, URG, PSH, RST, FIN, ACK (synchronize, urgent, push, reset, finish, and acknowledge). The specification doesn't say what to do when a packet with nonsensical combinations of flags bits arrives. One such combination is SYN and FIN set. This combination indicates the start of communication (SYN set) and the end of communication (FIN set). Clearly, this is not sensible, but bad guys on the network use packets like this to fingerprint your systems on the Internet. Depending on how the system replies to this packet, a bad guy can conjecture what sort of system is on the other end and from that, use known vulnerabilities to attack you. The best thing to do in this case is drop the packet without a reply. I thought this is easy with Darren Reed's IPFilter:
block in quick log proto tcp from any to any flags SF/SF
But as I read on, I found the fellow was doing this on a Linux firewall with iptables. IPFilter doesn't run on Linux, so he can't use IPFilter. The good news is iptables with Linux 2.4.x kernel does allow the inspection of the flag bits in a TCP header. So, I began to think how do you go about doing this with iptables. Hmm. There have been some significant changes with iptables over ipchains and not just in syntax. This is not as easy as it might seem at first blush. Rather than dig out the specification on iptables and delve into it, I decided it was time to look into a program I had had my eye on for some time, fwbuilder.
Vadim Kurland and Vadim Zaliva have written a program called Firewall Builder to make it easy to create and maintain firewall rulesets. Firewall Builder consists of an object-oriented GUI and a set of policy compilers for various firewall platforms, like iptables. In Firewall Builder, a firewall policy is a set of rules; each rule consists of abstract objects that represent real network objects and services (hosts, routers, firewalls, networks, and protocols). Firewall Builder helps firewall administrators maintain a database of objects and allows policy editing using simple drag-and-drop operations. Preferences and object databases are stored in XML format. Once the ruleset is written, Firewall Builder compiles the ruleset into a script that implements the security policy described by the ruleset.
I downloaded the source from http://fwbuilder.sourceforge.netto build the components of Firewall Builder: fwbuilder, fwbuilder iptables compiler, libfwbuilder and libfwbuilder development. I also had to download and build gtkmm-1.2.5 as Firewall Builder requires this. Everything built without a hitch once I had gtkmm-1.2.5 built as well.
To start Firewall Builder, type
This brings up a window showing the objects that come predefined in Firewall Builder. There are standard objects representing the standard services such as TCP and UDP services like telnet and NFS. There are user-defined objects for defining objects of interest to you. I clicked on "Firewall" and then Insert -> Firewall. Now I have a firewall.
At this point I am presented with forms to fill in information about the firewall such as a name. It's very important to name your firewall something meaningful since this name will be used to create other files related to the firewall. Hint: don't use spaces in the name. I fill in that it is a Linux 2.4 firewall and the firewall software, in this case, iptables.
Next, go to the Interfaces tab on the firewall and fill in the network interface names and IP addresses. These are necessary if you have rules that are specific to an interface. In this case, the rule is a global rule and not specific to any interface. After all, you might get probed from the inside by one of your own guys.
Next, I selected some option on the Firewall tab: I set the log level to 'warning' and don't want any sessions open prior to the start of the firewall to be considered valid.
Finally, click "Apply" and I have a firewall named "Demo-Firewall" in the layout viewer. I expand that entry and it has a "Policy" and a "NAT" entry. Before I get into making the "Policy", I need to define the special case I want to guard against. So, I click on open the "Services" in the directory viewer. Then I open "TCP" under the "Services". I want to create an object that represents the specific TCP condition I want to filter out. I pull down Insert -> TCP to create the object. I get a form to fill in that has port information, TCP flags, a name for this object, and commentary fields. I fill in the form with a name of "tcp-syn-fin" and click on the flags SYN and FIN, and then "Apply" to create the object.
Now, I go back to the directory listing and select my firewall "Demo-Firewall" and the "Policy" underneath it. There is a rule numbered '00' with a source, destination, and service set to "Any", an action of "Deny", a time of "Any" and a blank comment. I drag-and-drop my tcp-syn-fin object to the service column and click "Apply". There you have it; from any source to any destination deny tcp-syn-fin any time. I pull down Rules -> Compile. I get the standard sort of dialog box about where I want the result to go. The policy compiles without errors. The output from the compilation look like this:
# This is automatically generated file. DO NOT MODIFY !
# Firewall Builder fwb_iptables v1.0.0
# Generated Mon Feb 25 13:19:29 2002 CST by gsmith1
if [ -x /usr/bin/logger ]; then
logger -p warning "Activating firewall script Demo-Firewall.fw
generated Mon Feb 25 13:19:29 2002 CST by gsmith1"
modprobe ip_conntrack || exit 1
modprobe ip_conntrack_ftp || exit 1
modprobe ip_nat_ftp || exit 1
echo "0" > /proc/sys/net/ipv4/ip_forward
echo "30" > /proc/sys/net/ipv4/tcp_fin_timeout
echo "1800" > /proc/sys/net/ipv4/tcp_keepalive_intvl
iptables -P OUTPUT DROP
iptables -P INPUT DROP
iptables -P FORWARD DROP
cat /proc/net/ip_tables_names | while read table; do
iptables -t $table -L -n | while read c chain rest; do
if test "X$c" = "XChain" ; then
iptables -t $table -F $chain
iptables -t $table -X
ip addr flush dev eth0 scope link
ip addr flush dev eth1 scope link
iptables -A OUTPUT -p tcp ! --syn -m state --state NEW -j LOG
iptables -A OUTPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j LOG
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -A FORWARD -p tcp ! --syn -m state --state NEW -j LOG
iptables -A FORWARD -p tcp ! --syn -m state --state NEW -j DROP
# Rule #0
# Block SYN/FIN TCP packets.
iptables -N RULE_0
iptables -A OUTPUT -p tcp -m state --state NEW -j RULE_0 --tcp-flags ALL SYN,FIN
iptables -A INPUT -p tcp -m state --state NEW -j RULE_0 --tcp-flags ALL SYN,FIN
iptables -A FORWARD -p tcp -m state --state NEW -j RULE_0 --tcp-flags ALL SYN,FIN
iptables -A RULE_0 -j LOG --log-level warning --log-prefix "RULE 0 -- Deny "
iptables -A RULE_0 -j DROP
# Final rules
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
iptables -A FORWARD -j DROP
echo "$FWD" > /proc/sys/net/ipv4/ip_forward
Hmmm. All this from just one rule! Let's look at what this does. The first part including the 'modprobe's log the starting up of the firewall and make sure the necessary kernel modules are loaded. The next four lines dealing with /proc save the current state of IP forwarding, turn IP forwarding off and adjust some TCP parameters. The next three iptables commands set the default policy on the OUTPUT, INPUT, and FORWARD chain to DROP, a good policy to have.
The next bit of shell manipulations clear any previous rules out of all the existing chains so the firewall starts with a clean slate. The next six iptables statements get rid of and log any TCP sessions that exist at the starting of the firewall. Again, this is starting with a clean slate.
Now we get to the crux of the biscuit, as the late Frank Zappa would say, Rule 0. First, iptables creates a new chain called RULE_0. The next three iptables commands append rules to the OUTPUT, FORWARD, and INPUT chains specifying that when a new TCP connection comes in with the SYN and FIN bits set, jump to the chain named RULE_0.
The iptables command sets the warning level (warning) and the message (RULE 0 - Deny) that will go into syslog if the rule is matched. The next iptables command says that a match causes the packet to be unceremoniously dropped. The next three iptables commands are catchall rules in case something might be slipping in that we didn't consider; best to drop those things. The last statement restores the state of IP forwarding.
Wow! All that from one rule! Talk about bang for the buck! This was just setting up one rule; if you had more (and you would in a real world firewall) the rulesets would outweigh the overhead. The important thing to note here is that we were able to abstract the idea of dropping any TCP packets with SYN and FIN set as a policy without getting mired down the intricacies of iptables. This is just like using a compiler write a program instead of assembly language. Just as compilers free us from the hassles of keeping up with registers, storage locations and weird/arcane instructions and lets us abstract our problems at a higher level, Firewall Builder frees us from the hassles of keeping up with similar low level stuff and lets us abstract our security policy at higher level. Just as compilers give us more maintainable code, Firewall Builder gives us more maintainable firewalls.
Check out Firewall Builder at http://fwbuilder.sourceforge.net.