OpenVPN to route all / selective traffic to a client

This post is inspired from my urge to watch Macedonian TV (for free). Broadcast of Macedonian television is actually available on internet via Web MaxTV.mk, however it is limited to Macedonian IP addresses only. Since this scenario for tv broadcast or any kind of services, which are limited to a particular IP country block, applies to many other people living abroad, I decided to make my nightly research/experiment public.

The standard way to use services that operates in one or several countries only is to use proxy servers. However, in some cases there are either no proxies available in the home country, the services that one is planing to use can not be bypassed with a simple proxy server, the proxy services are slow to transfer broadcasts, or one just does not want to pay for a proxy service.

MaxTV.mk stream in Switzerland

MaxTV.mk stream limited on Macedonian IP, accessed in Switzerland

Obviously from the picture above, I have already resolved the problem, by making my home computer (the one in Macedonia) an internet gateway. This is almost a trivial task when the home computer has a public IP address, but in most cases, this simply does not apply (such as my Macedonian IP). Assuming that one can get his hands on a computer with a public IP address, a cheap (almost free) solution is routing via OpenVPN. What you need is the following:

  1. A computer with a public IP address (the server), located anywhere in the world. 
  2. A computer in the home country (the gateway), with a decent internet connection.
  3. One or several clients (the client), with an Internet connection

As I currently live in Switzerland, I am more than happy to use the services of upc cablecom ISP, especially since they are so nice to provide me a public IP address. Therefore, I can simply setup an OpenVPN server in Switzerland, and use it as a tunnel to redirect traffic to the home computer. My current setup looks like this:

OpenVPN Setup

OpenVPN Setup

From the drawing above you can infer that the server is ch-server, the gateway is mk-gateway and finally the client is astojanov-mac. The gray lines and black labels represent the physical connections, and the red lines and red labels specify the OpenVPN network. 

  • 72.xxx.xxx.xxx is the public address in Switzerland, and the router behind it has port-forwarding to ch-server, port 1194 to the ch-server having local IP address 192.168.1.50
  • ch-server and astojanov-mac are behind the same router and are part of the 192.168.1.0/24 network. Note that the client astojanov-mac can access the OpenVPN server from any network node on the Internet. Thus the route to access the ch-server goes through the Internet cloud.
  • mk-gateway is part of the 192.168.0.0/24 local network in Macedonia and has no public IP address attached on the router.
  • The OpenVPN overlaid network is represented with 192.168.2.0/24. The server has a static ip address: 192.168.2.1, as well as the gateway 192.168.2.250. The client astojanov-mac as every other OpenVPN client are assigned dynamic ip address.

The first step is installing and setting up OpenVPN. In order to run the server, a very modest computer can fulfill the needs of a VPN server if less than 10 VPN connections are anticipated. Personally I am using Intel(R) Pentium(R) M processor 1200MHz, with 1.6 GB of RAM. OpenVPN is cross platform and has no OS requirements. ch-server runs Debian GNU/Linux 6.0.6 (squeeze) and I base my instruction on this distribution. Note that to run OpenVPN server / client there are many alternatives with less power consumption requirements. For example the Raspberry Pi, which has 700 Mhz ARM CPU and costs about $25, or your router if you can set up DD-WRT on it.

Installing OpenVPN sever and setting up server / client keys & certificates

Installing and setting up OpenVPN has almost cross-platform steps. Also there are many tutorial available out there. My setup is based on the following tutorial, but you can also find additional tutorial on Linux, Windows and Mac OS X. First install OpenVPN and OpenSSL:

apt-get install openvpn openssl

Now we need to create server certificates. Before that we edit the variables of the certificates we are about to create.

cd /etc/openvpn
cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 ./easy-rsa
vim easy-rsa/vars

Edit accordingly:

export KEY_COUNTRY="CH" 
export KEY_PROVINCE="ZH"
export KEY_CITY="Zurich" 
export KEY_ORG="AlenBlog" 
export KEY_EMAIL="me@myhost.mydomain"

Save and quit. Load the variables, clean, and build the server key and certificate:

source ./easy-rsa/vars
./easy-rsa/clean-all
./easy-rsa/build-ca
./easy-rsa/build-key-server ch-server

As soon as the server ca.crt and ch-server.key are set, we can proceed towards creating the client keys. Note that we will have one special client, namely the mk-gateway client. This step must be repeated for ever clients you want to allow on your VPN. Note that the clients are identified by the ‘Common Name’.

./easy-rsa/build-key mk-gateway
./easy-rsa/build-key astojanov-mac

Now let’s create Diffie Hellman parameters:

./easy-rsa/build-dh

After this is done, we are ready to setup the OpenVPN configuration file.

OpenVPN server configuration

Since the main goal is to watch Macedonian TV, the router will be configured such that I do not have to turn on / off the VPN connection whenever I want to watch the TV stream. However, it was is also useful to have the opportunity to transfer the whole traffic to the mk-gateway. Therefore the client will make the decision of what routes will be redirected to the mk-gateway. In other words the OpenVPN will route complete or selective trafic to a client. The server configuration file is as simple as possible.

dev tun
proto udp
port 1194
ca /etc/openvpn/ca.crt
cert /etc/openvpn/ch-sever.crt
key /etc/openvpn/ch-server.key
dh /etc/openvpn/dh1024.pem
user nobody
group nogroup
server 192.168.2.0 255.255.255.0
persist-key
persist-tun
route 192.168.0.0 255.255.255.0
status /var/log/openvpn-status.log
ifconfig-pool-persist /etc/openvpn/ipp.txt
client-config-dir /etc/openvpn/ccd
verb 3
client-to-client

The server uses UDP as a transport protocol (although less reliable than TCP, it is quite faster than TCP), running on port 1194. For in-depth knowledge for the rest of the directives, I strongly advise the OpenVPN manpage.

Note the client-config-dir directive. It provides the flexibility to add specific configurations to the clients. We configure the mk-gateway here.

mkdir -p /etc/openvpn/ccd
vim /etc/openvpn/ccd/mk-gateway

In order to make mk-gateway route any specific traffic, we use the iroute directive. Ideally we would like to route 0/1 to the client and set something like:

iroute 0.0.0.0 128.0.0.0

However, THIS DOES NOT WORK in OpenVPN. Good news is that instead of using one general route, we can set routes from 1.0.0.0 to 255.0.0.0 using netmask 255.0.0.0 (thanks to fuzzie’s post for his insights) which will do exactly the same. We also like a static IP for the mk-gateway:

ifconfig-push 192.168.2.250 192.168.2.249
iroute 1.0.0.0 255.0.0.0
iroute 2.0.0.0 255.0.0.0
iroute 3.0.0.0 255.0.0.0
. . . . . . 

iroute 254.0.0.0 255.0.0.0
iroute 255.0.0.0 255.0.0.0

By now, the configuration for the OpenVPN server is complete. The server can be started with:

/etc/init.d/openvpn start

Setting up the remote gateway (mk-gateway). Optional DD-WRT setup.

Initially I configured the gateway to run on Windows 7 machine. Since this machine will be forwarding packets, the OS must be configured to enable forwarding. According to Bebop’s post, the following tweaks should do the job:

  • Start -> Right-click My Computer -> Manage -> Services. Right-click Routing and Remote Access -> Properties -> Automatic. Right-click Routing and Remote Access -> Start
  • Control Panel -> Network and Sharing Center -> Local Area Connection -> Properties -> Sharing. Tick the box “Allow other network users to connect through this computer’s Internet connection”. From the drop-down list select “Local Area Connection 2”, or whatever is the connection name of your TUN connection.
  • Run regedit. Navigate to HKEY_LOCAL_MACHINE and then to SYSTEM\CurrentControlSet\Services\Tcpip\Parameters. Change value of IPEnableRouter to 1.

OpenVPN GUI for Windows is a decent OpenVPN client for Windos, including GUI, as mentioned in its title. In order to set it up, download it, install it and copy the files /etc/openvpn/ca.crt, /etc/openvpn/mk-gateway.crt and /etc/openvpn/mk-gateway.key into C:\Program Files\Open VPN\config\ and finally create the config file config.opvn

dev tun
proto udp
remote ch-sever 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert mk-gateway.crt
key mk-gateway.key
verb 3
route-method exe
route-delay 2

The GUI client will enable / disable the tun device and setup the routes in the system. Therefore in Windows 7 / Vista it need administrator permissions. Make sure that you right-click on the GUI executable in C:\Program Files\OpenVPN and check the ‘Run as administrator’ checkbox.

OpenVPN client running on DD-WRT 

Having a computer running 24/7 just for routing is not really desirable. With a decent router having OpenVPN support, one can bypass the need for an extra computer. I personally have WRT54GL in Macedonia. It is possible to install DD-WRT on the router and ‘unleash’ the OpenVPN client support in the router itself. Setting up DD-WRT in some cases is router specific, and its installation has been well documented on the DD-WRT wiki.

