IPtables for Ubuntu 13 Web Servers

Overview

Whether your web application server is behind a hardware firewall or not, an internal firewall should also be used to further protect the server. Your web server should not be able to communicate with any other servers, unless communication is required by your application. And even then, only the ports, protocols, and packet directions needed should be allowed. All other incoming and outgoing communications should be blocked. Fencing your server off in this manner prevents attackers from using it as a gateway into other servers in your environment. It also lessens the risk of your server sending unsolicited communications from ports and protocols not defined in your policy. In this lab I will guide you through creating a baseline firewall policy using IPtables for a web server.

Lab Configuration

The lab will consist of the following server configurations:

Name OS Role Network Interface
WEBAPP01 Ubuntu 13.10 Web Application Server ETH0 – 172.30.0.50
WEBDB01 Ubuntu 13.10 MySQL Database Server ETH0 – 172.16.0.22

And the following networks exist in the environment.

Network Purpose
172.30.0.0/24 DMZ
172.16.0.0/24 Internal Production Servers
172.20.0.0/24 Internal network for IT

Firewall Policy

Always define a firewall policy for your publicly accessable servers and enforce it. Your company or web application may have different requirements, however, as an example, the following policy will be applied to our firewall on our web server and its database server.

  • All incoming and outgoing connections are to be dropped by default.
  • Only allow incoming SSH connections from internal network.
  • Only allow tcp connections on port 3306 between Webapp01 and Webdb01.

Disabled UFW

UFW is a basic frontend for Iptables on Ubuntu computers. Since we’re going to use IPtables directory to allow for more custom rules, we need to ensure UFW isn’t enabled.

  1. Check to see if UFW is enabled.
    sudo ufw status
  2. If UFW is enabled, disable it.
    sudo ufw disable

Create a Base Policy Script

  1. Create a new file named iptables-policy.sh
  2. Add the following lines to the file:
    # Drop all packets by default
    iptables -P INPUT DROP
    iptables -P FORWARD DROP
    iptables -P OUTPUT DROP
    
    # Drop invalid packets
    iptables -A INPUT -m state --state INVALID -j DROP
    iptables -A FORWARD -m state --state INVALID -j DROP
    iptables -A OUTPUT -m state --state INVALID -j DROP
    iptables -A INPUT -p TCP -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
    iptables -A INPUT -p TCP -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
    
    # Allow remote ssh connections from internal network only.
    iptables -A INPUT -i eth0 -s 172.20.0.0/24 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
    iptables -A OUTPUT -o eth0 -d 172.20.0.0/24 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
    
    # Allow MySQL queries to and responses from our database server, WEBDB01, only.
    iptables -A OUTPUT -o eth0 -d 172.16.0.22 -p tcp --dport 1306 -m state --state NEW,ESTABLISHED -j ACCEPT
    iptables -A INPUT -i eth0 -s 172.16.0.22 -p tcp --sport 1306 -m state --state ESTABLISHED -j ACCEPT
    
    # Allow HTTP traffic in
    iptables -A INPUT -i eth0 -p TCP --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
    iptables -A OUTPUT -o eth0 -p TCP --sport 80 -m state --state ESTABLISHED -j ACCEPT
    
    # Save and apply policy
    /sbin/service iptables save
  3. Save changes to the script file and exit the text editor.
  4. Ensure the script can be executed by you.
    sudo chmod u+x ./iptables-policy.sh
  5. Run the script to apply the new policy.
    ./iptables-policy.sh

Allow Installs from Ubuntu Repositories

You’re eventually going to need to install system updates or new applications from the Ubuntu repository. Our base policy blocks all new outgoing HTTP connections. To allow these connections, we need to add a few extra lines to our policy script.

  1. Open iptables-policy.sh into a text editor.
  2. Above the iptables save command, add the following lines:
    # Allow HTTP traffic out
    iptables -A OUTPUT -o eth0 -p TCP --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
    iptables -A INPUT -i eth0 -p TCP --sport 80 -m state --state ESTABLISHED -j ACCEPT
  3. Save changes and exit the text editor.
  4. This will allow HTTP connections out, but without DNS you won’t be able to do name resolution. To allow DNS lookups, see Allow DNS Lookups below.

Allow DNS Lookups

Unless you allow DNS related connections out, you will need to connect to everything via an IP address. To allow queries to a DNS server, we need to add another rule.

  1. Open iptables-policy.sh into a text editor.
  2. Above the iptables save command, add the following lines:
    # Allow DNS lookups
    iptables -A OUTPUT -o eth0 -p UDP --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
    iptables -A INPUT -i eth0 -p UDP --sport 53 -m state --state ESTABLISHED -j ACCEPT
  3. Save your changes and exit the text editor.
  4. Execute the iptables-policy.sh script to apply our new rules.