Zaera Technologies
index projects howtos philosophy about contact

HOWTOs :: Firewall rules for a dual-homed gateway server

Last modified on Wednesday May 25 2005 @ 20:59:15
This HOWTO shows how to get computers on your LAN to access the Internet through a dual-homed gateway server. It is divided into the following sub-sections:

The scenario is as follows: You have one static IP address issued by your ISP, but you have several computers that you want to have online. One way of solving this issue, is by installing a dual-homed gateway server as shown in the figure below.

dual-homed gateway server LAN example

Part 1: Getting your private hosts online (IP Masquerading)

You need to have IPTables installed and IP forwarding enabled in your kernel in order to get this to work. Check if your kernel has this enabled by typing the following command:

        cat /proc/sys/net/ipv4/ip_forward

If it has a value of 0, IP forwarding is not enabled in your kernel. Go into your kernel sources (/usr/src/linux) and do a 'make menuconfig' and configure as follows:

In Networking Options

  <*> Packet socket
  ...
  [*] Network packet filtering (replaces ipchains)
  ...
  <*> Unix domain sockets
  [*] TCP/IP networking
  ...
  <M>   IP: tunneling

Then, under Networking Options --> IP: Netfilter Configuration

  <M> Connection tracking (required for masq/NAT) 
  ...
  <M> IP tables support (required for filtering/masq/NAT)
  ...
  <M>   MAC address match support
  <M>   Packet type match support
  ...
  <M>   Connection state match support
  <M>   Connection tracking match support
  ...
  <M>   Packet filtering
  <M>     REJECT target support
  ...
  <M>   Full NAT
  <M>     MASQUERADE target support

Now, compile the kernel. Refer to the Kernel HOWTO for further information on this topic. Install your new kernel and reboot with it.

You now need to install the IP Tables tools. Install this on your Gentoo distribution by executing the following command:

        emerge net-firewall/iptables
If you don't run Gentoo, you can download the source at www.iptables.org. Refer to the installation documents in the package for how to compile and install IPTables.

After IPTables is installed, make sure they start next time you boot your gateway server by typing:

        rc-update add iptables default

Now, we need to customize the firewall, so you need to create a script that enables and disables your firewall rules. Open up your favourite editor and create a new file, e.g. /root/firewall.sh that looks like this:  

#!/bin/bash

################################################################################
# script to open the appropriate ports in the firewall
################################################################################

IPTABLES="/sbin/iptables"
IPTABLES_SAVE="/sbin/iptables-save"
IPTABLES_SAVEFILE="/var/lib/iptables/rules-save"

###  open: ssh, http, https, X forward (range) ###
SERVICES="22 80 443"
SERVICES_RANGE_START="6010"
SERVICES_RANGE_END="6011"

EXT_NIC="eth0"
INT_NIC="eth1"
INT_IP="192.168.50.0/255.255.255.0"

