Direct wifi traffic through a VPN with openwrt

I think we probably all know someone who’s received a copyright violation notice. Usually these notices list the user’s IP address, date, and copyrighted file that was shared while demanding some payment or the content owner will take the user to court.

Today we will explore how to setup a wireless access point that automatically tunnels traffic through a VPN, so that you don’t have to worry about the activities of your guests on your network.

Note: If your VPN provider does not push the “redirect-gateway” option then DNS queries from clients will still go through your normal internet connection. This means that activities on the guest wifi are not completely anonymous!

For this I will be using the following:

  • TP-Link WR703N running OpenWRT 12.09 (Attitude Adjustment)
  • 1GB USB key
  • a subscription-based VPN provider

I chose the WR703N mainly because I had one and it is small, has low power consumption, and is quite inexpensive.

There are many instructions for how to install OpenWRT on the WR703N, so I’m not going to discuss that here. Also the choice of VPN providers differs based on your needs and price range. I recommend reading the TorrentFreak articles on VPN providers to find out which one is best for you.

A 1GB USB key is required as the flash on the WR703N is not large enough to hold an OpenWRT installation with luci and openvpn installed. First we need to move the OpenWRT OS from the internal flash to the USB key, this will allow us to install the additional packages required, namely openvpn. I followed these instructions for how to transfer the OS from internal flash to USB. I’ll provide a tl;dr:

  • Partition the USB key with a DOS partition table, make at least one partition of type 82 (Linux)
  • Format this partition as ext4
  • Install block-mount, kmod-usb-core, kmod-usb-ohci, kmod-usb-storage, kmod-usb2, kmod-scsi-core, kmod-scsi-generic, kmod-fs-ext4, libblkid

Plug in the USB key. Check dmesg on the router and you should see that it recognizes the USB key as a block device. Create two temporary folders, one to mount the USB key at, and the other to bind mount /

mount /dev/sda1 /tmp/usb
mount --bind / /tmp/flash
tar -C /tmp/flash -cvf - . | tar -C /tmp/usb -xf -
umount /tmp/flash
umount /tmp/usb

Now that we’ve moved the OpenWRT installation to the USB key we have to configure the router to boot from the USB key instead of internal flash. Edit /etc/config/fstab and change the following:

config mount
     option device /dev/sda1
     option target /home
     option enabled 0

to:

config mount
     option device /dev/sda1
     option target /
     option enabled 1

Now reboot the router, it should boot off the USB key now.

Now there is lots of available space

Now there is lots of available space

I followed this post for most of the following openvpn configuration. Now go ahead and install the openvpn package:

opkg install openvpn

scp all the crt, ovpn and other openvpn configuration files to /etc/openvpn on the router.

You can test openvpn by ssh’ing into the router and running:

openvpn --config myconfig.ovpn

from /etc/openvpn. Assuming that works, now open the luci interface on the router to create a new interface:

  1. Go to the Network tab, click on Interfaces
  2. Create a new interface, I called mine “VPN” and set the protocol to “unmanaged”
  3. Specify tun0 as the network interface for the VPN interface
  4. Under “Advanced Settings” click the “Bring up on boot” checkbox

Now you have a choice, you can either:

  1. add the VPN interface we are in the process of creating above to the WAN zone, in which case a route with the prefix 0.0.0.0/1 will be added, which will supersede the WAN route of 0.0.0.0/0 through longest prefix matching, or
  2. create a firewall zone in luci to ensure that any traffic from LAN is automatically forwarded directly to the VPN, never going to the WAN. This is based on an openwrt wiki example

If you choose the second, then you need to do some additional work in luci:

  1. Go to the Network tab, click on Firewall
  2. Add a new Zone, I called mine “vpn” set it to Input:accept, Output:accept, Forward:accept
  3. Forward all traffic from the LAN to the vpn zone and visa versa, remove the WAN zone from the forwarding from the LAN zone.

Your zones should look like this now:

Firewall Zones

Firewall Zones

Go back to the Interface page and edit the VPN interface. Under the “Firewall Settings” tab change the zone from “wan” to “vpn”. The interface should look like this now:

VPN Interface Firewall Zone Settings

VPN Interface > Firewall Settings > Assign Firewall Zone “vpn”

There is an airvpn thread full of information on how to ensure that traffic goes from the LAN through the VPN. The above achieves something similar to the iptables rule mentioned in the airvpn thread.

Now that we have the routing all configured, you can go back to openvpn. If the ovpn file has “auth-user-pass” in it, you can create a text file which contains your VPN username on the first line, and your password on the second, and change the ovpn file to have “auth-user-pass credentials.txt” so openvpn will not prompt you for them when it connects.

Next we need to configure openvpn to start a boot:

  1. Go to the System tab, click on Startup
  2. At the bottom in the text box, add the following above “exit 0”
/usr/sbin/openvpn --cd /etc/openvpn --daemon --config /etc/openvpn/myvpn.ovpn &

Now we want to secure the router more. You might have some technically savvy guests who may try to break into the admin interface of your router to reconfigure it.

Before we block access to the management ports from the “bad” (guest-facing) side, we need to ensure that we don’t lock ourselves out of the router. Go to the Network tab, click on Firewall, click on “Port Forwards” add new rules to forward SSH (TCP 22), HTTP (TCP 80), and HTTPS (TCP 443) from WAN to the IP address of your router, in my case this is 192.168.1.1. Make absolutely sure you can access these ports from the WAN interface (your home LAN) before you do the following!

Now, go to the Network tab, click on Firewall, click on “Custom Rules” and add these rules in the space provided:

iptables -I zone_lan_ACCEPT 1 -p tcp -i wlan0 --dport 22 -j DROP
iptables -I zone_lan_ACCEPT 1 -p tcp -i wlan0 --dport 80 -j DROP
iptables -I zone_lan_ACCEPT 1 -p tcp -i wlan0 --dport 443 -j DROP

This blocks your wireless clients from accessing ports 22, 80, and 443 on the router, which means if they try to go to the luci interface or SSH into the router from the wireless side, they can’t! You need to restart the firewall for these changes to take effect.

The performance appears to be quite good. I am not sure precisely what the speed of my internet connection here is, but I was able to get over 6MBit/s down using the VPN and the speedof.me speed testing service, which seems very good.

That’s it. I recommend rebooting the router to make sure everything you did will survive a power cycle. IANAL but this solution should allow you to avoid any legal ramifications for the activities of guests on your IP address since they’ll be using a VPN and have a different termination IP address.

So, in summary:

  1. All traffic from wireless clients will be directed through the VPN, if the VPN is down wireless clients will not have internet, nor will they have access to your network
  2. Wireless clients are considered hostile, and as such are blocked from accessing ports 22, 80, and 443 on the router to prevent break-in attempts.

 

