Cheap Linux Firewall - IPTables on the WRT54G

I’m currently using the DD-WRT firmware on this platform, however these instructions should work for other firmware which contains IPTables as well.

Instructions for upgrading your router to DD-WRT can be found at James Stephens Blog or on the DD-WRT wiki under Installation.

A lot of the rules are generic and with a little tweaking can be applied to other platforms.

It is important to note that unlike a standard Linux router, with interfaces labelled as eth0, eth1 etc, the WRT54G has a single switch split into Virtual LANS.

  • vlan1 is the WAN interface.
  • vlan0 is the LAN interface(s).
  • eth1 is the Wireless interface.
  • br0 is a bridge comprising of eth1 and vlan0

Any external address applied to the router through the web-interface is applied to vlan1, the internal address is applied to br0, and is therefore available to all internal clients.

Before designing IPTables rules it is useful to examine the diagrams here, and understand where traffic flows in relation to the interfaces above.

Traffic heading in or out of the router, for example to it’s external address or internal address will hit the input and output chains.

Traffic which is destined for other hosts, such as those defined by the static NAT rules explained here, will pass through the forward chain of the router.

I’ve covered using custom chains to achieve greater efficiency and carry out multiple tasks previously.

Firstly on the router we need to clear the chains that are set-up by the web interface. James Stephens provides a good way to do this in his example scripts which are on his site at http://www.sns.ias.edu/~jns.

# Set default policies to ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT

# Flush all tables and chains.
cat /proc/net/ip_tables_names | while read table; do
iptables -t $table -L -n | while read c chain rest; do
if test “X$c” = “XChain” ; then
iptables -t $table -F $chain
fi
done
iptables -t $table -X
done

# Zero counters.
iptables -Z

This allows us to start with a fresh IPTables set-up, allowing the script to be run at any time, not just on start up.

Now add these rules:

# Allow all loopback traffic
iptables -A INPUT -i lo -m state –state NEW -j ACCEPT
iptables -A OUTPUT -o lo -m state –state NEW -j ACCEPT

# Allow all ESTABLISHED and RELATED traffic
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state –state ESTABLISHED,RELATED -j ACCEPT

# Allow all LAN traffic to router
iptables -A INPUT -i br0 -s $LANIP -m state –state NEW -j ACCEPT

# Allow all traffic from router to ANY
iptables -A OUTPUT -m state –state NEW -j ACCEPT

# Allow all traffic from LAN to ANY
iptables -A FORWARD -s $LANIP -m state –state NEW -j ACCEPT

This allows connections that are already in progress when the script is run, as well as accepting new connections. We also allow traffic from the LAN interface to reach the router and allow the router to talk to other systems.

Finally we need to enable IP Forwarding to allow routing to continue, and tighten out default policies.

# Tighten Default policies.
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP

# enable IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

This gives a blank slate to build on. I recommend adding some of the general security IPTables rules I’ve posted here, or looking at my example scripts.

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.

July 18th, 2007
By Joe | filed under Firewall, Network |