Tutorial Home‎ > ‎

Creating a Linux Firewall using IPTables

IPTables is one of the most popular and powerful Firewall/Routing solutions available for the Linux kernel. This article will cover a basic setup and configuration of IPTables for most generic GNU/Linux distributions. The distribution(s) of choice here at Section6 happen to be


Requirements

A computer with a 586 processor or higher, 128mb of RAM, two network interfaces, and a 2GB or larger hard drive

A working GNU/Linux distribution installed on the computer running the 2.6 kernel

Configuring the kernel:

You will need to add the following options to your kernel configuration file (Note: Debian based ditros like Ubuntu come with these options already preconfigured):

#
# IP: Netfilter Configuration
#
CONFIG_IP_NF_CONNTRACK=y
CONFIG_IP_NF_CT_ACCT=y
CONFIG_IP_NF_CONNTRACK_MARK=y
CONFIG_IP_NF_CT_PROTO_SCTP=y
CONFIG_IP_NF_FTP=y
CONFIG_IP_NF_IRC=y
CONFIG_IP_NF_TFTP=y
CONFIG_IP_NF_AMANDA=y
CONFIG_IP_NF_QUEUE=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_LIMIT=y
CONFIG_IP_NF_MATCH_IPRANGE=y
CONFIG_IP_NF_MATCH_MAC=y
CONFIG_IP_NF_MATCH_PKTTYPE=y
CONFIG_IP_NF_MATCH_MARK=y
CONFIG_IP_NF_MATCH_MULTIPORT=y
CONFIG_IP_NF_MATCH_TOS=y
CONFIG_IP_NF_MATCH_RECENT=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_DSCP=y
CONFIG_IP_NF_MATCH_AH_ESP=y
CONFIG_IP_NF_MATCH_LENGTH=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_MATCH_TCPMSS=y
CONFIG_IP_NF_MATCH_HELPER=y
CONFIG_IP_NF_MATCH_STATE=y
CONFIG_IP_NF_MATCH_CONNTRACK=y
CONFIG_IP_NF_MATCH_OWNER=y
CONFIG_IP_NF_MATCH_ADDRTYPE=y
CONFIG_IP_NF_MATCH_REALM=y
CONFIG_IP_NF_MATCH_SCTP=y
CONFIG_IP_NF_MATCH_COMMENT=y
CONFIG_IP_NF_MATCH_CONNMARK=y
CONFIG_IP_NF_MATCH_HASHLIMIT=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_TARGET_LOG=y
CONFIG_IP_NF_TARGET_ULOG=y
CONFIG_IP_NF_TARGET_TCPMSS=y
CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_SAME=y
CONFIG_IP_NF_NAT_LOCAL=y
CONFIG_IP_NF_NAT_SNMP_BASIC=y
CONFIG_IP_NF_NAT_IRC=y
CONFIG_IP_NF_NAT_FTP=y
CONFIG_IP_NF_NAT_TFTP=y
CONFIG_IP_NF_NAT_AMANDA=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_TARGET_TOS=y
CONFIG_IP_NF_TARGET_ECN=y
CONFIG_IP_NF_TARGET_DSCP=y
CONFIG_IP_NF_TARGET_MARK=y
CONFIG_IP_NF_TARGET_CLASSIFY=y
CONFIG_IP_NF_TARGET_CONNMARK=y
CONFIG_IP_NF_TARGET_CLUSTERIP=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_TARGET_NOTRACK=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y


Alternately if you prefer to use the menu-based kernel configuration utility, you would find these options under the following sections:

Device Drivers  --->
|_Networking support  --->
  |_Networking options  --->
    |_Network packet filtering --->
      |_IP: Netfilter Configuration  --->
        <*> Connection tracking (required for masq/NAT)                   
        [*]   Connection tracking flow accounting                        
        [*] Connection mark tracking support                              
        <*> SCTP protocol connection tracking support (EXPERIMENTAL)      
        <*> FTP protocol support                                          
        <*> IRC protocol support                                          
        <*> TFTP protocol support                                         
        <*> Amanda backup protocol support                                
        <*> Userspace queueing via NETLINK                                
        <*> IP tables support (required for filtering/masq/NAT)           
        <*>   limit match support                                         
        <*>   IP range match support                                      
        <*>   MAC address match support                                   
        <*>   Packet type match support                                   
        <*>   netfilter MARK match support                                
        <*>   Multiple port match support                                 
        <*>   TOS match support                                           
        <*>   recent match support                                        
        <*>   ECN match support                                           
        <*>   DSCP match support                                          
        <*>   AH/ESP match support                                        
        <*>   LENGTH match support                                        
        <*>   TTL match support                                           
        <*>   tcpmss match support                                        
        <*>   Helper match support                                        
        <*>   Connection state match support                              
        <*>   Connection tracking match support                           
        <*>   Owner match support                                         
        <*>   address type match support                                  
        <*>   realm match support                                         
        <*>   SCTP protocol match support                                 
        <*>   comment match support                                       
        <*>   Connection mark match support                               
        <*>   hashlimit match support                                     
        <*>   Packet filtering                                            
        <*>     REJECT target support                                     
        <*>   LOG target support                                          
        <*>   ULOG target support                                         
        <*>   TCPMSS target support                                       
        <*>   Full NAT                                                    
        <*> MASQUERADE target support                                     
        <*> REDIRECT target support                                       
        <*> NETMAP target support                                         
        <*> SAME target support                                           
        [*] NAT of local connections (READ HELP)                          
        <*> Basic SNMP-ALG support (EXPERIMENTAL)


Once the kernel has been compiled and installed with these options, it is time to install the IPTables package.

In Debian we would simply apt-get install iptables, where as in Gentoo we need to emerge iptables from the portage tree.

After the iptables package has been installed, we need to make sure that IP forwarding is enabled in the kernel (note: if you are not using your computer as a router/NAT then you do not need IP forwarding)

IP forwarding is enabled by simply adding the following line to /etc/sysctl.conf:

#Enable packet forwarding
net.ipv4.ip_forward = 1

Configuring a ruleset

The following example shell script creates a basic ruleset that allows all traffic out from an internal network and only a couple of ports inbound. This script should be created and saved in a convenient and accessible place like /usr/local/sbin. Name this script whatever you would like to call it, like maybe firewall.sh

#!/bin/sh
IPTABLES='/sbin/iptables'

# Set interface values
EXTIF='eth0'
INTIF='eth1'

# enable ip forwarding in the kernel
/bin/echo 1 > /proc/sys/net/ipv4/ip_forward

# flush rules and delete chains
$IPTABLES -F
$IPTABLES -X

#Enable masquerading to allow LAN internet access
$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE

#Forward LAN traffic from LAN $INTIF to Internet $EXTIF
$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -m state --state NEW,ESTABLISHED -j ACCEPT

#Allowing access to the SSH server"
$IPTABLES -A INPUT --protocol tcp --dport 22 -j ACCEPT

#Allowing access to the HTTP server"
$IPTABLES -A INPUT --protocol tcp --dport 80 -j ACCEPT

# block out all other Internet access on $EXTIF
$IPTABLES -A INPUT -i $EXTIF -m state --state NEW,INVALID -j DROP
$IPTABLES -A FORWARD -i $EXTIF -m state --state NEW,INVALID -j DROP

#Redirect TCP port 25 to another internal computer
$IPTABLES -A FORWARD -i $EXTIF -d 10.0.0.5 -p tcp --dport 25 -j ACCEPT
$IPTABLES -t nat -A PREROUTING -i $EXTIF -p tcp --dport 25 -j DNAT --to-destination 10.0.0.6:25

This script assumes that we are using eth0 for our external interface and eth1 for the internal interface. If you have a different setup then adjust the script accordingly and change theEXTIF and INTIF values.

Once this is done, we need to setup a startup script for IPtables. We can do this by creating and editing a file called /etc/init.d/iptables.

#!/bin/sh
#
#This is a ubuntu adapted iptables script from gentoo
#(http://www.gentoo.org) which was originally distributed
# under the terms of the GNU General Public License v2
#and was Copyrighted 1999-2004 by the Gentoo Foundation
#
#This adapted version was intended for and ad-hoc personal
#situation and as such no warranty is provided.
IPTABLES_SAVE="/etc/default/iptables-rules"
SAVE_RESTORE_OPTIONS="-c"
SAVE_ON_STOP="yes"
checkrules() {
if [ ! -f ${IPTABLES_SAVE} ]
then
echo "Not starting iptables. First create some rules then run"
echo "\"/etc/init.d/iptables save\""
return 1
fi
}
save() {
echo "Saving iptables state"
/sbin/iptables-save ${SAVE_RESTORE_OPTIONS} > ${IPTABLES_SAVE}
}
start(){
checkrules || return 1
echo "Loading iptables state and starting firewall"
echo -n "Restoring iptables ruleset"
start-stop-daemon --start --quiet --exec /sbin/iptables-restore -- ${SAVE_RESTOR
E_OPTIONS} < ${IPTABLES_SAVE}
}
case "$1" in
save)
save
echo "."
;;
start)
start
echo "."
;;
stop)
if [ "${SAVE_ON_STOP}" = "yes" ]; then
save || exit 1
fi
echo -n "Stopping firewall"
for a in `cat /proc/net/ip_tables_names`; do
/sbin/iptables -F -t $a
/sbin/iptables -X -t $a
if [ $a == nat ]; then
/sbin/iptables -t nat -P PREROUTING ACCEPT
/sbin/iptables -t nat -P POSTROUTING ACCEPT
/sbin/iptables -t nat -P OUTPUT ACCEPT
elif [ $a == mangle ]; then
/sbin/iptables -t mangle -P PREROUTING ACCEPT
/sbin/iptables -t mangle -P INPUT ACCEPT
/sbin/iptables -t mangle -P FORWARD ACCEPT
/sbin/iptables -t mangle -P OUTPUT ACCEPT
/sbin/iptables -t mangle -P POSTROUTING ACCEPT
elif [ $a == filter ]; then
/sbin/iptables -t filter -P INPUT ACCEPT
/sbin/iptables -t filter -P FORWARD ACCEPT
/sbin/iptables -t filter -P OUTPUT ACCEPT
fi
done
start-stop-daemon --stop --quiet --pidfile /var/run/iptables.pid --exec /sbin/ip
tables
echo "."
;;
restart)
echo -n "Flushing firewall"
for a in `cat /proc/net/ip_tables_names`; do
/sbin/iptables -F -t $a
/sbin/iptables -X -t $a
done;
start
echo "."
;;
*)
echo "Usage: /etc/init.d/iptables {start|stop|restart|save}" >&2
exit 1
;;
esac
exit 0

Once we have saved this file, simply make the file executable and enable it to start when the system boots:

root@host # chmod +x /etc/init.d/iptables
root@host # update-rc.d iptables default

We now need to start the IPTables service so that we can load this ruleset:

root@host # /etc/init.d/iptables start
* Loading iptables state and starting firewall...	[ ok ]
* Restoring iptables ruleset    			[ ok ]

Now simply run the firewall.sh script to load the ruleset and test it out. When you have verified the rules are woking and traffic is being routed correctly, you can permanently save the rules by running the following command:

root@host # /etc/init.d/iptables save
* Saving iptables state...  				[ ok ]

Again, before blindly using the ruleset demostrated here, keep in mind that this is not the most secure ruleset. In this example we are allowing all traffic passed out. Ideally, we would filter outgoing traffic as well. From here you should be up and going, so enjoy.