16 thoughts on “Direct wifi traffic through a VPN with openwrt

  1. El Jefe

    Thanks for the great guide! Couple of questions, though:

    1. I have a transmission daemon running on the router. Is there a way to force all of its traffic to go through the VPN too and have it not be connected at all if they VPN connection fails? Right now it just connects through the ISP router if the VPN connection fails. Same if i run say ping on the router – it continues to run even if the VPN connection fails.

    2. Is there a way to have clients connected to the VPN router still to be able to access the LAN network, but have all their Internet traffic go through the VPN? I would like to have let’s say a laptop connected to the VPN router, but still be able access network shares on it.

    Thanks!

    Reply
    1. Hal Martin Post author

      #1) That’s a tough question. The router itself always needs a valid route to the internet, otherwise you wouldn’t be able to connect to the VPN provider, or reconnect if the connection is lost. The behaviour you’re seeing is expected. If you traceroute to your ping target when you’re connected to the VPN, you should see that the route is different from when you’re connected through your ISP.

      My recommendation would be to run transmission on another system that is located behind the router. This way you ensure that if the VPN connection is down, there is no possibility that your P2P traffic will go over your normal internet connection.

      #2) LAN to LAN access should not be restricted by the firewall configuration.

      e.g. if you have two wireless clients on the router, they should be able to communicate with each other with the configuration described.

      The firewall configuration mentioned in the post only blocks LAN clients from accessing SSH and the luci interface. If you trust your LAN clients, then simply remove these rules. There are no other limitations on the LAN side, so if you cannot access network shares that are running on the router itself, I would recommend you check the configuration of your Samba/NFS daemon.

      I think I might be misunderstanding your question though. You are referring to accessing your home network LAN, which is actually the WAN side of the router handling the VPN connection. For that you should be able to add a static route from the VPN router LAN to your home network LAN (VPN router WAN) to allow access to that network while connected to the VPN.

      e.g. If your VPN router LAN subnet is 10.0.0.0/24 and your home network LAN subnet is 192.168.1.0/24, you should be able to add a static route in luci from 10.0.0.0/24 on interface br-lan to 192.168.1.0/24 on interface WAN and then be able to access your regular LAN resources when connected to the VPN router.

      Reply
  2. El Jefe

    Thanks a lot for the lighting fast reply! I didn’t expect one at all and getting one so fast made my day 🙂 I’m adding your blog to my rss reader and will be following you religiously! 😉

    Regarding 1.:
    Yes, if I traceroute once the VPN is up the traffic does go through the VPN. I would like the avoid running transmission on another device, since pretty much the main reason I set-up that router is to have a low-power consumption, low-noise torrent box. The very little torrenting I do does not justify a whole dedicated machine.

    Wouldn’t it be possible to limit Internet access only to the ip address / port number of the VPN provider when the VPN is not up? That way the router would be able to connect to the VPN but Transmission wouldn’t be able to access anything without a VPN connection…

    Regarding 2.:
    I followed this guide https://blog.ipredator.se/howto/openwrt/configuring-openvpn-on-openwrt.html to set-up my router. I am not sure I understand the differences between their firewall setup and yours, but it ends up doing the same thing, I believe.

    I have the VPN router (LAN 192.168.3.1) connnected to the ISP router (LAN 192.168.1.1) through it’s WAN port and have enabled DHCP on it, so it also gives IP addresses out.

    So you are saying that if I connect the VPN router through the ISP router (again through its WAN port) and set-up a static route from 192.168.3.0/24 to 192.168.1.0/24 it should work? Aren’t those different subnets? What’s the difference between 192.168.3.0/24 and 10.0.0.0/24? They are both private side addresses, right? Sorry I am still a newb 🙂

    Reply
    1. Hal Martin Post author

      Re: #1) Sure, you could setup an outgoing firewall rule on the router to block all connections that are not destined for the VPN endpoint, and then (if the openvpn configuration file is not an IPv4 address) put the VPN server in /etc/hosts

      A safer way to do this would be to assign the VPN router a static IP address on your ISP router, and then add a firewall rule on your ISP router (assuming it is advanced enough to allow this) to only allow that IP address access to the VPN provider. That way the VPN router simply cannot connect to anything else.

      I say the second option is more safe because if for whatever reason your OUTPUT rule on the VPN router gets dropped, you could silently pass P2P traffic, whereas if it’s on your ISP-facing router, that would never happen.

      #2) Okay, so in your setup you have 192.168.1.0/24 (your home network) and 192.168.3.0/24 (your VPN network). The concept you’re looking for is Network Address Translation (NAT), which allows computers on different subnets to communicate with each other through a router. Defining a static route should allow you to access resources on your home LAN (192.168.1.0/24) when you’re connected to your VPN LAN (192.168.3.0/24) due to something called Longest prefix matching. The VPN connection adds a catch-all route to the internet, so that all requests will be routed through your VPN provider instead of your normal internet connection. However, if you specify a static route to your 192.168.1.0/24 network, since the router uses longest prefix matching, this entry will be matched before the catch-all route inserted by openvpn.

      By doing this, your VPN router will route requests to 192.168.1.0/24 through the WAN interface, onto your home LAN, instead of trying to route it over the VPN connection (unless your configuration doesn’t route RFC1918 requests). This should accomplish what you’re trying to achieve.

      Reply
      1. El Jefe

        #1) OK, sounds great!!! My ISP router is running DD-WRT. Any chance you could let me know how to do this? If you don’t have DD-WRT or are not familiar with it, instructions for OpenWrt would do too. I’ll either install OpenWrt on the ISP router too or figure out how to convert them for DD-WRT. Sorry for the newb questions and I appreciate your time and help!

        Thanks so much!

        Reply
  3. El Jefe

    Maybe I am misunderstanding your instructions, but I cannot figure out a way to do a static route from one interface to another. Luci does not have such an option at all and reading the documentation for /etc/config/network (http://wiki.openwrt.org/doc/uci/network) I don’t see such a possibility either…

    Reply
    1. Hal Martin Post author

      Sorry, I don’t have an Altitude Adjustment installation of OpenWrt around. Here is what the page looks like in Barrier Breaker/Chaos Calmer, you can find it under Network->Static Routes

      Screenshot of Luci static routes page in CC

      You could also try adding it directly to iptables, something like:
      iptables -I FORWARD -i br-lan -o eth0 -d 192.168.1.0/24 -j ACCEPT
      iptables -t nat -A POSTROUTING -o eth0 -d 192.168.1.0/24 -j MASQUERADE

      (that’s a capital -i before the forward, the WordPress font is kind of horrible)

      Although the chain names will be slightly different for OpenWrt.

      Reply
      1. El Jefe

        Thanks a lot, Hal!

        I am using BB 14.07 too. Here’s how I’ve set it up, but no luck 🙁

        https://www.dropbox.com/s/5qyyf1g9db2jzvf/Capture.PNG?dl=0

        192.168.1.254 is the WAN address of the VPN router. Am I doing something wrong?

        Also, would you mind if I share a write-up of our discussion here on the OpenWrt and NordVPN forums? I’ll put a link to your blog too. I think quite a lot of people are interested in this and it’s not to be found anywhere else…. Thanks again!

        Reply
        1. Hal Martin Post author

          Feel free to share this with whoever you want 🙂

          Yup, there’s a slight misunderstanding here. The /24 is the netmask, but in Classless Inter-Domain Routing (CIDR) format. For the web interface you need to convert the /24 into 255.255.255.0 and put it in the netmask field.

          It’s been a while since I defined a route through the OpenWrt web interface. I’ll have to go back and try it out myself.

          You can try it manually on the router via SSH:
          route add -net 192.168.1.0/24 dev (your WAN device; probably eth0)

          As for DD-WRT, sorry I haven’t run it in years. Google should have instructions for setting a static DHCP lease for your VPN router and firewall rules should be pretty easy too.

          Here is an iptables rule that blocks all internet requests from the VPN router except those to the VPN endpoint IP address:
          iptables -I INPUT -i (DD-WRT LAN interface) -s (VPN router 192.168.1.X IP address) ! -d (VPN endpoint IP address) -j REJECT –reject-with icmp-port-unreachable

          Reply
          1. El Jefe

            OK, thanks a lot! I’ll have to read up on iptables, I guess 🙂

          2. El Jefe

            OK, I tried the manual way above and it does create the static route:

            root@OpenWrt:~# route
            Kernel IP routing table
            Destination Gateway Genmask Flags Metric Ref Use Iface
            default 10.7.7.13 128.0.0.0 UG 0 0 0 tun0
            default 192.168.1.1 0.0.0.0 UG 0 0 0 eth0.2
            10.7.7.1 10.7.7.13 255.255.255.255 UGH 0 0 0 tun0
            10.7.7.13 * 255.255.255.255 UH 0 0 0 tun0
            95.211.190.205 192.168.1.1 255.255.255.255 UGH 0 0 0 eth0.2
            128.0.0.0 10.7.7.13 128.0.0.0 UG 0 0 0 tun0
            192.168.1.0 * 255.255.255.0 U 0 0 0 eth0.2
            192.168.3.0 * 255.255.255.0 U 0 0 0 br-lan

            And I can indeed ping addresses in the 192.168.1.0/24 subnet. I can also ssh from the VPN router to the ISP router. However, it seems the clients connected to the VPN router do not see the 192.168.1.0/24 network and I cannot ping or connect to the ISP router from any of those clients. Also I cannot access the 192.168.3.0/24 network from clients connected to the ISP router, e.g. in the 192.168.1.0/24 network, which kind of makes sense, because I assume the ISP router knows nothing about routing to 192.168.3.0/24. Also I assume some firewall rules would have to be set-up….

            So anyways – I’ve just found this http://www.dd-wrt.com/wiki/index.php/Linking_Subnets_with_Static_Routes and I am going to try it out, it looks exactly like what I am trying to do.

            The only thing I am stumbled over is the last part where it says to change the mode of operation from Gateway to Router. OpenWRT routers don’t have that option. I assume it simply switches off masquarading (NAT) on the wan port of the VPN routers. Is that correct? Do I just go and take away the tick on the “Masquerading” checkbox for the wan interface in Firewall in Luci?

            Don’t want to waste your time anymore, you’ve already been very helpful. Thank you!

          3. Hal Martin Post author

            “However, it seems the clients connected to the VPN router do not see the 192.168.1.0/24 network and I cannot ping or connect to the ISP router from any of those clients.”

            Add a static route on the VPN router.
            Destination 192.168.0.0
            Netmask 255.255.255.0
            Gateway 192.168.3.1
            Device br-lan

            That should allow clients on the VPN LAN to ping Home LAN addresses.

            As for Home LAN pinging VPN LAN clients, you need to add a route on the DD-WRT router:
            Destination 192.168.3.0
            Netmask 255.255.255.0
            Gateway (VPN router WAN address on your 192.168.1.0 network)
            Device LAN

            That should allow you to ping your home LAN from the VPN LAN and visa versa. You may need to add a new FORWARD rule on the VPN router to allow reverse access.

            e.g. iptables -I FORWARD -i (wan interface) -d 192.168.3.0/24 -o br-lan -j ACCEPT

  4. El Jefe

    Ok, Hal, things are happening! 🙂

    I can now access the VPN clients from the ISP router (and open the Samba shares, although I think NETBIOS is not working, since it doesn’t show them, I have to open them manually, but works!!!). However, I still can’t ping the ISP clients from the ISP router. E.g. it only works one way 🙁

    Here’s the route output on the VPN router:
    https://www.dropbox.com/s/61agd8d8gupxn8d/Capture2.PNG?dl=0

    Here’s my Firewall set-up on the VPN router:
    https://www.dropbox.com/s/onpz749ix0uzjvf/Capture3.PNG?dl=0

    And here’s the Interfaces on the VPN router:
    https://www.dropbox.com/s/4xcriaslxkqjd24/Capture4.PNG?dl=0

    Btw. how do I remove the static routes? With route delete? They keep showing up again after reboot even if I delete them…

    Thanks!

    Reply
  5. El Jefe

    BTW. your firewall rule worked with a little modification:

    iptables -I FORWARD -i br0 -s 192.168.1.2 -d ! 95.211.190.205 -j REJECT

    …just in case someone else stumbles upon this and needs to know too 🙂

    Reply
  6. Kent

    I’m assuming in your setup that the WR703N was connected by Ethernet. Could this also work in a Wi-Fi repeater mode?

    I’m using my WR703N (running DD-WRT) as a repeater while traveling, and I’ve tried enabling it’s PPTP client function without any real success: it does seem to connect to the VPN and register the remote IP, but any traffic through the WR703N seems to be very short-lived, i.e. a webpage might load once and that’s it. The PPTP client works fine when connected by Ethernet, but that’s often not an option for me.

    Reply
    1. Hal Martin Post author

      Hi Kent,
      To the best of my knowledge, the ability of a WiFi chipset to be both a station (client) and AP depends on the hardware. I don’t happen to have any TP-Link WR703N devices around anymore (I’ve moved on to the Nexx 3020H, more hardware at a cheaper price) so I can’t tell you if this is possible or not. Since you’ve got it working with DD-WRT, I would expect it to also work with OpenWrt. Try it out and let us know in the comments!

      Reply

Leave a Reply to Hal Martin Cancel reply

Your email address will not be published. Required fields are marked *