A basic firewall configuration suitable for a gateway/nat

From LQWiki
Jump to: navigation, search


The field of application of a NAT Gateway is in example a private LAN consisting of several PC with an Internet connection with one public IP address.

  • The goal is to share the Internet connection among the LAN PCs.
  • The problem is that there is only one public IP for outbound traffic.
  • The solution is "Network Address Translation" (or NAT for short).

The Gateway (GW) is equipped with two network interfaces. One gets assigned the public IP, the second a private IP (i.e. Every other LAN PCs has it's own private IP (i.e. If an outbound connection is requested the LAN PC talks to the gateway which masquerades the outbound traffic using the public IP. So every external connection looks like if it is coming from only one PC.

The basic firewalling will prevent all connections from outside with the exception of SSH (port 22) which we leave open for service purposes (i.e.).

System preparation

The following assumes that the gateway has two network interfaces:

  • eth0 will be the external and
  • eth1 the internal interface.

To use iptables you need to have at least the following kernel components compiled in or as modules

  • ip_tables
  • ip_conntrack and ip_conntrack_ftp

IP forwarding needs to be active (echo 1 > /proc/sys/net/ipv4/ip_forward</userdefined).

Setup the external interface using the necessary data from your provider (IP and standard gateway). The internal interface (eth1) needs to get a private IP address, like The routing table of the gateway will be set up automatically during network initialization.

Every LAN PC will use the NAT-Gateways internal IP ( in our example) as standard gateway in its networking setup.

Firewall script

  extip=   # replace with your EXTERNAL IP
  lan= # your LAN<

  # start firewall
  start_firwall {
    echo "Enabling IP forwarding."
    echo 1 > /proc/sys/net/ipv4/ip_forward

    echo "Enabling iptables firewall."
    # default policies
    $ipt -P INPUT DROP
    $ipt -P FORWARD DROP

    # NAT
    $ipt -t nat -A POSTROUTING -o eth0 -j SNAT --to-source $extip

    # INPUT chain
    $ipt -A INPUT -i lo -j ACCEPT
    $ipt -A INPUT -i eth1 -s $lan -j ACCEPT
    $ipt -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
    $ipt -A INPUT -p tcp --destination-port 22 -j ACCEPT

    # FORWARD chain
    $ipt -A FORWARD -i eth1 -s $lan -j ACCEPT
    $ipt -A FORWARD -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT

  # stop firewall
  stop_firwall {
    $ipt -P INPUT DROP
    $ipt -P OUTPUT DROP
    $ipt -P FORWARD DROP
    # allow internal traffic
    $ipt -A INPUT -i eth1 -j ACCEPT
    $ipt -A OUTPUT -o eth1 -j ACCEPT

  # flushing, removing and zeroing tables
reset_firwall { chains=`cat /proc/net/ip_tables_names` for i in $chains; do $debug $ipt -t $i -F $debug $ipt -t $i -X $debug $ipt -t $i -Z done } case "$1" in start|restart|reload) reset_firewall start_firewall  ;; stop) reset_firewall stop_firewall  ;; *) echo "Usage: $0 {start|stop|restart|reload}" exit 1  ;; esac exit 0


  echo 1 > /proc/sys/net/ipv4/ip_forward

This option enables forwarding of packets between network interfaces. Every packet that will not be accepted by one of the rules in the INPUT or FORWARD chain will hit the default policy in the particular chain so we set every default policy to DROP.

  iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source $extip

With only one external IP you need to masquerade every outgoing packet using the external IP. This is done in the Postrouting Chain, just before the packet leaves the gateway. This works only with a static IP. If the external IP is assigned dynamically you should use the following line (replace the interface as apropriate):

  iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

The iptables INPUT chain allows all traffic from the loopback (lo) and internal interface (eth1). Outside connections (eth0) are accepted if they are already established, related to another connection or if it is a SSH connection.

New in comparison to the workstation firewall is the FORWARD chain. This chain will handel all traffic that is destined for one of the LAN internal PCs. Like in the INPUT chain it allows all traffic from the internal interface (eth1) and only established or related connections from the outside interface (eth0).


The firewalling script must be executable (chmod +x fwscript). Now you can run it simply by typing: ./fwscript [start|stop].

Starting the script during system initialization depends on your distribution. You should check the system init scripts (/etc/init.d, /etc/rc*.d).


Copy the fwscript file to /etc/init.d. Decide in which runlevels you want it to be started. Now in each runlevel's /etc/rc*.d directory, create an symlink called either S99fwscript if you want the firewall on, or K99fwscript if you want it off, pointing to ../init.d/fwscript.

e.g. the other alternative fot this link is to sipmlpy type $ update-rc.d firewall defaults and the application number from any of the runlevels.

  ln -s /etc/init.d/fwscript /etc/rc2.d/K99fwscript
  ln -s /etc/init.d/fwscript /etc/rc3.d/S99fwscript

The start or stop parameter will be automagically added according to whether the symlink started with S (for start) or K (for kill), except in runlevels 0 and 6 where everything will be stopped.

Alternatively, if you want your firewall active in all runlevels, put just one symlink in /etc/rcS.d.


The RedHat iptables package already includes an iptables service. To use the configuration described in this document with this service, first run the script as per instructions above:

  ./fwscript start

Then execute

  /etc/rc.d/init.d/iptables save

This will save the settings into /etc/sysconfig/iptables, so now you can enable the iptables service at boot by executing

  chkconfig --level 2345 iptables on

You might also want to check that IP forwarding is enabled in /etc/sysctl.conf by executing

  sysctl -w net.ipv4.ip_forward=1

External links