Hack #51. Test Your Firewall

Find out if your firewall really works the way you think it should.

So, you’ve set up a firewall and done a few cursory tests to make sure it’s working, but have you tested the firewall to be sure that it’s blocking everything it’s supposed to? You might not have done this because you think it will take too long or be too difficult. Luckily, there’s FTester (http://dev.inversepath.com/trac/ftester/), a free tool for doing extensive firewall tests.

FTester consists of three Perl scripts. The ftest script is used for injecting custom packets as defined in the configuration file ftest.conf. If you are testing how the firewall behaves with ingress traffic, you should run this script on a machine outside of your firewalled network. If you want to test your firewall’s behavior toward egress traffic, you will need to run ftest from a machine within your firewall’s protected network.

One of the other scripts, ftestd, listens for the packets injected with ftest that come through the firewall that you are testing. You should run this script on a machine within your internal network if you are testing the firewall’s ingress behavior. If you are testing egress behavior, you’ll need to run it on a machine external to your network. Both of these scripts keep a log of what they send or receive. After a test run, their respective logs can be compared using the freport script, to quickly see what packets were able to get through the firewall.

Before you can use FTester, you will need the Net::RawIP , Net::PcapUtils, and NetPacket Perl modules. You will also need the Net::Pcap module if it is not already installed, since the Net::PcapUtils module depends on it. If you have the CPAN Perl module available, you can install these modules with the following commands:

# perl -MCPAN -e "install Net::RawIP"
# perl -MCPAN -e "install Net::PcapUtils"
# perl -MCPAN -e "install NetPacket"
         

Once these modules are available on the systems you will be using to conduct your firewall test, you will need to create a configuration file to tell ftest what packets it should generate.

Here’s the general form for a TCP or UDP packet in ftest.conf, where source addr and source port are the source IP address and port, and dest addr and dest port are the destination IP address and port:

            source addr:source port:dest addr:dest port:flags:proto:tos
         

Address ranges can be specified in the low - high format or by using CIDR notation. You can also specify port ranges using the low - high format. The flags field is where you specify the TCP flags that you want set for the packet. Valid values for this field are S for SYN, A for ACK, P for PSH, U for URG, R for RST, and F for FIN. The proto field specifies which protocol to use (either TCP or UDP), and tos contains the number to set for the Type-of-Service (ToS) field in the IP header. Sometimes, routers use the contents of this field to make decisions about traffic prioritization. You can get more information on the ToS field by reading RFC 791 (http://www.ietf.org/rfc/rfc0791.txt), which defines the Internet Protocol.

You can define ICMP packets in a similar manner. Here’s the general form for one:

            source addr::dest addr:::ICMP:type:code
         

As you can see, the main difference between the two forms is the omission of port numbers and flags, which ICMP does not use. Instead, it uses types and codes (hence the addition of the type and code fields). Currently, there are over 40 ICMP types. The ones used by the ping utility, echo (type 8) and echo reply (type 0), or the type used by the traceroute command (type 30), might be familiar to you. ICMP codes are like subclassifications of ICMP types. Not all ICMP types have ICMP codes associated with them, although there are roughly the same number of ICMP codes as types. You can find out more about ICMP types and codes by reading the Internet Assigned Numbers Authority’s assignments for them at http://www.iana.org/assignments/icmp-parameters.

Here’s an ftest.conf that will check all of the privileged TCP ports on a machine with the IP address 10.1.1.1:

192.168.1.10:1025:10.1.1.1:1-1024:S:TCP:0
stop_signal=192.168.1.10:1025:10.1.1.1:22:S:TCP:0

stop_signal creates a payload for the packet that will tell ftestd that the testing is over. For quick tests, you can use the -c option and specify a packet to send using the syntax described previously. For instance, the following command sends a packet with the source IP address and port of 192.168.1.10:1025 to port 22 on 10.1.1.1.1:

# ./ftest -c 192.168.1.10:1025:10.1.1.1:22:S:TCP:0
         

Before starting ftest, you should start ftestd:

# ./ftestd -i eth0
         

Then, run ftest:

# ./ftest -f ftest.conf
         

This command creates a log file called ftest.log containing an entry for every packet ftest sent. When ftestd receives the signal to stop, it will exit. You can then find its log of what packets it received in ftestd.log.

Now, you can copy the logs to the same machine and run them through freport. If you used a configuration file like the one shown earlier and were allowing SSH, SMPTP, and HTTP traffic, you might get a report similar to this:

# ./freport ftest.log ftestd.log

Authorized packets:
-------------------

22 - 192.168.1.10:1025 > 10.1.1.1:22 S TCP 0
25 - 192.168.1.10:1025 > 10.1.1.1:25 S TCP 0
80 - 192.168.1.10:1025 > 10.1.1.1:80 S TCP 0

Modified packets (probably NAT):
--------------------------------

Filtered or dropped packets:
----------------------------

1 - 192.168.1.10:1025 > 10.1.1.1:1 S TCP 0
2 - 192.168.1.10:1025 > 10.1.1.1:2 S TCP 0
3 - 192.168.1.10:1025 > 10.1.1.1:3 S TCP 0

If you are using a stateful firewall and want to test this functionality, you can also specify packets that have flags other than SYN set. For instance, if the previous example had used ACK or some other flag instead of SYN, it would have been dropped by the firewall because only packets with the SYN flag set are used to initiate connections.

It’s a good idea to run ftest each time you make changes to your firewall, or periodically just to make sure that your firewall works as you expect. While complex rulesets on your firewall can sometimes make it difficult to predict exactly how it will behave, ftest will tell you with good authority exactly what kinds of traffic are permitted.