In continuation of my previous article on installing OpenWRT on a Linksys WRT54GL, I discuss how to set some of the more advanced network configurations of the router, and how to setup a firewall with traffic shaping.
Controlling the Network Switch
If you’ve had a chance to look at the hardware layout of the WRT54GL, you will notice that the router uses VLAN tagging to seperate the WAN port from the rest of the switch. This VLAN configuration settings are stored in NVRAM and, as such, we can modify them to our heart’s content. The WRT54G series router’s switch supports up to 15 VLAN tags which, since there are only 6 switch ports, is overkill. By default, your router will have the following vlan configuration settings: (you can get/set these using nvram)
vlan0ports="3 2 1 0 5*" vlan0hwname=et0 vlan1ports="4 5" vlan1hwname=et0
For a quick explanation; Each vlan’s setting are defined in vlan[#][setting]. Ports defines which ports belong to that vlan, and must always include port 5 or the vlan will not be able to talk to the router (making it essentially useless). The asterisk next to the 5 at the end of the ports list indicates that this vlan is the default vlan. Hwname is the physical port the switch is connected to, and should always be et0 for the WRT54GL.
If you would like to add a DMZ to your router, you can set your nvram settings as such: (this makes port 4 (internal 0) the DMZ)
vlan0ports="3 2 1 5*" vlan0hwname=et0 vlan1ports="4 5" vlan1hwname=et0 vlan2ports="0 5" vlan2hwname=et0
Now that you have the vlan tagging setup properly, you will need to initialize the interface within OpenWRT. First, setup your configuration options for the DMZ zone:
dmz_ifname=vlan2 dmz_proto=static dmz_ipaddr=192.168.3.1 dmz_netmask=255.255.255.0
Then, make sure in /etc/init.d/S40network that the following line exists:
ifup dmz
At bootup, when the S40network script is run, ifup will look for all nvram settings starting with dmz_ and use them to initialize the interface. It is also smart enough to look at [name]_ifname and determine if it is ethernet interface, vlan, or bridge.
For example, if you look at your lan settings (nvram show | grep "lan_"), it will look something like this:
lan_ifname=br0 lan_ifnames="vlan0 eth1 eth2 eth3" lan_proto=static lan_ipaddr=192.168.1.1 lan_netmask=255.255.255.0
What’s happening here is that the lan interface is a bridge of vlan0 (LAN) and eth1 (Wifi). (Don’t ask about eth2 & eth3, I have no idea why they are there)
If you would like to seperate the LAN from the Wifi network, change your settings to:
lan_ifname=vlan0 lan_ifnames="vlan0 eth2 eth3" lan_proto=static lan_ipaddr=192.168.1.1 lan_netmask=255.255.255.0 wifi_ifname=eth1 wifi_proto=static wifi_ipaddr=192.168.2.1 wifi_netmask=255.255.255.0
Then make sure /etc/init.d/S40network has the following line within it:
ifup wifi
Just reboot and your seperated.
Note that if you are adding more zones to your router, you should also configure your other services such as firewall script and DHCP client to take advantage of the new configuration.
For dnsmasq, you should add something like the following to /etc/dnsmasq.conf:
dhcp-range=lan,192.168.1.100,192.168.1.199,255.255.255.0,24h dhcp-range=wifi,192.168.2.100,192.168.2.199,255.255.255.0,1h dhcp-range=dmz,192.168.3.100,192.168.3.199,255.255.255.0,24h
You should also allow the “safe” zones to talk among each other by adding the following firewall rules to /etc/init.d/S45firewall:
... WIFI=$(nvram get wifi_ifname) #add if LAN/Wifi are seperated DMZ=$(nvram get dmz_ifname) #add if you have a DMZ zone ... #replace references to br0 iptables -A FORWARD -i $LAN -o $LAN -j ACCEPT iptables -A FORWARD -i $LAN -o $WAN-j ACCEPT #add if wifi is seperated iptables -A FORWARD -i $LAN -o $WIFI-j ACCEPT iptables -A FORWARD -i $WIFI-o $LAN -j ACCEPT iptables -A FORWARD -i $WIFI-o $WAN-j ACCEPT iptables -A FORWARD -i $WIFI-o $WIFI-j ACCEPT #add if dmz is available iptables -A FORWARD -i $LAN -o $DMZ -j ACCEPT iptables -A FORWARD -i $WIFI -o $DMZ -j ACCEPT #if wifi is also seperated ...
Firewall Made Easy
Despite your experience with iptables, this network routing program is hard to read and even harder to remember all the switches when its time to add a new rule to your firewall. Thankfully there is a much easier way to configure your firewall, and it’s called Shorewall.
The Shoreline Firewall, more commonly known as “Shorewall”, is a high-level tool for configuring Netfilter. You describe your firewall/gateway requirements using entries in a set of configuration files. Shorewall reads those configuration files and with the help of the iptables utility, Shorewall configures Netfilter to match your requirements.
You can download one of the latest builds of Shorewall for the OpenWRT from Fabio Longarai’s OpenWRT site. To install Shorewall, it’s as simple as:
cd /tmp wget http://openwrt.homelinux.net/shorewall_x.x.x_mipsel.ipk ipkg install shorewall_x.x.x_mipsel.ipk rm shorewall_x.x.x_mipsel.ipk
Note that the following guide was written for Shorewall v3.0.4-2.
All your configuration files can be found in /etc/shorewall/. Since every person’s needs and router settings are unique, their firewall will be unique as well. As such, the following configuration settings are stereotypical settings only and should be customized to one’s needs. For more information on configuring Shorewall, please see the official documentation.
For beginners to Shorewall, I recommend tackling the firewall files in the following order:
zones
This file specifies the available zones you want to control by your firewall. The names of zones are nothing more then aliases, and as such Shorewall has no understanding of the meaning of them. Do not assume a zone called DMZ will behave like a DMZ zone.
############################################################################### #ZONE TYPE OPTIONS IN OUT # OPTIONS OPTIONS fw firewall lan ipv4 wifi ipv4 dmz ipv4 wan ipv4 #LAST LINE
policy
This file defines the default behavior for a zone. Any zone is allowed to talk to itself, so you don’t need to specify a zone in both the source and destination. Also, (assuming your networking is A->FW->B) just because A can talk to FW, doesn’t mean that A can talk to B - you must explicitely define it.
You can also, in this file, define what the default behavior of traffic being forwarded from one zone to another is and the type of logging the firewall does.
############################################################################### #SOURCE DEST POLICY LOG LIMIT:BURST # LEVEL fw all ACCEPT lan all ACCEPT wifi all ACCEPT dmz fw ACCEPT dmz wan ACCEPT dmz all REJECT notice wan dmz ACCEPT wan all DROP all all REJECT notice #LAST LINE
interfaces
In this file, you define the interfaces and how they map to the available zones. You can also specify options on restricting what types of erronious traffic can be let through.
############################################################################### #ZONE INTERFACE BROADCAST OPTIONS lan vlan0 detect routeback,dhcp wifi eth1 detect routeback,tcpflags,dhcp,routefilter,detectnets,nosmurfs dmz vlan2 detect routeback,dhcp wan vlan1 detect routeback,tcpflags,blacklist,dhcp,routefilter,nosmurfs #LAST LINE
masq
This file defines how source NAT-ing is done through the firewall, and through which interface.
############################################################################### #INTERFACE SUBNET ADDRESS PROTO PORT(S) IPSEC vlan1 vlan0 vlan1 eth1 vlan1 vlan2 #LAST LINE
rules
This is the brain of your firewall, where you define the complicated exceptions to the default policy and let traffic through. A lot can be done in this file, so be sure to read up on it. For this example, I’m going to allow pings to the firewall, and incoming BitTorrent to my main system. The first rules uses a macro while the second is a typical rule that employs DNAT-ing.
############################################################################################################# #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINALRATE USER/ # PORT PORT(S) DEST LIMIT GROUP #SECTION ESTABLISHED #SECTION RELATED SECTION NEW Ping/ACCEPT wan fw DNAT net lan:192.168.1.100 tcp 6881:6889 - #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
routestopped
The rules in this file define the default behavior when Shorewall is stopped. For the most part, to allow “safe” zones to talk properly when Shorewall is stopped, added them to this file as so:
############################################################################### #INTERFACE HOST(S) OPTIONS vlan0 - source eth1 - source vlan2 - source #LAST LINE
tos
Unfortunately, OpenWRT’s iptables does not support TOS, so don’t bother adding any entries to this file.
params
For the most part, if you are doing basic firewalling, you can ignore the rest of the files in this folder. The only other file you may be interested in is params, where you can define variables to be used in the other config files in this directory. For example, you could put in this file…
$LAN_ZONE=lan $LAN_IFNAME=$(nvram get lan_ifname) $LAN_BROADCAST=192.168.1.255 ...
… and then, you could use these variables in your scripts …
/etc/shorewall/interfaces: ... $LAN_ZONE $LAN_IFNAME $LAN_BROADCAST $LAN_OPTIONS ...
… in order to simplify the changing of your network configurations.
Traffic Control
One of my primary goals of setting up a dedicated firewall was to have Traffic Shaping/QoS determine the priority of my internet traffic and adjust accordingly based on the needs to the network. For example, my primary network traffic is VoIP, BitTorrent, and HTTP/web. I want VoIP to have the highest priority of my network communications, while BitTorrent to be the lowest. Therefore, my phone conversations won’t drop when I’m downloading heavy.
In order to use traffic shaping, you must have the tc package installed. You can do this by running:
ipkg install tc
It should be noted before you start that you can only shape outbound traffic. You may ask why, but think about how a network works. The router can only make a decision on what packet has priority over another packet when it has received that packet and examined it. Therefore, it does not make sense to shape incoming traffic since a)your internal network is likely must faster then your incoming internet traffic thus making prioritization useless, and b) you’ve already received the packet, so you might as well just send it on its way (your ISP has determined which packet was important to go down the line first).
tcdevices
First, you need to define the devices on your router you would like to enable traffic shaping on. You can do this by editing the tcdevices config file:
############################################################################### #INTERFACE IN-BANDWITH OUT-BANDWIDTH wan 5mbit 512kbit #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
You should set these settings to your theoretical maximum speed on that line. If traffic starts moving faster then these defined settings, the router will begin dropping packets in order to slow down the traffic.
tcclasses
For my purposes, I created five “buckets” to prioritize my traffic in. Note that a higher priority will get served first (till its empty) before a lower priority is served. In the example below, priority 4 is the default priority and all unmarked traffic will go into this priority queue. I also auto-marked all (small) ACK packets as highest priority to artifically speed up downloads.
############################################################################### #INTERFACE MARK RATE CEIL PRIORITY OPTIONS br1 1 full full 1 tcp-ack #CRITICAL br1 2 full full 2 #HIGH br1 3 full full 3 #NORMAL br1 4 full full 4 default #LOW br1 5 full full 5 #USELESS #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
tcrules
Finally, this is the file where we specify how our traffic is prioritized. I wanted my VoIP traffic to be priority 2, my common internet traffic as priority 3, and my BitTorrent traffic and everything else as 4. The reason I did not make priority 3 my default and then just (add rules to) put BitTorrent in priority 4 is due to the fact that my BitTorrent client does not allow me to define the source ports of outbound traffic. So instead, any unrecognized traffic gets low priority.
In the example below, I specify that Pings & Rdate (time update) requests are highest priority, VoIP traffic & DNS requests are next highest, my common internet traffic (HTTP, SSH, FTP) are next, and everything else is last.
############################################################################### #MARK SOURCE DEST PROTO PORT(S) CLIENT USER TEST # PORT(S) 1 vlan0,eth1 0.0.0.0/0 icmp 8 #Ping 1 vlan0,eth1 0.0.0.0/0 tcp 37 #Rdate 2 vlan0 0.0.0.0/0 udp 5060:5061 #VoIP 2 vlan0 0.0.0.0/0 udp 16384:16482 #VoIP 2 vlan0,eth1 0.0.0.0/0 udp 53 #DNS 2 vlan0,eth1 0.0.0.0/0 tcp 53 #DNS 3 vlan0,eth1 0.0.0.0/0 tcp 80 #HTTP 3 vlan0,eth1 0.0.0.0/0 tcp 22 #SSH 3 vlan0,eth1 0.0.0.0/0 tcp 20 #FTP-DATA 3 vlan0,eth1 0.0.0.0/0 tcp 21 #FTP #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
For more advanced rules, see the docs.
Conclusion
Last thing, in order to start using Shorewall, use the command shorewall start. If you would like to have Shorewall start on bootup, add the following code to /etc/init.d/S46shorewall. (Don’t forget to make it executable: chmod a+x S46shorewall)
#!/bin/bash shorewall start
Please note that you can easily prevent yourself from accessing the CLI with Shorewall. And if Shorewall starts on startup, a reset will not fix the problem. Please thoroughly test your firewall scripts before auto-starting shorewall on startup.
Well, its getting late and I need to crash. I hope you enjoyed the article, and look forward to reading your comments. If you would like more information on a particular section, feel free to drop me a note and I’ll look into updating it. Later!
August 29th, 2006 at 12:35 pm
Gary,
Thank you for this detailed walkthrough! It was exactly what I was looking for. However, after i followed through step by step, I ran into a small problem.
After I rebooted the router, my DNS request stoped working.
ie. I get an IP but cannot goto www.google.com, but can go by http://72.40.xx.xx
I suspect it has to do with:
/etc/dnsmasq.conf vs. /etc/init.d/S50dnsmasq
I stopped using S50dnsmasq and used /etc/dnsmasq.conf only.
Comments in the S50dnsmasq said if I am using /etc/dnsmasq.conf I can get rid of S50dnsmasq.
Thats what I did…
Anycomments appreciated.
Thank you.
August 30th, 2006 at 5:39 pm
Yea, looks like I forgot to comment on that. I commented out, in
S50dnsmasq, the line…args=”-l /tmp/dhcp.leases -K -F $(int2ip $start),$(int2ip $end),$(int2ip $netmask),12h ${wanif:+-I ${wanif} }”
…which essentially removes the overriding configuration options that you then define in
dnsmasq.conf.You do need to have
S50dnsmasqin there in order to start thednsmasqservice.April 20th, 2008 at 4:39 pm
Well, The best firewall i have found in my experience with linux is APF, very simple configuration and work great! Is there a distribution for openwrt???? i googled a lot some minutes ago without answer