Debian/Ubuntu Tips and Tricks


Debian/Ubuntu Tips and Tricks

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

Posted by chantra on June 29th, 2008

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:


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 on port 22.

Here is the script used:

# this script requires iptables package to be
# installed on your machine
# Where to find iptables binary
# The network interface you will use
# WAN is the one connected to the internet
# LAN the one connected to your local network
# First we need to clear up any existing firewall rules
# and chain which might have been created
$IPT -F -t mangle
$IPT -F -t nat
# Default policies: Drop any incoming packets
# accept the rest.
# 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 PREROUTING -i $WAN -p tcp --dport 2222 -j DNAT --to-destination
$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
# plus from your local network
# 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 -p tcp --dport 22 -j ACCEPT
# Accept related and established connections
# 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

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 :

# load options
if [ -f /etc/default/iptables ] ; then
  . /etc/default/iptables
  exit 1
# 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
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 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
      elif [ $table = filter ]; then
        ${IPTABLES} -t filter -P INPUT ACCEPT
        ${IPTABLES} -t filter -P FORWARD ACCEPT
        ${IPTABLES} -t filter -P OUTPUT ACCEPT
  return 0
case "$1" in
  log_begin_msg "Loading iptables settings..."
  log_end_msg $?
  log_begin_msg "Saving iptables settings..."
  log_end_msg $?
  log_begin_msg "Clearing iptables settings..."
  log_end_msg $?
  $0 stop
  $0 start
  log_success_msg "Usage: $0 {start|stop|restart|status|save}"
  exit 1

and another one to /etc/default/iptables :


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.

