Quick iptables firewall script

Here's a quick shell script to configure iptables to provide a firewall.

This could be done using iptables-save once the firewall is configured and iptables-restore to reload it, but I prefer it this way, as I find it easier to edit.

I generally save the script as /etc/rc.d/rc.firewall.

Obviously change the paths etc to suit your system.

#!/bin/bash
 
IPT=/usr/sbin/iptables
IFCONFIG=/sbin/ifconfig
 
# ugly way to get our IP:
IP=`$IFCONFIG eth0 | grep 'inet addr:' | cut -d ':' -f 2 | cut -d ' ' -f 1`
 
echo "Firewall configuration.........."
echo "My IP: '$IP'"
 
# flush all chains
for CHAIN in INPUT OUTPUT FORWARD; do $IPT -F $CHAIN; done;
 
# set default policies:
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT ACCEPT
 
# security settings:
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 1 > /proc/sys/net/ipv4/icmp_ratelimit
echo 0 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
 
# these need to be set individually per interface.. you could just
# set them only for your external interface if you prefer.
for IFACE in /proc/sys/net/ipv4/conf/*; do
    echo 0 > $IFACE/accept_source_route
    echo 0 > $IFACE/accept_redirects
done;
 
 
echo '..... allowing everything from localhost'
$IPT -A INPUT -p tcp -s 127.0.0.1 -j ACCEPT
$IPT -A INPUT -p udp -s 127.0.0.1 -j ACCEPT
 
 
echo '..... allowing return traffic'
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
 
 
# add your own custom rules here #
 
 
################################################################
## drop icmp (except some which we should accept)
echo '..... allowing certain ICMP types, dropping rest'
$IPT -A INPUT -p icmp --icmp-type 0 -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type 3 -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type 11 -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type 8 -m limit --limit 3/second -j ACCEPT
$IPT -A INPUT -p icmp -j DROP
 
# drop NetBIOS shite:
$IPT -A INPUT -p udp --dport 137:139 -j DROP
$IPT -A INPUT -p tcp --dport 137:139 -j DROP
 
 
 
################################################################
## drop attempted attacks always:
# these are TCP flag combinations which should never, ever occur
# in the wild.  These are illegal combinations which most likely
# indicate an attempted attack on us.
echo '..... dropping invalid TCP flags'
$IPT -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
$IPT -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
$IPT -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
$IPT -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
$IPT -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
$IPT -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
 
# log and deny anything that's left:
$IPT -A INPUT -p all -s 0/0 -j LOG --log-prefix 'firewall: '
 
 
echo "Firewall configuration complete."

The security settings above tweak some kernel settings to improve security slightly. Below is a brief explanation, but see http:www.securityfocus.com/infocus/1711 for a lot more detail. * enabling icmp_echo_ignore_broadcasts stops this host responding to broadcast pings - useful to stop us being used as an unwitting participant in smurf attacks (but sometimes broadcast pings may be useful) * icmp_ratelimit limits the amount of ICMP messages we'll respond to * disabling accept_source_route - When source routed packets are allowed, an attacker can forge the source IP address of connections by explicitly saying how a packet should be routed across the Internet. This could enable them to abuse trust relationships or get around TCP Wrapper-style access lists. There's no need for source routing on today's Internet. * disabling ip_forward stops us forwarding packets between interfaces. Unless this machine is acting as a router, this is not something we want to be doing. * disabling accept_redirects stops us accepting ICMP redirect messages, which a cracker can use ICMP redirects to trick you into sending your packets through a machine it controls to perform man-in-the-middle attacks. * tcp_syncookies can prevent a very popular denial of service attack involving a cracker sending many (possibly forged) SYN packets to your server, but never completing the TCP three way handshake, using up slots in the kernel's half open queue, preventing legitimate connections from succeeding. (see: http:cr.yp.to/syncookies.html)

Resolving hostnames

If you want to resolve hostnames within the firewall script in order to get the IP address to use for the rule, you can use the following snippet:

# simple function to resolve hostname to IP address:
resolve() {
echo $( $HOST $1 | grep 'address' | cut -d ' ' -f 4 );
}

Whack that in the script near the top, then you can use it like:

$IPT -A INPUT -p tcp --dport 22 -s $(resolve('host.example.com')) -j ACCEPT

Hmm, writing this made me think about it... I'm not sure why I do it like this, as iptables can resolve it for you if you just use -s host.example.com - it should resolve that hostname to an IP as the rule is created.

The main benefit I guess is the fact I normally test for whether it worked, I tend to use something like:

IP=$(resolve host.example.com)
 
if [ "$IP" ]; then
    # set up the rules using that IP
else
    # failed to resolve it, take appropriate action
fi

~~DISCUSSION~~

 
iptables.txt · Last modified: 2010/02/26 10:45 (external edit)
 
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki