Linux — IPTABLES Network Firewall

Most firewalls in the consumer world are ones that are either bought at Bestbuy or supplied by your ISP as an all-in-one type of network device. These devices, such as the Linksys WRT54GL, are good enough for most user’s home setups. Providing Wireless and Wired network access with built in Firewall security. Blocking most inbound network threats , and other unwanted requests that are not pre-established (i.e. return path from an outbound request). Some of these consumer routers can be even further enhance with a rich set of plugins and network tools by using custom firmwares. DD-WRT, Tomato, or openWRT are all interdependent communities, who develop custom firmware to be used with these consumer all-in-one routers. You can check your devices compatibility with their firmware at each of their websites.

I for one own a Linksys WRT54GL router and have used both DD-WRT and Tomato. Both of these custom firmwares as well as the stock firware(Linksys) provide enough security, accessibly, and capacity for a typical consumer. However, that’s not what this article is about! This article is how to setup your own Network Firewall using a standalone Linux box! Woot!.

Why build a standalone Network Firewall?


Hopefully you’ve read this far that I don’t need to convince you to continue, however…First, the ability to customize. With a standalone Network Firewall you have the ability to run any type of firewall application. IPTABLES, ufw, IPCop, Shorewall. The last two being complete Linux Distributions geared toward network security.
Second, capacity. Consumer products have a limitation based on the hardware they use to support a certain amount of half-open connections, or load, or even configuration sizes (e.g. blocklist to large to fit on consumer router’s memory). Our standalone Linux server will have it’s own dedicated storage as well as much more RAM to handle these customizations. I encountered this limitation first hand when I was working for a large corporation on an IT project. The project entailed deploying consumer routers such as Linksys, or D-Link, etc with 20+ PDAs (remember those!!, haha). I noticed when all 20 PDA tried to connect to the router, some of the PDAs would be dropped. Now granted, I know this was probably a limitation of the wireless chipset in the router, however this is to only illustrate my point. Consumer routers are not built with high-capacity in mind.
Lastly, application addons. Because this box will be a standalone Linux box, we can install additional applications along side of it. For example, running a network traffic monitor, such as nTop, or a proxy server, such as squid-cache.
There are a lot of other reasons as well.

Network Design