Series Navigation<< How-To: Set up a LAN gateway with DHCP, Dynamic DNS and iptables on Debian Etch — page 2 — DNS server

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

  1. Hi Chantra. I am newbie. After extensive searching on the Internet, I came across your post. I have the exact similar setup on my system, i.e. eth0 is get IP via DHCP which can connect to the Internet. eth1 is intended to be the interface for the internal lan. My objective is to setup and internal lan that can reach the internet and get DHCP IP address from the eth1 interface. I want to accomplish more than this however, I'd like to start small.

    I am running the system in oracle virtualbox. The eth0 adapter is set as bridge adapter and is getting IP address from my router. eth1 is set as an internal network adapter with the name as intnet-test (in Virtualbox).

    My system is running debain squeeze (kernel 2.6.32-5-686) in terminal mode so there is no gui interface. I have not installed any of the server packages from debian. When the system comes to the login prompt, the eth0 interface is up. I am able to ping

    My issue is that when I execute ifconfig , I can only see eth0 and the loop back adapter in the listing. eth1 does not show up. I have been trying to set up the interface with a static IP address, by editing the /etc/network/interface file, however, the error message says I don't have enough variables set for eth1 and the interface does not come up.

    Any help with this is really appreciated. Thanks - Kevin

  2. most likely your eth1 configurstion is from. It should look like

    auto eth1
    iface eth1 inet static

    in /etc/network/interfaces, then reload your network settings.

    In case it still fails, using:

    ifup eth1

    might give you some info on why it fails.

  3. Wow! I have been trying combinations of commands since the last night. Nothing seemed to work. This fixed my issue. I really appreciate your help. Now I can move on. Thank you very much.

  4. Hi Chantra. I am facing an issue here. I performed the exact installation for the VM on two different physical machines. One desktop and one laptop. The above suggestion worked perfectly in a desktop environment and hence my comment about working.

    On the laptop, the same four lines gives me "Don't seem to have all the variables for eth1/inet. Failed to bring up eth1". Not sure why. Both installations are default, no additional package installed. Any suggestions? Thanks. Kevin

  5. **** OK, now it is working on my laptop ****

    This time I selected a different NIC in the network settings. Re-installed Debian. Inserted the above four lines. Brought up the interface. I am up and working.

    *** Thanks again. Kevin

  6. Hi Chantra. I have configured my debian machine to be dns and dhcp as shown in the post. Here are some details:

    Server Hostname: debtest2
    eth0 = DHCP from external router; 192.168.1.x
    eth1 =, netmask

    For DNS configuration

    ------ named.conf.local

    #allow dns updates from localhost with key "rndc-key"
    include "/etc/bind/rndc.key";
    controls {
    inet allow { localhost; } keys { "rndc-key"; };
    #defines galaxy.local
    zone "galaxy.local" {
    type master;
    file "db.galaxy.local";
    allow-update { key "rndc-key"; };
    #defines our local subnet
    zone "" {
    type master;
    notify no;
    file "db.2.168.192";
    allow-update { key "rndc-key"; };

    ------ db.galaxy.local file

    $TTL 3D
    @ IN SOA ns.galaxy.local. postmaster.galaxy.local. (
    201201081; serial, todays date + todays serial #
    8H ; refresh, seconds
    2H ; retry, seconds
    4W ; expire, seconds
    1D ) ; minimum, seconds
    NS ns ; Inet Address of name server
    MX 10 mail ; Primary Mail Exchanger
    A ; IP address
    router A
    ns CNAME router
    dhcp CNAME ns.galaxy.local.
    * A

    ------ db.2.168.192 file

    $TTL 3D
    @ IN SOA galaxy.local. postmaster.galaxy.local. (
    201201081 ; serial, todays date + todays serial #
    8H ; refresh, seconds
    2H ; retry, seconds
    4W ; expire, seconds
    1D ) ; minimum, seconds
    @ IN NS ns.galaxy.local.
    @ IN PTR galaxy.local.
    1 IN PTR router.galaxy.local.

    Issue: nslookup debtest2 gives me error. I believe it does not function as intended.

    server can't find debtest2: NXDOMAIN

    DHCP server configuration

    ----- /etc/defaults/isc-dhcp-server file

    INTERFACES = "eth1"

    ------ /etc/dhcp/dhcpd.conf file

    server-identifier router;
    ddns-update-style interim;
    include "/etc/bind/rndc.key";
    # Use what key in what zone
    zone galaxy.local. {
    key "rndc-key";
    #Standard DHCP info
    option domain-name "galaxy.local";
    option domain-name-servers ns.galaxy.local;
    default-lease-time 600;
    max-lease-time 7200;
    log-facility local7;
    subnet netmask {
    option routers router.galaxy.local;
    zone {
    primary ns.galaxy.local;
    key "rndc-key";
    zone galaxy.local. {
    primary ns.galaxy.local;
    key "rndc-key";

    When I boot up a client PC (configured with internal adapter), it gets the IP address from the DHCP server. Details are:

    ifconfig: clientPC#1

    eth0 Link encap:Ethernet HWaddr 08:00:27:b6:9b:d3
    inet addr: Bcast: Mask:
    inet6 addr: fe80::a00:27ff:feb6:9bd3/64 Scope:Link
    RX packets:7 errors:0 dropped:0 overruns:0 frame:0
    TX packets:92 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:986 (986.0 B) TX bytes:15307 (15.3 KB)
    Interrupt:10 Base address:0xd020

    route -n clientPC#1

    Destination Gateway Genmask Flags Metric Ref Use Iface U 1000 0 0 eth0 U 1 0 0 eth0

    hostname -f: client PC#1

    Issue: I can't resolve debtest2 from the client PC. Cannot access Internet as well. I think the gateway address is missing.

    Any suggestions or perhaps any obvious error? Thank you again for helping me. Kevin (

  7. Hi Kevin,
    please review page 2 of this how-to (basically, there were errors in both dhcp and dns files that prevented the settings to work.

    in bind zone, NS should be using A and record.

    The DNS issue prevents your client to get the right router ip.

    If your client is a debian box, make sure you use:
    send host-name ""
    in /etc/dhcp/dhclient.conf

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>