How-To: Set up a LAN gateway with DHCP, Dynamic DNS and iptables on Debian Etch — page 4 — IPtables

5 minute read

We now provide IPs to the hosts in our LAN with our newly installed DHCP server. Now we need to pass their network packets around.

3. Forwarding Internet traffic with IPtables

IPtables is both used to act as a firewall, but it is also the one passing packets from one network to another.

3.1. Enabling IP forwarding

IP forwarding is enabled at the kernel level. The way to enable it is to set /proc/sys/net/ipv4/ip_forward_ to 1.

This can be done during runtime by typing:

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

To make those changes permanent upon reboots, edit /etc/sysctl.conf and make sure there is the following values:

net.ipv4.conf.default.forwarding=1
net.ipv4.conf.all.forwarding=1

3.2. Setting iptables rules

The next step is to set up iptables rules, the ones that will tell the kernel what to do with the packet depending on their states.

This firewall will only accept ssh connection from the WAN, anything from the LAN and will forward port 2222 from the WAN to machine 192.168.2.2 on port 22.

Here is the script used:

#!/bin/sh
# 
# this script requires iptables package to be
# installed on your machine


# Where to find iptables binary
IPT="/sbin/iptables"
# The network interface you will use
# WAN is the one connected to the internet
# LAN the one connected to your local network
WAN="eth0"
LAN="eth1"
# First we need to clear up any existing firewall rules
# and chain which might have been created
$IPT -F
$IPT -F INPUT
$IPT -F OUTPUT
$IPT -F FORWARD
$IPT -F -t mangle
$IPT -F -t nat
$IPT -X

# Default policies: Drop any incoming packets
# accept the rest.
$IPT -P INPUT DROP
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD ACCEPT

# To be able to forward traffic from your LAN
# to the Internet, we need to tell the kernel
# to allow ip forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

# Masquerading will make machines from the LAN
# look like if they were the router
$IPT -t nat -A POSTROUTING -o $WAN -j MASQUERADE


$IPT -t nat -A PREROUTING -i $WAN -p tcp --dport 2222 -j DNAT --to-destination 192.168.2.2:22
$IPT -A FORWARD -i $WAN -p tcp  --dport 22 -m state --state NEW -j ACCEPT

# Do not allow other new or invalid connections to reach your internal network
$IPT -A FORWARD -i $WAN -m state --state NEW,INVALID -j DROP

# Accept any connections from the local machine
$IPT -A INPUT -i lo -j ACCEPT
# plus from your local network
$IPT -A INPUT -i $LAN -j ACCEPT

# log those packets and inform the sender that the packet was rejected
$IPT -N Rejectwall
$IPT -A Rejectwall -m limit --limit 10/minute -j LOG --log-prefix "Rejectwall: "
$IPT -A Rejectwall -j REJECT
# use the following instead if you want to simulate that the host is not reachable
# for fun though
#$IPT -A Rejectwall -j REJECT  --reject-with icmp-host-unreachable

$IPT -A INPUT -p icmp -j ACCEPT

# Accept ssh connections from the Internet
$IPT -A INPUT -i $WAN -p tcp --dport 22 -j ACCEPT

# or only accept from a certain ip
#$IPT -A INPUT -i $WAN -s 125.124.123.122 -p tcp --dport 22 -j ACCEPT

# Accept related and established connections
$IPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Drop netbios from the outside, no log, just drop
$IPT -A INPUT -p udp --sport 137 --dport 137 -j DROP

# Finally, anything which was not allowed yet
# is going to go through our Rejectwall rule
$IPT -A INPUT -j Rejectwall

Now, run the script:

# sh iptables.sh

All host within the LAN should now be able to access the internet!

now we have to make sure that the changes are permanent upon reboot.

3.3. Making iptables rules persistent

I like to be able to easily start and stop iptables using an init.d script. Unfortunately, this is gone from debian packages.

Anyhow, here is a script that you can copy to /etc/init.d/iptables :

#!/bin/sh

IPTABLES="/sbin/iptables"

# load options
if [ -f /etc/default/iptables ] ; then
  . /etc/default/iptables
else
  exit 1
fi

# Check for daemon presence
test -x ${IPTABLES} || exit 0

# Get lsb functions
. /lib/lsb/init-functions
. /etc/default/rcS

# Check for saved state
if [ x$1 != "xsave" ] && [ x$1 = "xstart" ] && ! test -r ${IPTABLES_SAVE}; then
  log_warning_msg "Skipping iptables configuration..."
  exit 0
fi

flush() {
  if [ -f /proc/net/ip_tables_names ] ; then
    for table in `cat /proc/net/ip_tables_names`; do
      ${IPTABLES} -F -t $table
      ${IPTABLES} -X -t $table
      if [ $table = nat ]; then
        ${IPTABLES} -t nat -P PREROUTING ACCEPT
        ${IPTABLES} -t nat -P POSTROUTING ACCEPT
        ${IPTABLES} -t nat -P OUTPUT ACCEPT
      elif [ $table = mangle ]; then
        ${IPTABLES} -t mangle -P PREROUTING ACCEPT
        ${IPTABLES} -t mangle -P INPUT ACCEPT
        ${IPTABLES} -t mangle -P FORWARD ACCEPT
        ${IPTABLES} -t mangle -P OUTPUT ACCEPT
        ${IPTABLES} -t mangle -P POSTROUTING ACCEPT
      elif [ $table = filter ]; then
        ${IPTABLES} -t filter -P INPUT ACCEPT
        ${IPTABLES} -t filter -P FORWARD ACCEPT
        ${IPTABLES} -t filter -P OUTPUT ACCEPT
      fi
    done
  fi
  return 0
}

case "$1" in
  start)
  log_begin_msg "Loading iptables settings..."
  ${IPTABLES}-restore ${SAVE_RESTORE_OPTIONS} ${IPTABLES_SAVE}
  log_end_msg $?
  ;;
  save)
  log_begin_msg "Saving iptables settings..."
  ${IPTABLES}-save ${SAVE_RESTORE_OPTIONS} > ${IPTABLES_SAVE}
  log_end_msg $?
  ;;
  stop)
  log_begin_msg "Clearing iptables settings..."
  flush
  log_end_msg $?
  ;;
  restart)
  $0 stop
  $0 start
  ;;
  status)
  ${IPTABLES} -L
  ;;
  *)
  log_success_msg "Usage: $0 {start|stop|restart|status|save}"
  exit 1
esac

and another one to /etc/default/iptables :

IPTABLES_SAVE="/etc/iptables-rules"
SAVE_RESTORE_OPTIONS="-c"

finally, once you are satisfied with your actual rules, save them by typing the following:

# /etc/init.d/iptables save

We also need to make sure that the service will be started upon boot up by typing:

# update-rc.d iptables defaults 20

And that’s it, here we are with a box that provide full access t internet!

4. Troubleshooting

Even though this tutorial is made in such a way that you could just copy and paste, issues may arise.

You might find useful to install the packages dnsutils, telnet, tcpdump and nmap to get a better idea of what is going on.

In /var/log , action is going to be mailly in messages, daemon.log and syslog.