DMZ setup with router Asus RT-N56U

I am working on a home web server setup. I would like to minimize potential damage in the event that this server gets compromised. The solution is to put it into a separate network with minimal access to the rest of my home network. This is usually referred to as DMZ, demilitarized zone.

To follow this tutorial you need to be comfortable with using ssh, vi, and iptables. I also assume that you have a static IP address from your Internet provider. My workstation is running Linux so if you use different platform, you might need to adjust some steps a little bit.

Here is what I intend to achieve with my setup:

Home router DMZ setup

Most home routers don’t have such functionality available by default. However some devices are supported by free software projects like OpenWrt, DD-WRT, pfSense, or Tomato, that can be configured that way.

My router Asus RT-N56U is supposedly supported by OpenWrt (which I never tested myself). The other alternative firmware I found that supports it is called Padavan. I will describe how to setup DMZ using the latter.

1. Download and installation

Download the files from https://code.google.com/p/rt-n56u/ – section Downloads link for [RT-N56U]. I chose following files:

  • RT-N56U_3.4.3.9-095_base.trx
  • RT-N56U_3.4.3.9-095_base.md5

There are other builds available that include optional extra functionality. See Firmware Builds page for details. Once you download your files check the MD5 checksum and compare with the content of your md5 file.

md5sum RT-N56U_3.4.3.9-095_base.trx

Install the firmware by using your current Asus Administrator interface at http://192.168.1.1/ (Advanced Settings > Administration – Firmware Upgrade).

2. Port isolation and firewall setup

In usual home router all network ports belong to one common network interface inside the router. What we need to do to achieve efficient traffic isolation is to setup completely separate network interface for the DMZ port. If you have any doubts do some reading on how easy it is to spoof IP address and MAC address. DMZ functions that some home routers advertise are insecure, unless they include network interface separation.

So how can we achieve such network interface/port isolation with Padavan? The answer is buried deep on Russian forums, since the developer is Russian. You can see the original question by user xedoc and Padavan’s response here: http://forum.ixbt.com/topic.cgi?id=14:58134-120

a) Setup in web console

We will start by logging into the router web console again. Setup a strong password for your administrative account (Advanced Settings > Administration – System, System Identification section).

Make sure IPv6 traffic is disabled (Advanced Settings > WAN – IPv6 Protocol, IPv6 Connection Type: Disabled). Leaving IPv6 on may open up unexpected ways to bypass your firewall if you are not careful.

Then go to Advanced Settings > LAN – LAN IP and check that your router IP address and subnet mask are on defaults:

  • IP Address: 192.168.1.1
  • Subnet Mask: 255.255.255.0

Check that your DHCP Server (Advanced Settings > LAN – DHCP Server) is setup for the same range, for example:

  • IP Pool Starting Address: 192.168.1.100
  • IP Pool Ending Address: 192.168.1.200

Now the first step of the actual port isolation setup. Go to Advanced Settings > WAN – Internet Connection and select:

  • Choose IPTV STB Port: LAN1 (this will become the isolated DMZ port)
  • WAN Cable is Attached to Port: WAN
  • IPTV STB Port(s) Isolation: Isolation between WAN Bridge Ports

In order to complete the rest of the setup we need to enable SSH access to the router. Go to Advanced Settings > Administration – Services:

  • Enable SSH Server: Yes

See also screenshots:

LAN IP Settings  DHCP Server Settings  Port Isolation Settings  Enable SSH Settings

b) Configure the rest from command line

With the GUI setup out of the way we can get to the fun part. Login to your router via SSH:

ssh admin@192.168.1.1

We will need to edit two scripts. The first one completes the setup as per Padavan’s post:

cd /etc/storage/
vi post_wan_script.sh

Copy and paste following lines at the end of the script. Please read the original instructions for explanation what each command does. The result is that your LAN port 1 will become isolated on interface eth3.3 while the rest of the LAN ports are still on eth2 (which is part of bridge br0). See also listing of all standard network interfaces in Mini FAQ. The last line defines gateway IP and subnet for our DMZ:

vconfig add eth3 3
ifconfig eth3.3 up
rtl8367 63 0x00500050 0x00020002
rtl8367 63 0x00010041 0x00030003
rtl8367 62 0x40 0
ifconfig eth3.3 192.168.2.1 netmask 255.255.255.0 broadcast 192.168.2.255 up

Now it is time to define some firewall rules. I want to send all syslog messages to my SAN so I need to allow UDP traffic to port 514 into my 192.168.1.0/24 network. I also allow the server in DMZ to talk to outside Internet on http/https, DNS lookups, NTP, and ICMP. Everything else gets logged and rejected. The same goes for any traffic to the router itself. You should keep traffic originating from DMZ as tightly controlled as possible. It is perfectly fine to be paranoid when setting up computer systems.

vi post_iptables_script.sh

Add your firewall rules at the end of the script. Here is my example. Note that the address to SNAT to will be your static public IP address and 192.168.1.xxx is my NAS running rsyslog server:

# NAT 192.168.2.0/24 on the way out to Internet
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth3 -j SNAT --to xxx.xxx.xxx.xxx
# Log and reject all traffic from DMZ to router
iptables -I INPUT -i eth3.3 -j REJECT
iptables -I INPUT -i eth3.3 -m limit --limit 10/h --limit-burst 3 -j LOG --log-prefix="iptables: rejected INPUT: " --log-level alert
# Allow DMZ logging to rsyslog server
iptables -A FORWARD -i eth3.3 -p udp -d 192.168.1.xxx --dport 514 -j ACCEPT
# Allow DMZ http, https to all internet (for various reasons)
iptables -A FORWARD -i eth3.3 -o eth3 -p tcp -m multiport --dports 80,443 -j ACCEPT
# Allow DNS lookups from Google servers in DMZ
iptables -A FORWARD -i eth3.3 -o eth3 -p udp -d 8.8.8.8 --dport 53 -j ACCEPT
iptables -A FORWARD -i eth3.3 -o eth3 -p udp -d 8.8.4.4 --dport 53 -j ACCEPT
# Allow UDP to port 123 @ Ubuntu NTP servers in DMZ
iptables -A FORWARD -i eth3.3 -o eth3 -p udp -d 91.189.89.199 --dport 123 -j ACCEPT
iptables -A FORWARD -i eth3.3 -o eth3 -p udp -d 91.189.94.4 --dport 123 -j ACCEPT
# Allow ICMP protocol (for example ping an outside address from DMZ)
iptables -A FORWARD -i eth3.3 -o eth3 -p icmp -j ACCEPT
# Reject and log everything else from DMZ to anywhere
iptables -A FORWARD -i eth3.3 -m limit --limit 10/h --limit-burst 3 -j LOG --log-prefix="iptables: rejected FORWARD: " --log-level alert
iptables -A FORWARD -i eth3.3 -j REJECT

In order to make the above work you can simply run the scripts or you can reboot your router. Once you have done that, check the effect on iptables chains:

iptables -L -v -n --line-numbers
iptables -t nat -L -v -n --line-numbers

3. Server configuration

I need to setup a static IP address for my server running Ubuntu Server:

cd /etc/network
sudo cp interfaces{,.bak}
sudo nano -w interfaces

Original setup:

# The primary network interface
auto p2p1
iface p2p1 inet dhcp

Replace with static definition (pick your own IP address within the range):

# The primary network interface
auto p2p1
iface p2p1 inet static
address 192.168.2.xxx
netmask 255.255.255.0
gateway 192.168.2.1
dns-nameservers 8.8.8.8 8.8.4.4

Add a new section for your public IP address as a second IP address. This will be useful if your application wants to talk to itself on this IP address:

# add second static IP address
auto p2p1:0
iface p2p1:0 inet static
address xxx.xxx.xxx.xxx
netmask 255.255.255.255

Reboot the server and check if everything works as expected:

sudo shutdown -r now
ifconfig

4. Port forwarding

Once your server is ready for its prime time, you can setup port forwarding. In my case I will be forwarding port 80 (http) onto my server in DMZ. In the router GUI, Advanced Settings > WAN – Port Forwarding:

  • Enable manual port forwarding.
  • Add a line and apply (using your specific server IP address):

Service Name: HTTP
Source IP:
Port Range: 80
Local IP: 192.168.2.xxx
Local Port: 80
Protocol: TCP

5. Drop private network address on public interface

There is a number of extra things that you can setup on your router. It all depends on your needs and functions you want to implement. One simple and useful thing is to block all traffic coming in from Internet pretending to be your local traffic. As far as I know there is no legitimate use for such IP spoofing. So you can safely send them into the black hole of naughty packets. As per section 8 in http://www.cyberciti.biz/tips/linux-iptables-examples.html:

IPv4 Address Ranges For Private Networks (make sure you block them on public interface)

10.0.0.0/8 -j (A)
172.16.0.0/12 (B)
192.168.0.0/16 (C)
224.0.0.0/4 (MULTICAST D)
240.0.0.0/5 (E)
127.0.0.0/8 (LOOPBACK)

I like to log all possibly naughty traffic (with some rate limiting of course) before I reject or drop it. This way I can review my logs and see if anything untoward was happening. To implement the suggested blocking in your router firewall add following rules to post_iptables_script.sh. Note that we are inserting the checks into both INPUT and FORWARD chains. If you need to refresh your understanding why we do that, see the diagram in chapter on traversing of tables and chains of iptables tutorial.

# Drop Private Network Address On Public Interface
# create new chain that logs (with rate limiting) and drops all packets
iptables -N logdrop
iptables -A logdrop -m limit --limit 1/m --limit-burst 5 -j LOG --log-prefix="iptables: dropped spoofing: " --log-level alert
iptables -A logdrop -j DROP
# create new chain that checks source address - if it belongs to private ranges log and drop the traffic
iptables -N checkspoof
iptables -A checkspoof -s 10.0.0.0/8 -j logdrop
iptables -A checkspoof -s 172.16.0.0/12 -j logdrop
iptables -A checkspoof -s 192.168.0.0/24 -j logdrop
iptables -A checkspoof -s 224.0.0.0/4 -j logdrop
iptables -A checkspoof -s 240.0.0.0/5 -j logdrop
iptables -A checkspoof -s 127.0.0.0/8 -j logdrop
# send all traffic from public interface for check on private range spoofing
iptables -I INPUT -i eth3 -j checkspoof
iptables -I FORWARD -i eth3 -j checkspoof

I hope this tutorial will be useful for a few people. If you spot any issues please leave a comment.

Advertisements

3 comments

  1. Pingback: Building a small server for photography website | freeandthings

  2. Pingback: How to generate iptables rules for smtp.gmail.com « freeandthings


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s