In order to setup DD-WRT on a router, one needs to flush the current firmware, and replace it with a DD-WRT, which might be a risky business. Note that the first step is flushing the router with the ‘mini firmware’ available at the DD-WRT website, and then the next step is installing the OpenVPN supported firmware. When the final firmware is installed, setting up the OpenVPN client can be done via the Web interface in Services -> VPN. The files /etc/openvpn/ca.crt, /etc/openvpn/mk-gateway.crt and /etc/openvpn/mk-gateway.key can simply be copy-pasted into the corresponding fields:

DD-WRT Setup

DD-WRT Setup

Depending on the router CPU, you can enable or disable the LZO Comporession. I have actually disabled it in my final configuration since WRT54GL has 200MHz CPU.

The above creates a connection to the OpenVPN server ch-server as soon as the router is rebooted. Before rebooting, packet forwarding within the router must be enabled. This can be done in Administration -> Commands, by setting the following commands for the Firewall.

iptables -I FORWARD 1 --source 192.168.2.0/24 -j ACCEPT
iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -o br0 -j ACCEPT

By clicking Save Firewall, the commands will allow packets to flow to/from the ch-sever to the mk-gateway.

Setting up the client such that the whole traffic is redirected to the remote gateway

The client astojanov-mac, runs Mac OS X. I am using Tunnelblick as an OpenVPN client GUI. To set it up, the generated key & certificates: /etc/openvpn/ca.crt, /etc/openvpn/astojanov-mac.crt and /etc/openvpn/astojanov-mac.key must be copied to the client, and config.opvn file must be created:

client
dev tun
proto udp
remote ch-server 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert astojanov-mac.crt
key astojanov-mac.key
verb 3
redirect-gateway def1
dhcp-option DNS 8.8.8.8

Note the redirect-gateway def1 directive. This directive forces the client to change its default gateway and redirect it to the OpenVPN server. Since the mk-gateway takes all the routes from 1.0.0.0 to 255.0.0.0, the whole traffic will be redirected to mk-gateway.

Setting up the client to route selective traffic via a remote gateway

For this scenario, I use most of the previous settings for redirecting the whole traffic and Tunnelblick, with a modified config.opvn file. In order to perform selective routing, instead of redirecting the gateway, we need to rewrite the routing rules to the specific selective trafic that we are planning to redirect. I personally wanted scenario where all Macedonian web sites hosted in Macedonia will be redirected through the mk-gateway. To identify all Macedonian hosts, I used the NirSoft country based IP blocks. The blocks are given by their price ranges, and the number of hosts for each block. With a simple math, it is easy to derive the netmasks for each block taking into considerations the number of nodes.

Finally the config file looks like the following:

client
dev tun
proto udp
remote ch-server 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert astojanov-mac.crt
key astojanov-mac.key
verb 3
route 31.11.64.0 255.255.192.0 # Cabletel DOOEL Skopje
route 78.157.0.0 255.255.224.0 # Cabletel DOOEL Skopje
route 92.53.0.0 255.255.192.0 # Cabletel DOOEL Skopje
route 188.44.0.0 255.255.224.0 # GIV Ivan LTD Gostivar
route 212.120.0.0 255.255.224.0 # NETCETERA DOOEL Skopje
route 95.86.0.0 255.255.192.0 # Inel Dooel Kavadarci
route 79.141.112.0 255.255.240.0 # INFEL-KTV DOO
route 213.135.160.0 255.255.224.0 # KDS-Kabel Net DOOEL
route 212.110.64.0 255.255.224.0 # Macedonia On-Line
route 46.217.0.0 255.255.0.0 # Makedonski Telekom
route 62.162.0.0 255.255.0.0 # Makedonski Telekom
route 62.220.192.0 255.255.224.0 # Makedonski Telekom
route 77.28.0.0 255.254.0.0 # Makedonski Telekom
route 79.125.128.0 255.255.128.0 # Makedonski Telekom
route 195.26.128.0 255.255.224.0 # Makedonski Telekom
route 89.205.0.0 255.255.128.0 # MEGANET
route 94.100.96.0 255.255.240.0 # Miksnet
route 217.196.192.0 255.255.240.0 # Miksnet
route 80.77.144.0 255.255.240.0 # NEOTEL Skopje
route 88.85.96.0 255.255.224.0 # NEOTEL Skopje
route 92.55.64.0 255.255.192.0 # NEOTEL Skopje
route 95.180.128.0 255.255.128.0 # NEOTEL Skopje
route 79.126.128.0 255.255.128.0 # ONE Telecom
route 85.30.64.0 255.255.192.0 # ONE Telecom
route 212.158.176.0 255.255.240.0 # ONE Telecom
route 217.16.64.0 255.255.240.0 # ONE Telecom
route 217.16.80.0 255.255.240.0 # ONE Telecom
route 151.236.240.0 255.255.240.0 # PET NET DOO Gevgelija
route 31.12.16.0 255.255.240.0 # T-Mobile Makedonija
route 95.156.0.0 255.255.192.0 # T-Mobile Makedonija
route 146.255.64.0 255.255.224.0 # TELESMART TELEKOM DOO
route 89.185.192.0 255.255.224.0 # TRD " Net Kabel"
route 212.13.64.0 255.255.224.0 # UltraNet d.o.o.
route 194.149.128.0 255.255.224.0 # "Sv. Kiril i Metodij"