if [ "$1" = "start" ] 
then

    echo "Starting firewall..."

    ###  set default rules (DENY, ACCEPT)  ###
    ${IPTABLES} -P INPUT DROP
    ${IPTABLES} -P FORWARD ACCEPT
    ${IPTABLES} -P OUTPUT ACCEPT

    ###  allow all incoming packets from internal net  ###
    ${IPTABLES} -A INPUT -i ! ${EXT_NIC} -j ACCEPT
    ###  allow incoming realated packets on external NIC  ###
    ${IPTABLES} -A INPUT -i ${EXT_NIC} -m state --state ESTABLISHED,RELATED -j ACCEPT

    ###  allow certain services  ###
    echo -n "* opening ports: "
    for x in ${SERVICES} 
    do 
        echo -n "$x "
        ${IPTABLES} -A INPUT -i ${EXT_NIC} -p tcp --dport $x -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
        ${IPTABLES} -A INPUT -i ${EXT_NIC} -p udp --dport $x -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    done
    echo ""

    ###  allow certain services : range ###
    echo "* opening port range: ${SERVICES_RANGE_START} - ${SERVICES_RANGE_END}"
    for port in $(seq $SERVICES_RANGE_START $SERVICES_RANGE_END); do 
        ${IPTABLES} -A INPUT -i ${EXT_NIC} -p tcp --dport $port -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
        ${IPTABLES} -A INPUT -i ${EXT_NIC} -p udp --dport $port -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    done

    ###  enables masquerading of internal hosts  ###
    echo "* enabling ip forwarding in kernel"
    echo 1 > /proc/sys/net/ipv4/ip_forward

    echo "* enabling masquerading of internal hosts"
    ${IPTABLES} -t nat -P PREROUTING ACCEPT
    ${IPTABLES} -t nat -P POSTROUTING ACCEPT
    ${IPTABLES} -t nat -P OUTPUT ACCEPT
    ${IPTABLES} -t nat -A POSTROUTING -o ${EXT_NIC} -j MASQUERADE

    ####  opening ports for ICMP  ###
    ${IPTABLES} -A INPUT -p icmp -j ACCEPT



    ################################################################################ 
    ###  enable SSH forwarding to internal IP address                            ###
    ################################################################################ 
    #
    # begin configuration
    #

    # port to listen to on the outside
    LISTEN_ON_PORT=7000
    # internal IP address to the inside desktop
    FORWARD_TO_IP="xxx.xxx.xxx.xxx"  
    # forward SSH to port 22
    FORWARD_TO_PORT=22

    #
    # end configuration
    #

    echo "* forwarding incoming requests on port $LISTEN_ON_PORT to $FORWARD_TO_IP:$FORWARD_TO_PORT"

    #
    # handle port forwarding for SSH2 to schweetie
    #
    ${IPTABLES} -t nat -I PREROUTING -i ${EXT_NIC} -p tcp --dport ${LISTEN_ON_PORT} -j DNAT --to ${FORWARD_TO_IP}:${FORWARD_TO_PORT}

    #
    # Enable forwarding rules to allow the above port forwarding connections to progress through
    #
    ${IPTABLES} -A FORWARD -i ${EXT_NIC} -p tcp -d ${FORWARD_TO_IP}/32 --dport ${FORWARD_TO_PORT} -j ACCEPT

    ###  end forwarding ssh rules
    ################################################################################ 


    ################################################################################
    ####  enable emule forwarding on router                                      ###
    ################################################################################

    ### from xmule.org forum  ###
    #
    # This script assumes that there is a single machine behind an iptables
    # enabled gateway which is running an emule or lmule client.  If you are
    # running a client on the same machine for which the firewall is also
    # enabled, the rules will be based in the INPUT and OUTPUT tables instead of
    # the nat and FORWARD tables.
    #

    #
    # begin configuration
    #

    # Default server port
    SERVERPORT=4661
    # The port used by our client
    CLIENTPORT=4666
    #CLIENTPORT=4662
    # The port used by our client for the extended emule protocol
    EXCHANGEPORT=4672
    # The port used by our client for the web server
    WEBPORT=4771
    # The network address of our machine behind this gateway
    EMULE_CLIENTIP="xxx.xxx.xxx.xxx" 

    #
    # end configuration
    #

    echo "* forwarding incoming eMule/lMule packets (ports $SERVERPORT, $CLIENTPORT, $EXCHANGEPORT, $WEBPORT) to $EMULE_CLIENTIP"

    #
    # Handle port forwarding for our client behind this gateway
    #
    ${IPTABLES} -t nat -I PREROUTING -i ${EXT_NIC} -p tcp --dport ${CLIENTPORT} -j DNAT --to ${EMULE_CLIENTIP}:${CLIENTPORT}
    ${IPTABLES} -t nat -I PREROUTING -i ${EXT_NIC} -p udp --dport ${CLIENTPORT} -j DNAT --to ${EMULE_CLIENTIP}:${CLIENTPORT}
    ${IPTABLES} -t nat -I PREROUTING -i ${EXT_NIC} -p udp --dport ${EXCHANGEPORT} -j DNAT --to ${EMULE_CLIENTIP}:${EXCHANGEPORT}
    ${IPTABLES} -t nat -I PREROUTING -i ${EXT_NIC} -p tcp --dport ${EXCHANGEPORT} -j DNAT --to ${EMULE_CLIENTIP}:${EXCHANGEPORT}
    ${IPTABLES} -t nat -I PREROUTING -i ${EXT_NIC} -p tcp --dport ${WEBPORT} -j DNAT --to ${EMULE_CLIENTIP}:${WEBPORT}

    #
    # Enable forwarding rules to allow the above port forwarding connections to progress through
    #
    ${IPTABLES} -A FORWARD -i ${EXT_NIC} -p tcp -d ${EMULE_CLIENTIP}/32 --dport ${CLIENTPORT} -j ACCEPT
    ${IPTABLES} -A FORWARD -i ${EXT_NIC} -p udp -d ${EMULE_CLIENTIP}/32 --dport ${EXCHANGEPORT} -j ACCEPT
    ${IPTABLES} -A FORWARD -i ${EXT_NIC} -p tcp -d ${EMULE_CLIENTIP}/32 --dport ${WEBPORT} -j ACCEPT

    #
    # Enable forwarding rules to allow our internal client to get to allowed ports
    #
    ${IPTABLES} -A FORWARD -i ${EXT_NIC} -p tcp -s ${EMULE_CLIENTIP}/32 --dport ${SERVERPORT} -j ACCEPT
    ${IPTABLES} -A FORWARD -i ${EXT_NIC} -p tcp -s ${EMULE_CLIENTIP}/32 --dport ${CLIENTPORT} -j ACCEPT
    ${IPTABLES} -A FORWARD -i ${EXT_NIC} -p udp -s ${EMULE_CLIENTIP}/32 --dport ${EXCHANGEPORT} -j ACCEPT
    ${IPTABLES} -A FORWARD -i ${EXT_NIC} -p tcp -s ${EMULE_CLIENTIP}/32 --dport ${WEBPORT} -j ACCEPT

    ###  end emule rules
    ################################################################################ 


    #
    # Finally, allow any established or related connections on to the external interface be forwarded on
    #
    $IPTABLES -A FORWARD -i ${EXT_NIC} -m state --state ESTABLISHED,RELATED -j ACCEPT


    # end start