Ok, if you made it this far, congrats. You are a geek like me. Haha, lets get to it.

    1. First we need a network design for the network and firewall. Are you using an dual-homed firewall? 3-legged with DMZ? If you are unsure of your need check out this article from firewall.cx. It is a very good explanation of firewall topology setups. For our topology we will be designing a three-legged firewall with DMZ.
      Next, we need to create our logical networks. I would recommend utilizing /24 networks for simplicity. However remember a /24 network will only give you 254 hosts per network. So if you are designing this for a large host base in mind, adjust accordingly. I chose 192.168.0.0/24 for the internal network and 172.16.0.0/24 for the DMZ network. Both are in the Private Address Space.Here is our basic design:
      3-legged Network Example
      As you can see, there are 3 legs. You can easily add more legs for more networks. Although remember depending on 1 firewall for large networks is ill advised from a security vulnerability perspective.
    2. Install Linux OS on the Linux Firewall Box. For this tutorial I am using Ubuntu 12.04 LTS server. You can easily do this on any linux/unix OS variation, as IPTABLES is built into the Linux kernel. (I think…).
    3. Setting up our interfaces. Login as root and edit your network interfaces configuration file.
      vi /etc/networking/interfaces

      In here look for the line

      # The loopback network interface
       auto lo iface lo inet loopback

      Under this line copy and paste the following, there should be nothing else in this file besides these items.

      #ISP dynamically assigned IP via DHCP
      auto eth0
      iface eth0 inet dhcp
      
      #1st Leg NIC for Internal Network
      auto eth1
      iface eth1 inet static
              address 192.168.0.1
              netmask 255.255.255.0
      
      #2nd Leg NIC for DMZ Network
      auto eth2
      iface eth2 inet static
              address 172.16.0.1
              netmask 255.255.255.0
      

      NOTICE: my eth0 interface is set to obtain an IP automatically from my ISP via DHCP.If you have a static IP from your ISP or external network you are connect this firewall to, you would put it here make sure to change it from iface eth0 inet dhcp to iface eth0 inet static

      NOTICE: I chose .1 as the interfaces host address, you can choose what ever you want, just make sure your network hosts know how to get to these NICs so they can be routed correctly.\

    4. Enable IP Forwarding on the Linux Kernel. This step is crucial for allowing routing between each network and interfaces. By default Ubuntu has this disabled, essential anything destined for a network besides it’s own is dropped or not processed.
    5. Login as Root, and Check first.
      cat /proc/sys/net/ipv4/ip_forward
    6. Change it to 1, and make it start as 1 on boot..
      echo 1 > /proc/sys/net/ipv4/ip_forward 
      sysctl -w net.ipv4.ip_forward=1 
      sysctl -p /etc/sysctl.conf 
      service network restart

      See here for more info on permanently enabling IP Forwarding.

    7. The next step is very impacting. It is important for you to be either consoled into or directly connected to this Linux box. I would not recommend doing this configuration change remotely, as an fat-fingered item from the previous step could render your Linux box unreachable.
      Restarting the Linux networking service. You can do this two ways, either restart the server completely(reboot) or issue the following command:

      sudo service networking restart

      NOTICE: If you receive any errors on networking go back and check your interfaces configuration file.

    8. Next, check your Route table
      route -n
      Destination     Gateway         Genmask         Flags Iface
      0.0.0.0         {externalNet}   0.0.0.0         UG    eth0
      {externalNet}   0.0.0.0         255.255.252.0   U     eth0
      172.16.0.0      0.0.0.0         255.255.255.0   U     eth2
      192.168.0.0     0.0.0.0         255.255.255.0   U     eth1
      

      NOTICE: I omitted some columns to make the table fit on the page.

    9. Check network connectivity. If you have end point devices on each network configure each a single node on each of the different networks (Internal and DMZ) with an IP address (not the same as our Linux Firewall) with a gateway address of the Linux Firewall NIC it is attached to on the same network. For example for a Internal device, configure it with the IP address of 192.168.0.50, netmask of 255.255.255.0, and a gateway of 192.168.0.1 (Internal Network NIC). Try now to ping the device from the Linux Firewall box and vice-versa.
    10. Using a endpoint device on the internal network, try to do a ping or traceroute from that device to another device on the DMZ network. This will ensure that routing is correctly working. If you receive a destination unreachable, ensure your endpoint devise is using the Linux Firewall box NIC’s IP and that you completed step 3 and 4.
      ***If you are successfully with the last two steps, congratulations you have a working Linux router. If that is what you wanted, stop hear and go have a beer!.

    Firewall with IPTABLES.

    1. How are IPTABLE rules constructed? IPTABLES have three main firewall tables you need to keep in mind. INPUT, FORWARD, OUTPUT. All are relative to the Firewall system itself. Meaning, INPUT table is any datagram destined for the firewall. For example in our scenario a packet from 192.168.0.10 –> 192.168.0.1(our Internal Network NIC) would be processed by the INPUT table. OUTPUT table is exactly the opposite, anything Outbound from the Firewall. For example in our scenario a packet from 192.168.0.1 –> 192.168.0.10. Lastly, the FORWARD table. FORWARD table is where most of our rules will exist, this table is triggered any time a packet is received on one network that is destined for another network, pretty much anything routed.
      Now you may be thinking, well what about Port Forwarding, or NAT’ing? There are indeed other chained tables, such as PREROUTING, POSTROUTING, etc used for these functions. There is a great article here that explains the inter-workings and tables of the entire IPTABLES technology. I recommend a read.Target Types. Target types are actions used when an IPTABLE rule is triggered/matches. It can be anything from an ACCEPT to a REJECT. Possible Target Types are; ACCEPT, DROP, REJECT, LOG, DNAT, SNAT, MASQUERADE.
      NOTICE: The difference between a DROP and REJECT, is a DROP will not inform the user the packet was denied, while REJECT will send back a clean “tear-down” message. DROPs are good for anything public, REJECTs for anything internal.A typical IPTABLE rule statement:

      iptables -I INPUT 0 -i eth1 -s 192.168.0.0/24 -p tcp -dport 80 -m comment --comment "Allow Internal Address Space to our Firewall Address on port TCP 80" -j ACCEPT

    Planning Firewall Rules. We now need to step back and brainstorm what rules we want in place on our network. The firewall is only as secure as the rules it uses to satisfy your network solution. For this tutorial I have the defined following criteria:

    • Internal Nodes is allowed to access DMZ Nodes
    • DMZ Nodes are not allowed to access Internal Nodes
    • Internal Nodes should dynamic NAT with overloading,when outbound the eth0 Interface
    • DMZ Nodes are allowed access to Internal DNS Server
    • DMZ Nodes should NAT one-to-one when outbound over eth0 Interface

    NOTICE: If you would like to know more regarding Network Address Translation(NAT) types, see my article here.

    OK! We have some IPTABLE rules to construct, so let’s get started.

    Constructing IPTABLES

    For the examples below, eth0 is the public interface.

    1. Internal to DMZ fully access.
      iptables -A FORWARD -s 192.168.0.0/24 -d 172.16.0.0/24 -j ACCEPT -m comment --comment "Allow Internal to DMZ network full"
    2. Deny DMZ to Internal
      iptables -A FORWARD -s 172.16.0.0/24 -d 192.168.0.0/24 -j REJECT -m comment --comment "Deny DMZ access to Internal"
    3. DMZ access to internal DNS server at 192.168.0.2
      iptables -A FORWARD -s 172.16.0.0/24 - 192.168.0.2/32 p tcp -dport 53 -j ACCEPT 
      iptables -A FORWARD -s 172.16.0.0/24 -d 192.168.0.2/32 -p udp --dport 53 -j ACCEPT

      NOTICE: DNS uses UDP for queries and TCP for zone transfers, so depending on what you are trying to accomplish use either statement.

    4. Let’s let any DMZ server make DNS (53), HTTP (80), and SMTP (25) connections to other networks.
      iptables -A FORWARD -s 172.16.0.0/24 -p tcp -m multiport --dports 53,80,25 -m comment --comment "Allow 53,80,25 FORWARDED from 172.16.0.0/24" -j ACCEPT
    5. After you have implemented all the Firewall rules you need, a good practice is to change the dfeault policy to DROP for each table. Caution when performing this, as you could make the Firewall unreachable.
      iptables -P INPUT DROP 
      iptables -P FORWARD DROP 
      iptables -P OUTPUT -DROP

    Advanced IPTABLES

    For the examples below, eth0 is the public interface.

    1. Port Forwarding to a web server at 172.16.0.100
      iptables -A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -m comment --comment "HTTP(80) Port Forwarding from ETH0" -j DNAT --to-destination 172.16.0.100:80
    2. Internal clients overload over NAT
      iptables -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/24 -j MASQUERADE
    3. Transparent port redirects. Example redirects destination port from 553 to 53.
      iptables -A PREROUTING ! -s 192.168.0.0/24 -p tcp --dport 553 -j DNAT --to-destination 192.168.0.2:53

      NOTICE: This rule will only be triggered when the source IP comes from another network.

    That’s it, there are a lot of different scenarios that you can use IPTABLES for. These are just some IPTABLES that can be used. Port Forwarding, IP Masquerading, Port Redirects, etc.

    Sources: