Setting up DMZ with multiple static IPs on an office LAN using DD-WRT

Note: This post should be an article in the DD-WRT wiki. If it looks OK, I’ll post it there later – its here so people can comment on it.

This is the story of how I managed to setup a DD-WRT powered router for my office LAN, with multiple static IPs (from a DSL connection) on a DMZ. It was kind of trial and error because I couldn’t find a good reference on how to do such a thing (or in any way use static IPs without port mapping or DNAT) – so I decided to write one.

Things that you’ll need

  • A router running DD-WRT v23 SP2
  • A DSL connection, recommended with a static IP
  • An additional block of static IPs mapped to your DSL connection by your ISP
  • An SSH client to connect to the router – I use Linux, so I got one with the operating system, and so do MacOS-X users. MS-Windows users can download the free Putty client, or use some commercial software.

This is my current setup

  • I got a Linksys WRT54GL v1.1 router. Installing DD-WRT on it was not difficult and its clearly explained in The DD-WRT installation manual. If you break anything, its easy to reflash the router using TFTP (also explained there), so don’t worry too much. Do make sure to download both the “mini” version of the firmware and the one you finally would want to install (I used the “vpn” version) before you start as it will save you a lot of time
  • I got a DSL connection from an Israeli provider named Netvision. They are notorious for their lousy tech support, and couldn’t help me one little bit – but most chances are you’re not going to need tech support help for this – you can mess up on your own ;-). I have a static IP on a PPPoE connection, which shall hence forth be known as 1.2.3.4
  • I got an additional block of 8 IP addresses, which I shall dub 5.5.5.0/29 (also known as 5.5.5.1-5.5.5.6 as the first address is the network address and the last is the broadcast address, leaving 6 usable IPs)

Basic Setup
The first thing you need to do is to setup your router to dial up to the DSL. This should be fairly easy if you’ve ever done this before, and the DD-WRT interface for setting up the network is almost identical to the original Linksys interface – to the point that if your browser saved you the dial-up user name and password when you set it up before, it will gladly fill them up for you again in the DD-WRT setup. I’m assuming the rest of the configuration you are doing from a computer connected to the first LAN port of the router. Note that the first LAN port is the port farthest away from the WAN port, and not the one that is connected to the led marked in “1” (see discussion below).

Once that done, we can go on to the interesting stuff – start by setting up the administrator password by going to “Administration->Management”. Enter ‘root’ as the username and some complicated password as many times as needed. Also enable the “SSH Management” in the “Remote Access” section. Then click on “Save Settings” at the bottom of the page. Doing this would disable the telnet interface (which is always open without a password – this is a bad thing) and would enable the SSH access (that is secure and encrypted – this is a good thing). Note that the SSH access is open by default to all networks – LAN, DMZ and the public internet. I don’t mind so much and so this article would say nothing more about this, but its possible to limit access in several different ways.

Setting up the DMZ virtual LAN interface
Now we need to set up our VLAN – we will use the router’s built-in switch’s VLAN capabilities to setup one port on the switch to serve as a DMZ area, saving 3 ports for the LAN. You can setup different ports, by changing the VLAN configuration as we’ll discuss immediately, but it is sometimes tricky to get it right, and easy to lock yourself outside the router. At any point always keep port number 1 on the vlan0 port list, as some routers would refuse to be reflashed from TFTP if that is not the case – making it impossible to fix a broken router.

Start by checking out your current VLAN configuration – SSH to the router, which should have the IP address of 192.168.1.1 (if you haven’t changed it) – type ‘root’ as the username and whatever you put in the web interface as the password. Then type at the command prompt:

nvram show | grep vlan.ports

This should show you your current vlan configuration as it is stored in the router’s NVRAM (non-volatile RAM – where the router stores its configuration). It should look like this:


vlan0ports=0 1 2 3 5*
vlan1ports=4 5

The WRT router has 6 ports on its internal switch – 4 ports are used as the LAN ports, 1 as the WAN port, and the last one is hardwired into the router’s network interface. The ports are then split into VLANs – one VLAN allows the router to have its own network interface talk to the WAN (wide area network – the external interface), and another VLAN lets the router talk with devices on the local area network (LAN). When router sends a packet, it marks the packet with the VLAN that it should go out on – so packets destined to the public internet are marked as VLAN 1 and are sent from port 5 to port 4, while packets destined to the local network are marked with VLAN 0 and are sent to the switch from port 5 to be distributed to the correct device in ports 0, 1, 2 or 3. Its important to note that the 5 external ports are ordered from 0 near the power port to 4 which is the WAN port – exactly the opposite of what the leds for the ports are marked, with led “1” being physical port 3 and led “4” being physical port 0.

Now to create our new vlan – lets say we want to take port 3 (the right most port, looking at the front of the router, the one closest to the WAN port) and make it into our DMZ VLAN – we will execute the following commands:


nvram set vlan0ports="0 1 2 5*"
nvram set vlan2ports="3 5"
nvram set vlan2hwname=et0
nvram commit

The first two commands reassign port 3 to the newly created vlan2. The third command assigns vlan2 to the first network interface (eth0 – the et0 shorthand is a vxworks legacy name that was kept by the OpenWRT guys for their nefarious purposes). The last commands writes all the changes to the persistent configuration memory.

Now that we built our new vlan, its time to tell DD-WRT about it – open the web interface for the router again, and under “Setup” goto “VLANs”. Note that in the web interface, the port numbering is different once more – the WAN port is marked with a W, and the LAN ports are marked as 1 to 4 which corresponds to physical ports 0 to 3, and leds 4 to 1 (leds are exactly reversed then the port numbers in the DD-WRT configuration). Because we set port 3 to VLAN 2, we need to change the VLAN port configuration in the DD-WRT web interface by unchecking the port “4”/VLAN 0 checkbox and checking the port “4”/VLAN 2 checkbox. Then hit “Save settings”.

On to the new DMZ network
It not strictly necessary to have a static IP on the DSL connection for additional IPs to be assigned, but its probably what you are going to get – and anyway I don’t think the configuration is different for dynamic IP as we don’t mess around with the DSL connection. The additional static IP address block your ISP assigned to you should already be routed through your DSL dial-up connection so no extra setup should be necessary – we will simply setup the router’s DMZ leg (the vlan2 network interface) with one IP address – usually the first one, the other devices on the network with the other addresses, and let the Linux TCP stack in the WRT router do the rest – with a little help from us.

The first step is to setup the IP address for the router – from the router web interface choose “Administration” and then “Commands”. Now in the “Command Shell” box, type this:


#!/bin/ash
PATH="/sbin:/usr/sbin:/bin:/usr/bin:${PATH}"
ifconfig vlan2 5.5.5.1 netmask 255.255.255.248 up

The above example sets up the first host IP (after the network address) of an 8 IPs block, and its netmask. As a reminder, the IP block assigned to us is 5.5.5.0 to 5.5.5.7, with 5.5.5.0 as the network address and 5.5.5.7 as the broadcast address, with the valid host addresses between them – this results in a netmask of 255.255.255.248 (or 29 network bits). If you get a different number of IP addresses, you’d have to compute your netmask yourself. The GNU command line utility ipcalc is very useful, but if you don’t have a Linux computer handy then there are lots of web based tools to address the problem.

Now hit “Save Startup” – the script above will now be run at the end of the router startup sequence, and it will setup the IP address on the vlan2 network interface – the one assigned to the DMZ VLAN.

This should be enough for basic routing to work, but the standard DD-WRT firewall is very restrictive and won’t let you do much of anything with the new interface – so we’d need to fix the firewall. Type the following commands back into the “Command Shell” box:


# add input rules to mimic br0 behavior
iptables -I INPUT 4 -j DROP -p udp -i vlan2 --dport 520
iptables -I INPUT 7 -j logaccept -i vlan2 -m state --state NEW
# allow packets from the network, destined to the DMZ
iptables -I INPUT 8 -j ACCEPT -d 5.5.5.0/29 -m state --state NEW


# allow access from LAN to DMZ
iptables -I FORWARD 4 -j ACCEPT -i br0 -o vlan2 -m state --state NEW
# allow access from DMZ to WAN
iptables -I FORWARD 3 -j ACCEPT -i vlan2 -o ppp0
# allow access from WAN to DMZ
iptables -I FORWARD 4 -j ACCEPT -i ppp0 -o vlan2


# disable masquerading on real IPs in DMZ
iptables -t nat -I POSTROUTING 0 -j ACCEPT -o ppp0 -s 5.5.5.0/29

Then click on “Save Firewall”. The first section sets up our new vlan2 interface to be able to receive IP packets from the WAN, in a very similar fashion to how DD-WRT does by default for the LAN interface (including the dropping of UDP port 520, which I’m not sure what it does). The second section sets up what kind of interactions between the 3 different networks we allow: we want to be able to access the DMZ from the LAN, but not the other way around, and we want to be able to access the DMZ from the WAN and vice versa. The last section disables the masquerading for the DMZ – by default the router assigns private (non-routeable) addresses to the LAN and then uses “masquerading” – a technique to translate private to real IP addresses and back – to hide the private IPs when you access the internet. Because the DMZ uses real IP addresses assigned to you by your ISP, we don’t want to have masquerading enabled for these.
Theoretically, I don’t need to specify the IP address range for the POSTROUTING rule, and I probably don’t want to – I can use a “mangle” rule to mark incoming packets from VLAN2 and have the POSTROUTING rule match on the mark – but I couldn’t get it to work: it didn’t want to mark packets from my DMZ, so I gave up on it.