Linux clients

For the linux users, particularly, the linux clients, setting up openvpn in a client mode is straight forward. We use the same keys and certificates as explained above. The content of the config file remains the same and its renamed to client.conf. All the files should be placed into /etc/openvpn and the client is started with:

/etc/init.d/openvpn start client
Advertisements

15 thoughts on “OpenVPN to route all / selective traffic to a client

  1. Way too long a procdure :/

    I’m paying $40 a year for a VPN solution but right now I loath the manual toggling off/on of the VPN. Because i have to disable the VPN when gaming (so it doesnt add the extra latency to my pings) and then enablign VPN back on for youtube etc (which are banned in my country Pakistan). I was hoping there’s an easy way to make OPENVPN alway on and make it only pass the traffice to vpn tunnel when using selective sites like youtube. In every other case, it should just pass on my traffic to my local isp.

    • Well … yeah, this is indeed a long procedure.

      However, I guess your VPN provider enables you to tunnel the whole traffic. If you can do that, you can also redirect specific traffic by slightly modifying the client settings. Have a second pass only on the “Setting up the client to route selective traffic via a remote gateway” section. The section is self-sufficient, and independent on the other parts, and I believe that this will be a good guideline how to setup your VPN.

  2. Thanks for the detailed setup guide. I was hoping to find more information on how to route all traffic through the OpenVPN server itself, where the server is a part of a remote network and the client is my macbook. To clarify my setup, I have a new install of OpenVPN on my VPS (CentOS) located in a datacenter, and I want to secure all my inbound/outbound traffic of my Mac for any network I join (i.e. cafe hotspots, libraries, airports, etc) as a roadwarrior. Ideally, I would VPN tunnel to my server in order to redirect all client traffic through my server to prevent man-in-the-middle attacks or sniffing. I dug through a ton of documentations and websites, but haven’t gotten a clear answer for my setup. Any pointers on how I can successfully achieve this?

  3. Hi!
    You may replace lines:
    iroute 128.0.0.0 255.0.0.0

    iroute 255.0.0.0 255.0.0.0

    with one line:
    iroute 128.0.0.0 128.0.0.0

  4. Hello, do you think is possible to use lets say an old android device as “gateway” instead of DD-WRT or another PC?

    Thanks,

    • Of course. There is a port of OpenVPN for Android. You only need to setup the configuration file as explained above, and plug it with the key files into the OpenVPN client for Android. It is quite simple.

      • Great, appreciate the quick reply, in my scenario we have 1 OpenVPN server and I need to route 10 remote clients traffic thru 10 different remote gateways in different locations, remote clients will use always the same remote gateway/location, gateways in those remote locations ideally will be old android phones using the OpenVPN client port as you suggest. Do you have any suggestion to this setup and does this look like what you explain but with multiple gateways?

        Thanks

      • Well I am no OpenVPN expert, so please do not take my thoughts for granted. The scenario that I am describing in the post is actually meant for one server, one gateway and multiple clients, such that the whole traffic goes through the gateway. Now, to achieve want you want, one option is to instantiate 10 different OpenVPN instances (they still run on the same server, but on different ports), and you repeat the same procedure 10 time. This is relatively easy, since all you need is 10 config files. Now if you want to achieve the same thing with one server, then things get complicated, since you must configure all clients beforehand, and the server should know about them all. This is to ensure that there is no way that one client will maliciously connect to another gateway. To do this you should do the following:

        1. Create different routed lans and ignore the iroute directive completely. https://community.openvpn.net/openvpn/wiki/RoutedLans
        2. Make sure that server pushes the route to a single client. You do this by putting the route command in a client-specific file in what’s known as the client-config folder on the server i.e. client-config-dir
        3. Make sure that each client has a route that corresponds to the gateway lan (most likely using route-gateway directive, or simply route).

        I have never tested this, but I guess it is the logical thing to do, according to the documentation. Good luck.

  5. Amazing, I will pick the first option as seems easier to implement, I will let you know how it goes once I have this working, thanks for the help

  6. Great guide. But I’m struggling to replicate this behavior in my networks. Maybe you could help me — I would appreciate it very much.

    I have almost the same network configs — two LANs, one has public IP and runs VPN-server, second is a client and has access to IPTV I’m trying to share with VPN-server and its other clients. Difference is that my OpenVPN server and client (gateway) are running on routers themselves.

    I’m trying to get access to IPTV provided by ISP for remote LAN (VPN-client) by routing specific IP (91.235.x.x – IPTV-server) via VPN. And I have an interesting situation:
    – when I ping iptv-server from my LAN, it gets responds (looks like router responds instead of target).
    – when I traceroute it, there is only one hop — to the VPN-client, i.e. router, 10.8.0.2 (I’ve set up 10.8.0.x subnet for VPN, 10.8.0.1 is server, 10.8.0.2 – client with access to IPTV), and it doesn’t goes further.
    – while I am pinging IPTV-server, tcpdump on remote router (vpn-client) shows these requests AND SHOWS REPLIES from 91.235.x.x!

    So I suppose that route from VPN-server to client’s IPTV is OK, but route back to VPN-server is cut by the router (which is a VPN-client). And I can’t figure out why.

    Maybe you have some thoughts? I’d be very, very grateful.

    Thanks!

  7. I’m using Advanced Tomato which is kinda like DD-WRT. What I want to do is have 2 VPN clients running at the same time and selectively use one or the other based on which websites I visit. Currently, I can do this in the GUI by using “route-nopull” on both clients and specifying certain websites on one client and then specifying .ca .com and .net on the other. When I do this, traffic routed through the VPN clients is VERY slow. Maybe selecting .ca .com and .net as ranges is too broad? When I run only one VPN client at a time, speeds are excellent.

  8. I believe it is design defect(bug) in openvpn that makes “iroute 0.0.0.0 128.0.0.0” not work correctly. It simply ignore “0.0.0.0” of any side.
    To work around this defect, you can do below which is equivalent to “iroute 0.0.0.0 128.0.0.0”

    iroute 64.0.0.0 192.0.0.0
    iroute 32.0.0.0 224.0.0.0
    iroute 16.0.0.0 240.0.0.0
    iroute 8.0.0.0 248.0.0.0
    iroute 4.0.0.0 252.0.0.0
    iroute 2.0.0.0 254.0.0.0
    iroute 1.0.0.0 255.0.0.0

    by the way, “iroute 128.0.0.0 128.0.0.0” works well as is.
    So, if you want to do “default all traffic to go via tunnel” you can add add “iroute 128.0.0.0 128.0.0.0” to the groups above.

    Any questions? comments?

  9. You don’t need a billion iroute lines. To route “The Internet” in all of its IPv4 entirety, this is enough:

    iroute 0.0.0.0 248.0.0.0
    iroute 8.0.0.0 254.0.0.0
    iroute 11.0.0.0 255.0.0.0
    iroute 12.0.0.0 252.0.0.0
    iroute 16.0.0.0 240.0.0.0
    iroute 32.0.0.0 224.0.0.0
    iroute 64.0.0.0 192.0.0.0
    iroute 128.0.0.0 224.0.0.0
    iroute 160.0.0.0 248.0.0.0
    iroute 168.0.0.0 252.0.0.0
    iroute 172.0.0.0 255.240.0.0
    iroute 172.32.0.0 255.224.0.0
    iroute 172.64.0.0 255.192.0.0
    iroute 172.128.0.0 255.128.0.0
    iroute 173.0.0.0 255.0.0.0
    iroute 174.0.0.0 254.0.0.0
    iroute 176.0.0.0 240.0.0.0
    iroute 192.0.0.0 255.128.0.0
    iroute 192.128.0.0 255.224.0.0
    iroute 192.160.0.0 255.248.0.0
    iroute 192.169.0.0 255.255.0.0
    iroute 192.170.0.0 255.254.0.0
    iroute 192.172.0.0 255.252.0.0
    iroute 192.176.0.0 255.240.0.0
    iroute 192.192.0.0 255.192.0.0
    iroute 193.0.0.0 255.0.0.0
    iroute 194.0.0.0 254.0.0.0
    iroute 196.0.0.0 252.0.0.0
    iroute 200.0.0.0 248.0.0.0
    iroute 208.0.0.0 240.0.0.0

  10. Thanks.. used this to view greek channels. Worked as a charm.. Actually the only thing I was missing, was the iroutes. I was using iroute 0.0.0.0 which did not work

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