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 that it's supposed to? You may not have done this because you think it will take too long or be too difficult. Luckily there's ftester (http://ftester.sourceforge.net), 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 is ftestd, which listens for the packets injected with ftest that come through the firewall that you are testing. This script should be run 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.
The general form for a TCP or UDP packet in ftest.conf is:
source addr:source port:dest addr:dest port:flags:proto:tos
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. Address ranges can be specified in the low-high format or by using CIDR notation. Port ranges can be specified using the low-high format as well. The flags field is where you specify the TCP 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 the Type-of-Service (ToS) field in the IP header to. Sometimes routers will 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 Internet Protocol.
ICMP packets can be defined in a similar manner. Here's the general form for one:
source addr::dest addr:::ICMP:type:code
Here you can see that the main difference between the two forms is the omission of port numbers and flags. This is because ICMP does not use port numbers and does not make use of flags. Instead, it uses types and codes, hence the addition of the type and code fields. Currently, there are over 40 ICMP types. Some that may be familiar to you are 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). ICMP codes are like subclassifications of an ICMP type. Not all ICMP types have ICMP codes associated with them, although there are roughly the same number of ICMP codes as there are types. You can find out more about ICMP types and codes by reading the IANA's assignments for them (see http://www.iana.org/assignments/icmp-parameters).
Here's an ftest.conf that will check all of the unprivileged TCP ports on a machine with the IP address 10.1.1.1:
The stop_signal creates a payload for the packet that will tell ftestd that the testing is over.
Before starting ftest, you should start ftestd:
# ./ftestd -i eth0
Now, to run ftest:
# ./ftest -f ftest.conf
This will create 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 be dropped by the firewall since 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 it to. 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 kind of traffic is permitted.