Additional Services
The last step is to setup DNS services for your DMZ network – for devices on your DMZ network you’d want the simplest network setup possible, and unless you’re going to equip every server on the DMZ with a resolving DNS server, then you probably want the router to do DNS caching for you. Once you have that setup, network setup on DMZ devices is very easy – just setup the IP address as 5.5.5.x, netmask 255.255.255.248, DNS 5.5.5.1 and thats it.

For this to work, we need to tell the WRT’s internal DNS server to listen on the vlan 2 – so, under “Administration” in the web interface, find “Services” and find the “DNSMasq” section. In the “Additional DNS option”, on a line of its own, add:

interface=vlan2

And click “Save Settings”.

That’s it – configuration is complete. Once the router has saved the last settings change, its a good time to reboot the router – just click on the “Reboot Router” button and wait. Due to the more complex setup, it takes the router about a minute more after the web interface comes back, for the new network configuration to take effect.

To test it, you can now point your web browser to the router’s DMZ address – http://5.5.5.1 (while you are still using the computer connected to the LAN port). You should get the router’s web interface again, if so everything is working – you just need to connect some sort of switch to your DMZ port and start setting up your server. If it doesn’t come up – go back and make sure you have completed all the steps correctly.

Possible Problems
There are a few issues with this setup, which I don’t think are major but there are security implications:

Due to the fact that the DMZ is completely exposed to the public internet, the router’s DMZ leg is exposed to both the LAN, the DMZ and the WAN. the first two are unavoidable, but people would probably be less comfortable with having the internal interface of the router exposed to the public internet, especially with the web interface and all. To disable that, you can go back to the “Commands” panel and click on “Edit” in the “Firewall” box. The web interface now has the firewall configuration in the “Command Shell” box. Now add at the bottom of the box, the following lines:


# make the router's DMZ leg inaccessible to the world
iptables -I INPUT 5 -j DROP -i ppp0 -d 5.5.5.1 -p tcp --dport 80

The above would work if you want only to disable access to the web interface. If you want to stop all access to the router’s DMZ ip address, then use this:


# make the router's DMZ leg inaccessible to the world
iptables -I INPUT 5 -j DROP -i ppp0 -d 5.5.5.1

After saving the firewall script, wait a couple of minutes for the firewall to refresh – there’s no need to reboot.

Another issue is that devices on the DMZ can access the router’s leg on the LAN – the private internal ip address of the router, which is 192.168.1.1 by default. DMZ devices can’t access anything else on the LAN, but the default firewall setup of the DD-WRT explicitly allows anything to get to 192.168.1.1 (presumably so you wont lock yourself out of your router configuration interface), and I didn’t want to mess with it.

That’s it, we’re done here. I’d appreciate any comments on this article – especially if you’d like to try this at home and tell me how it went. Good luck!

14 Responses to “Setting up DMZ with multiple static IPs on an office LAN using DD-WRT”

  1. Joksi:
    Fatal error: Uncaught Error: Call to undefined function comment_dir() in /vhosts/coil/geek/public_html/wp-content/themes/modern-bluish/single-comment2.php:17 Stack trace: #0 /vhosts/coil/geek/public_html/wp-content/themes/modern-bluish/functions.php(8): include() #1 /vhosts/coil/geek/public_html/wp-includes/class-walker-comment.php(179): themed_comment() #2 /vhosts/coil/geek/public_html/wp-includes/class-wp-walker.php(144): Walker_Comment->start_el() #3 /vhosts/coil/geek/public_html/wp-includes/class-walker-comment.php(139): Walker->display_element() #4 /vhosts/coil/geek/public_html/wp-includes/class-wp-walker.php(387): Walker_Comment->display_element() #5 /vhosts/coil/geek/public_html/wp-includes/comment-template.php(2229): Walker->paged_walk() #6 /vhosts/coil/geek/public_html/wp-content/themes/modern-bluish/comments.php(26): wp_list_comments() #7 /vhosts/coil/geek/public_html/wp-includes/comment-template.php(1539): require('/vhosts/coil/ge...') #8 /vhosts/coil/geek/public_html/wp-content/themes/modern-bluish/single.php( in /vhosts/coil/geek/public_html/wp-content/themes/modern-bluish/single-comment2.php on line 17