elif [ "$1" = "stop" ] 
then
    echo "Stopping firewall..."

    ${IPTABLES} -F INPUT
    ${IPTABLES} -F FORWARD
    ${IPTABLES} -P INPUT ACCEPT

    #  turn off NAT/masquerading, if any
    ${IPTABLES} -F -t nat

#    ${IPTABLES} -L -v
#    ${IPTABLES} -L -v -t nat

elif [ "$1" = "save" ] 
then
    echo "Saving IP Table rules to ${IPTABLES_SAVEFILE}"
    ${IPTABLES_SAVE} > ${IPTABLES_SAVEFILE}

else
    echo "invalid parameter"
    echo "Usage: firewall.sh "
fi

##############################################################################o
#EOF

Save your file, and exit the editor. Now, make sure you have the executable flags on the firewall.sh script:

        chmod 700 /root/firewall.sh

Great! Start your firewall by typing:

        /root/firewall.sh start

TODO: explain how to set up internal routing (DHCP/static) here...

You should now be able to get online with the internal hosts. If everything works as expected, you want to save your firewall rules so that they start up automatically next time you boot your server. Do this by typing:

        /root/firewall.sh save

WARNING: The save command is customized for the Gentoo distribution, and is not guaranteed to work with other distros. Figure out where IP Tables saves its rules in your distro, and change the IPTABLES_SAVEFILE variable in the script above.

Your rules are now saved and everything will start automatically next time you boot your gateway server. :D

Part 2: Opening for selected services on your gateway server

The following lines in the script above determine the services that are open to the world on the gateway server:

###  open: ssh, http, https, X forward (range) ###
SERVICES="22 80 443"
SERVICES_RANGE_START="6010"
SERVICES_RANGE_END="6020"

Change them to fit your system, and restart your firewall by typing:

        /root/firewall.sh stop; /root/firewall.sh start

Now, test the firewall by opening a connection to either of the opened services. If everything works ok, save the firewall rules:

        /root/firewall.sh save

Part 3: SSH-forwarding to an internal host through your gateway server

The scenario is as follows: You want to access a service (e.g. SSH) on one of the internal hosts from the outside world as depicted in the figure below.

forward

The trick is to have the firewall (IPTables) to forward any connection attempt to a given port (e.g. 7000 as in the image) on the gateway server to an internal IP address. In order to enable forwarding to an internal host on your private network, edit the following configuration and customize it to your environment:

    ################################################################################ 
    ###  enable SSH forwarding to internal IP address                            ###
    ################################################################################ 
    #
    # begin configuration
    #

    # port to listen to on the outside
    LISTEN_ON_PORT=7000
    # internal IP address to the inside desktop
    FORWARD_TO_IP="192.168.0.12"  
    # forward SSH to port 22
    FORWARD_TO_PORT=22

    #
    # end configuration
    #

Now, restart your firewall by typing:

        /root/firewall.sh stop; /root/firewall.sh start

Now, test the new config by SSH-ing in from an external host:

        ssh -o "Port 7000" 218.121.12.10

Verify that you got forwarded to the internal host. If everything works ok, remember to save the firewall rules:

        /root/firewall.sh save

Part 4: Get eMule/lMule/xMule to run inside your private network

The goal of this part is to get eMule/lMule/xMule to run on one of your internal hosts without getting the LowID that eMule/lMule/xMule gives you if no external connections are allowed. The scenario is as the figure shows:

forward

The section of the firewall script above that needs to be customized to enable emule on the inside of our gateway is as follows:

    ### from xmule.org forum  ###
    #
    # This script assumes that there is a single machine behind an iptables
    # enabled gateway which is running an emule or lmule client.  If you are
    # running a client on the same machine for which the firewall is also
    # enabled, the rules will be based in the INPUT and OUTPUT tables instead of
    # the nat and FORWARD tables.
    #

    #
    # begin configuration
    #

    # Default server port
    SERVERPORT=4661
    # The port used by our client
    CLIENTPORT=4662
    # The port used by our client for the extended emule protocol
    EXCHANGEPORT=4672
    # The port used by our client for the web server
    WEBPORT=4771
    # The network address of our machine behind this gateway
    EMULE_CLIENTIP="192.168.0.11"

    #
    # end configuration
    #

Now, restart your firewall by typing:

        /root/firewall.sh stop; /root/firewall.sh start

The next step is to configure your eMule/lMule/xMule client to match the configuration set here. Go into the preferences and set the ports as specified in the firewall rules.

Verify that you don't get LowID after restarting your eMule/lMule/xMule client. If everything works ok, remember to save the firewall rules:

        /root/firewall.sh save