Linksys, OpenWRT and multiple VLANs

The Cisco Linksys WRT54G/GS/GL is made up of a six-port configurable switch, a standard Ethernet controller (usually a Broadcom controller named eth0) and a Wireless controller (usually a Broadcom controller named eth1).

The following diagram tries to illustrate the different components that made up the Cisco Linksys and how are they interconnected:

                                            Linksys rear
 Trunk    Internet    1     2     3     4   port number
  ---        ---     ---   ---   ---   ---
  |5|        |4|     |3|   |2|   |1|   |0|  switch port number
  ---        ---     ---   ---   ---   ---
  |           |       |                 |
  |         vlan1     |----- vlan0 -----|
  |
  | Miniswitch
  ----------------------------------------
  | Linux
  |
  |           ---- vlan0 -> LAN
  |           |
  |----- eth0 -
              |
              ---- vlan1 -> Internet/WAN

The standard Ethernet controller is attached to the sixth port (port #5) of the switch and is configured as a 802.1q VLAN trunk port. This allows running several VLANs using a single connection to the switch.

By default, OpenWRT configures two per-VLAN network interfaces:

  • vlan0:

    stands on the VLAN0 (the Local Area Network which comprises the four ports labeled as 1, 2, 3 and 4 at the rear of the box).

  • vlan1:

    stands on the WAN network (the port labeled Internet at the rear of the box).

The VLAN configuration is controlled using NVRAM variables. The variable labeled vlan0ports defines which switch ports are assigned onto the VLAN0, while vlan1ports defines which switch ports are assigned onto the VLAN1.

This is the default NVRAM configuration:

nvram set vlan0ports="3 2 1 0 5*"
nvram set vlan0hwname=et0
nvram set vlan1ports="4 5"
nvram set vlan1hwname=et0
  • vlan0ports:

    states that ports #3, #2, #1 and #0 (the ports labeled as 1, 2, 3 and 4 at the rear of the box) are assigned onto VLAN0. Additionally, port #5 is also assigned onto VLAN0.

    The asterisk sitting besides the 5 means VLAN0 is the default, native VLAN for this port, so any untagged traffic is considered to belong to VLAN0.

  • vlan1ports:

    states that port #4 (the port labeled as Internet at the rear of the box) is assigned onto VLAN1. Additionally, port #5 is also assigned onto VLAN1 since it’s a trunk port.

    The lack of an asterisk means VLAN1 is not the default, native VLAN for this port.

NOTE: vlannhwname needs to have a value assigned to it, even when it’s value is never used by the init scripts. This value is usually et0.

NOTE: Care must be exercised as ports numbers are zero-based, as illustrated before, and the sixth-port (port #5) must be assigned to every VLAN, since it is an VLAN trunk port.

The following code snippet from /etc/init.d/S10boot shows how the init script tells the switch which ports are onto which VLANs:

# configure the switch based on nvram
[ -d /proc/switch/eth0 ] &ports)"
    [ -z "$vp" -o -z "$(nvram get vlan${nr}hwname)" ] || {
        echo "$vp" > /proc/switch/eth0/vlan/$nr/ports
    }
  done
}

We can also see that up to sixteen VLANs are supported by the switch.

Custom VLANs

The Linksys and OpenWRT combination is so flexible that we can configure additional VLANs. In fact, I was looking to add an additional administrative VLAN (VLAN2) granting me full access to the box while I could restrict access from the LAN and WAN to the minimum — for example, by using additional firewall rules.

This is depicted in the following figure:

                                            Linksys rear
 Trunk    Internet    1     2     3     4   port number
  ---        ---     ---   ---   ---   ---
  |5|        |4|     |3|   |2|   |1|   |0|  switch port number
  ---        ---     ---   ---   ---   ---
  |           |       |     |           |
  |         vlan1   vlan2   |-- vlan0 --|
  |
  | Linksys
  ----------------------------------------
  | Linux
  |
  |           ---- vlan0 -> LAN
  |           |
  |----- eth0 ---- vlan1 -> Internet/WAN
              |
              ---- vlan2 -> Administrative VLAN

To achieve this configuration, we need to remove port #3 (labeled as 1 at the rear of the box) from VLAN0 and assign it onto VLAN2. We also need to add port #5 to the VLAN2 since it is the VLAN trunk port used to carry the traffic from the switch to Linux through the standard Ethernet controller:

nvram set vlan0ports="2 1 0 5*"
nvram set vlan0hwname=et0
nvram set vlan1ports="4 5"
nvram set vlan1hwname=et0
nvram set vlan2ports="3 5"
nvram set vlan2hwname=et0

I’ve defined three custom NVRAM variables that will get used by an additional init script to configure the VLAN2 as an administrative VLAN, granting full access to the box:

  • adm_ifname:

    defines the Linux network interface name assigned to the administrative VLAN, in the form of vlann, where n is the VLAN number.

  • adm_ipaddr:

    defines the IP address for the administrative interface.

  • adm_netmask:

    defines the network mask for the administrative interface.

For example:

nvram set adm_ifname=vlan2
nvram set adm_ipaddr=192.168.0.100
nvram set adm_netmask=255.255.0.0

I’ve also coded up an additional init script, named /etc/init.d/S41network, used to bring up the administrative interface. I’ve decided not to fiddle with /etc/init.d/S40network to avoid breaking things and having problems during upgrades.

These are the contents of /etc/init.d/S41network:

#!/bin/sh
IFNAME=$(nvram get adm_ifname)
VLAN=${IFNAME##vlan}
IPADDR=$(nvram get adm_ipaddr)
NETMASK=$(nvram get adm_netmask)
vconfig add eth0 $VLAN
ifconfig vlan${VLAN} up ${IPADDR} netmask ${NETMASK}

Testing

To test this custom configuration, I recommend disabling the firewall, my removing the executable permission bit from /etc/init.d/S45firewall and /etc/init.d/S41network just to prevent being locked out from the box in case problems arise.

Firewalling

I’ve also replaced the firewalling init script, /etc/init.d/S45firewall, with my own version. This allows for a fine-grained and thighter configuration.

Since the box will act as a routing firewall, and since it has 3 VLANs, I wanted to apply the following policy:

  • Any traffic coming from or going to the administrative VLAN (VLAN2) is allowed:

    This rule allows administering the box from a computer attached to the VLAN2, while blocking administrative access from other VLANs.

  • Incoming ICMP Echo Requests and ICMP Time Exceeded control messages are allowed from any interface:

    This rule allows certain ICMP control messages to reach the box. ICMP Echo Request is needed in order for the box to respond to ping and ICMP Time Exceeded (TTL) so we don’t break the PMTU discovery algorithm.

  • Any other incoming traffic from the LAN is rejected:

    This rule rejects any other traffic which does not match previous rules. Traffic is explicitly rejected, so we avoid having clients blocked waiting for an RST TCP segment.

  • Any other incoming traffic from the WAN is dropped:

    This rule silently drops any traffic coming from the WAN which does not match any previous rule. This will make external scan attacks much slower.

  • Local DNS queries coming from the local box going to configured DNS servers are allowed:

    This rule allows the local machine to resolve DNS queries sent against configured DNS servers (those configured in the wan_dns NVRAM variable). This is rarely needed, but the ipkg command requires a working DNS name resolution.

  • HTTP traffic from the local machine to the WAN is allowed:

    This rule allows upgrading and installing packages using the ipkg command.

  • Outgoing ICMP Echo Requests and ICMP Time Exceeded control messages are allowed from any interface:

    This rule allows certain ICMP control messages to depart from the box. ICMP Echo Request is needed in order for the box to invoke ping and ICMP Time Exceeded (TTL) so we don’t break the PMTU discovery algorithm.

  • Forwarding SSH/NX traffic coming from WAN to the designated SSH/NX server in the LAN:

    This rule allows accesing the SSH/NX traffic from the WAN. In addition, I apply SNAT to make IP datagrams appear to come from the firewall box since I have multiple DSL links.

  • Forwarding HTTP and HTTP/S traffic coming from the LAN targeted to the WAN:

    This rule allows using HTTP and HTTP/S services from the LAN.

  • DNS queries coming from the LAN going to configured DNS servers are allowed:

    This rule allows the machines in the LAN to resolve DNS queries sent against configured DNS servers (those configured in the wan_dns NVRAM variable).

  • Forwarding ICMP Echo Requests coming from the LAN to the WAN:

    This allows pinging external hosts from the LAN. ICMP Time Exceeded, however, is not forwarded, since the firewall sits in the middle between the LAN and the WAN (and I do use SNAT and DNAT).

Here is the complete /etc/init.d/S45firewall script:

#!/bin/sh
IPTABLES=/usr/sbin/iptables
FW_INET_IFACE=$(nvram get wan_ifname)
FW_INET_IP=$(nvram get wan_ipaddr)
FW_PRIVATE_IFACE=$(nvram get lan_ifname)
FW_PRIVATE_IP=$(nvram get lan_ipaddr)
FW_ADM_IFACE=$(nvram get adm_ifname)
NX_IP=10.200.0.10

$IPTABLES -F
$IPTABLES -t nat -F

# Configure SNAT/DNAT/MASQUERADE
$IPTABLES -t nat -A PREROUTING -i ${FW_INET_IFACE} -p tcp 
                               -d ${FW_INET_IP} --dport 179 
                               -j DNAT --to-destination ${NX_IP}:22
$IPTABLES -t nat -A POSTROUTING -o ${FW_PRIVATE_IFACE} -p tcp 
                                -d ${NX_IP} --dport 22 
                                -j SNAT --to-source ${FW_PRIVATE_IP}
$IPTABLES -t nat -A POSTROUTING -o ${FW_INET_IFACE} -j MASQUERADE

# Configure input firewall filtering:
# Allow:
#   - Traffic flowing from the loopback interface
#   - Traffic coming from the administrative VLAN
#   - ICMP Echo Request coming from WAN
#   - ICMP Time Exceeded (TTL) coming from WAN
#   - Traffic from an already established or related connection
# Block:
#   - Any traffic coming from the WAN
# Reject:
#   - Any other traffic coming from the LAN
$IPTABLES -A INPUT -i lo -j ACCEPT
$IPTABLES -A INPUT -i ${FW_ADM_IFACE} -j ACCEPT
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
$IPTABLES -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
$IPTABLES -A INPUT -i ${FW_INET_IFACE} -j DROP
$IPTABLES -A INPUT -j REJECT

# Configure output firewall filtering:
# Allow:
#   - Traffic flowing to the loopback interface
#   - HTTP traffic
#   - ICMP Echo Request going to WAN
#   - ICMP Time Exceeded (TTL) going to WAN
#   - DNS queries to configured WAN name servers
#   - Traffic from an already established or related connection
# Reject:
#   - Any other traffic
$IPTABLES -A OUTPUT -o lo -j ACCEPT
$IPTABLES -A OUTPUT -o ${FW_INET_IFACE} -p tcp -m tcp 
                     --dport 80 -m state --state NEW -j ACCEPT
$IPTABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
$IPTABLES -A OUTPUT -p icmp --icmp-type time-exceeded -j ACCEPT
for ns in $(nvram get wan_dns); do
        $IPTABLES -A OUTPUT -o ${FW_INET_IFACE} -p udp -m udp 
                            -d "$ns" --dport 53 -j ACCEPT
        $IPTABLES -A OUTPUT -o ${FW_INET_IFACE} -p tcp -m tcp 
                            -d "$ns" --dport 53 -j ACCEPT
done
$IPTABLES -A OUTPUT -j REJECT

# Configure forward firewall filtering:
# Allow:
#   - Incoming SSH/NX traffic -> the filtering takes place after the
#     PREROUTING chain has been processed and, since DNAT has been already
#     being performed, the traffic is filtered accordingly to its final
#     destination (the SSH/NX server)
#   - Outgoing DNS queries to configured WAN name servers
#   - Outgoing HTTP and HTTP/S traffic
#   - ICMP Echo Request coming from LAN going to WAN
#   - Trafic from an already established or related connection
# Drop:
#   - Any other traffic
$IPTABLES -A FORWARD -i ${FW_INET_IFACE} -o ${FW_PRIVATE_IFACE} -p tcp -m tcp 
                     -d ${NX_IP} --dport 22 -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -i ${FW_PRIVATE_IFACE} -o ${FW_INET_IFACE} -p tcp -m tcp 
                     --dport 80 -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -i ${FW_PRIVATE_IFACE} -o ${FW_INET_IFACE} -p tcp -m tcp 
                     --dport 443 -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -i ${FW_PRIVATE_IFACE} -o ${FW_INET_IFACE} 
                     -p icmp --icmp-type echo-request -j ACCEPT
for ns in $(nvram get wan_dns); do
        $IPTABLES -A FORWARD -i ${FW_PRIVATE_IFACE} -o ${FW_INET_IFACE} 
                             -p udp -m udp -d "$ns" --dport 53 -j ACCEPT
        $IPTABLES -A FORWARD -i ${FW_PRIVATE_IFACE} -o ${FW_INET_IFACE} 
                             -p tcp -m tcp -d "$ns" --dport 53 -j ACCEPT
done
$IPTABLES -A FORWARD -j DROP
Advertisements

18 thoughts on “Linksys, OpenWRT and multiple VLANs

  1. Very informative post – thank you.

    I assume that a separate vlan could also be created for unprivileged access (for example, a totally open WAP that you only wanted to grant internet access to (but no access to internal LAN resources))?

    Also, n00b question, but could these rules be kept in /etc/firewall.user ? or do you need to replace the openwrt init script?

    I am still trying to iron out my config – I have worked with Linux (poorly) for years – IPTABLES has always been my biggest stumbling block.

  2. Yes, you can use the separate VLAN for whatever you intend to do.

    When I wrote this post, I was describing a real case scenario of one of my customers wanting to deploy three different networks with different network access levels. However, this three network-based model can fit the one you describe: the first VLAN connects to the private LAN, the second VLAN connects to a public and unprivileged Wireless LAN, and the third network connects to the Internet. From the scenario described in this post, you can use the administrative VLAN as a public guest/Wireless VLAN and configure the firewall properly so that no traffic can flow from the public guest/Wireless VLAN to the LAN but any traffic can freely flow from the public guest/Wireless VLAN to the Internet/WAN.

    Wrt. the firewall configuration, I’ve played very little with OpenWRT default firewall script. In fact, I find easier to replace it with my customized version.

  3. Ah! Forgot to mention that you will need to remove the Wireless network interface (usually eth1 on the Linksys WRT54G) from the existing bridge, br0.

    By default, the Linksys WRT54G bridges together the wired and wireless network interfaces. However, you won’t want this, since the wired and wireless LANs will have different access levels.

    You can have a look at a post I wrote sometime ago describing, among other things, how to break the bridge.

  4. Mabuhay ka Felipe! I’ve been trying to look for information about VLANs on WRT and this post explains it like I’m in grade school. Thank you! Now I need to find out how to deal in applying IPs on each VLANs. I’ve created additional 3 VLANs 1 for each LAN.

    I’d really like to make my WRT to have totally separate access from each LAN ports (with their own IP subnets e.g. 192.168.22.0/24 for VLAN2, 192.168.33.0/24 for VLAN3, 192.168.44.0/24 for VLAN4). I’d also like to setup my WLAN to have it’s own subnet separate from the other LAN ports.

    I hope you have some spare time to post a blog on how to do this.. 🙂

  5. Hi! I also have a Linksys WRT54G ,mine is a version 2 .I have flashed it Openwrt Whiterussian RC5 when I first got it. I find it amazing that a very inexpensive box could be this multifunctional.. Anyway I got QoS working with the NBD-script and I also got port forwarding working by editing the /etc/firewall.user.
    I just recently flashed it to RC6 and I can’t wait for Kamikaze to be stable ..
    Anyway,I can’t seem to ping my wireless clients from my wired desktop pc ,I can ping them from the router fine. But how does one allow network access from the wired to the wireless clients..is it possible that a firewall is clocking my ping scan? I will try to scan the clients with nessus.

  6. I guess that your computer is sending an ICMP Echo Request to your wireless clients but the Linksys is blocking the response back.

    When you ping from the Linksys, the ICMP Echo Requests traverses the OUTPUT chain (since the packet is generated locally). The ICMP Echo Reply gets into the INPUT chain since it’s targeted to the local box.

    However, when pinging from a PC behing the router, packets traverse the FORWARD chain. Thus, it would be useful for us to take a look at your Netfilter/IPTables chains. I guess that Linksys is blocking some ICMP datagrams in the FORWARD chain.

  7. 2 questions for you? I have eth1 separated from the other VLANS. Everything works great except for a slight problem. I added so WiFi based SIP phones, and I have SIP phone connected to a wireless bridge. One of my VLANs support phone (asterisk) stuff.

    The question is, if I am on the wireless interface, is there any way to get my phones to be assigned an IP address from my VLAN1, as opposed to the standard IP address assigned to wireless clients?

    The second question is about iptables… For the version of iptables that is on RC6, is there a way to figure out if I can make use of the –timestart –timestop module?

    Thanks

  8. One other question as well… If one replaces the S35firewall with something custom, are there any other files that need to be changed considering that some of the functionality of the standard S35firewall was changed.

    Also, considering that one has multiple VLANs, what should be done in the firewall to make sure that the LAN can always long into the router, just stopping any accidental lock-outs…

    K.

  9. Hola Felipe,
    Magníficos manuales los que tienes en tu página.
    Llevo varias semanas con un Linksys WRT54GS al que he instalado una tarjeta SD con la intención de usarlo como firewall + proxy en mi casa.

    He instalado OpenWRT Whiterussian (RC6) y tengo configurado el router con tres redes:

    vlan1: Sólo y exclusivamente para enlazar a Internet
    br0: red de cable interna
    eth1: red wifi

    Ya tengo funcionando el proxy Squid pero tengo un problema que no consigo resolver: “soy incapaz de poder ver páginas https desde la red wifi”.

    Si puedes ayudarme, te lo agradecería.

    Saludos

  10. Necesitaría echar una vistazo a:

    – La configuración de los interfaces de red (ifconfig -a)
    – La tabla de rutas (netstat -anr)
    – La configuración del cortafuegos (iptables -L -n -v así como iptables -t nat -L -n -v)

    Con esto, quizá podríamos empezar a averiguar dónde está el problema.

  11. Impressive explanation! Thanks.

    How has stability been? I’ve heard some people have stability problems with the WRT54G. (I’ve had one for years, running the Linksys firmware, and I have occasional stability problems even in that condition.)

    Thanks,
    John

  12. Can I using WAN port (Internet port in rear) like a Lan Port (I want have 5 LAN Port, I no need WAN port)
    I’m using WRT54GL.
    Thx. sorry for my bad english 😀

  13. Gia, yes you can, just play with your vlan settings and make it:

    option vlan0 “0 1 2 3 4 5*”

    instead of

    option vlan0 “0 1 2 3 5*”

  14. Pingback: Alexis » OpenWRT

  15. Hi Felipe,

    You can create multiple vlan on the same WAN port with different ID to encapsulate 802.1Q vlans?

    Thank you,

  16. Hi admin, do you monetize your site ? There is easy method
    to earn decent money every day, just search on youtube – How to earn with wordai
    4

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