Mastering ipfwadm: Hardening Linux 2.0.x Firewalls
You just installed Slackware or Red Hat 5.0, and you're feeling good. But as soon as that 56k modem or ISDN line is up, you're visible. In 1998, with the number of 'WinNuke' and 'Ping of Death' attacks on the rise, you cannot rely on defaults. On the Linux 2.0.x kernel series, our primary weapon is ipfwadm.
Forget the upcoming ipchains or the rumored iptables for the 2.2 kernel; we need security today. The philosophy is simple: deny everything by default, and only punch the holes you need.
The Default Deny Strategy
First, flush all your current rules and set the default policy to deny. This is the hallmark of a professional sysadmin. If you don't do this, you're not running a firewall; you're running a suggestion engine.
# Flush all rules
ipfwadm -I -f
ipfwadm -O -f
ipfwadm -F -f
# Set default policy: DENY everything
ipfwadm -I -p deny
ipfwadm -O -p accept
ipfwadm -F -p deny
Allowing the Essentials
You need to talk to yourself, so allow the loopback interface (lo). Then, allow your DNS lookups and web traffic. Remember, in 1998, we mostly care about TCP/UDP ports.
# Allow loopback
ipfwadm -I -a accept -W lo
# Allow DNS (UDP port 53)
ipfwadm -I -a accept -P udp -S 0.0.0.0/0 53 -D 0.0.0.0/0 1024:65535
# Allow incoming HTTP traffic to your web server
ipfwadm -I -a accept -P tcp -D 192.168.1.1 80
IP Masquerading (NAT)
If you're using your Linux box as a gateway for your home or office LAN, you'll need IP Masquerading. This allows your internal machines with private IPs (like 192.168.x.x) to reach the outside world through your single public IP.
# Enable Masquerading for the local subnet
ipfwadm -F -a masquerade -S 192.168.1.0/24 -D 0.0.0.0/0
Watching for Probes
Use the -l flag to log every packet that hits a deny rule. This will fill your /var/log/messages pretty fast, but it's the only way to see who's scanning your ports. When you see a repeat offender, you can manually block their entire CIDR block.
Remember, ipfwadm is stateless. It doesn't know if a packet is part of an existing connection. This makes it vulnerable to certain types of spoofing and ACK scans. You have to be surgical with your port ranges and source/destination combinations. Keep your rc.firewall script simple and readable.