Using Firewall Builder, Part II
After you've finished your firewall policy, you need to convert it to an actual iptables script. To do so, first make sure that on the screen's left-hand hierarchy view your firewall's object, its global policy or one of its interface policies is selected—it doesn't matter which. Then, pull down the Rules menu and select Compile. Figure 3 shows the result.
Upon successful policy compiling, Firewall Builder writes a file whose name consists of the name of the firewall object whose policy you compiled and the suffix .fw. The example script we produced, trillian.fw, is shown in Listing 1. Listing 1 has been modified slightly due to space requirements, and some housekeeping material has been removed. All of the actual rules mentioned in the article are present.
This script now can be copied over manually to Trillian and run as is, or it can be converted manually into a startup script appropriate to Trillian's Linux distribution, for example, a standard Red Hat 7.3 startup script. Easier still, you can copy it over automatically and activate it with a Firewall Builder installer script such as fwb_install, available under contrib at sourceforge.net/project/showfiles.php?group_id=5314.
The latter in particular is an elegant and simple way to copy and activate your firewall scripts securely; fwb_install uses scp to copy the script to /etc/firewall on the remote host and then ssh to execute the script remotely. If you've downloaded fwb_install somewhere on your Firewall Builder system, you can configure Firewall Builder to use it from within each firewall object's Compile/Install properties.
Be sure to tweak fwb_install manually to match your system settings and to set up SSH keys for fwb_install to use. Once you've set this up, all you need to do to install your policies after compiling them is pull down the Rules menu and select Install.
As handy as fwb_install is, you'll want a startup script in place on your target system that also executes the firewall script on startup and after any reboot. Otherwise, the system is vulnerable between each startup or reboot and the next time you execute Install from within Firewall Builder. It's easy to copy and adapt existing scripts in your system's /etc/init.d directory.
I've devoted most of this column to the bastion host example, but building a policy for a multihomed (multi-interfaced) network firewall is quite similar. Create loopback policies, create anti-spoofing policies for the other interfaces, create a global policy, compile the policy and install it.
The big differences have to do with the fact that a firewall, unlike a server, has multiple network interfaces. Because a single-interfaced system receives all packets except loopback at one physical point, it can't distinguish spoofed packets from legitimate packets; it must take each packet's source-IP address at face value. But a multihomed system can distinguish easily between packets that truly originate from local networks and packets that arrive from the Internet but have forged source-IP addresses matching a local or trusted network.
For instance, our example internal network is numbered 192.168.111.0 (subnet mask 255.255.255.0). If we have a firewall named Slartibartfast between this network and the rest of the world, we can use anti-spoofing rules to tell Slartibartfast to drop any packet immediately from any interface other than the one facing our internal network, if that packet has a source IP beginning with 192.168.111. Such a packet is obviously spoofed. Figure 4 shows Slartibartfast's anti-spoofing rule.
Before I made this rule, I created several network objects that refer to the reserved IP address spaces defined in RFC 1918, “Address Allocation for Private Internets”. RFC 1918 address spaces are for use only within an organization and can't be routed over the Internet, so any internet firewall should consider inbound packets bearing such addresses to be spoofed, which is precisely what the rule in Figure 4 does. Because my RFC 1918 Class C object expands to 192.168.0.0, subnet mask 255.255.0.0 and my internal network address is 192.168.111.0 (part of RFC 1918 address space), it wasn't necessary to include my Net_Internal object in this rule.
By the way, if you're not familiar with RFC 1918, my RFC 1918 Class A object refers to 10.0.0.0, subnet mask 255.0.0.0, and RFC 1918 Class B is 172.16.0.0, subnet mask 255.240.0.0.