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.
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:
- A computer with a public IP address (the server), located anywhere in the world.
- A computer in the home country (the gateway), with a decent internet connection.
- 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:
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
export KEY_COUNTRY="CH" export KEY_PROVINCE="ZH" export KEY_CITY="Zurich" export KEY_ORG="AlenBlog" export KEY_EMAIL="firstname.lastname@example.org"
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:
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 220.127.116.11
However, THIS DOES NOT WORK in OpenVPN. Good news is that instead of using one general route, we can set routes from 18.104.22.168 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 22.214.171.124 255.0.0.0 iroute 126.96.36.199 255.0.0.0 iroute 188.8.131.52 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:
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:
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 184.108.40.206
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 220.127.116.11 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 18.104.22.168 255.255.192.0 # Cabletel DOOEL Skopje route 22.214.171.124 255.255.224.0 # Cabletel DOOEL Skopje route 126.96.36.199 255.255.192.0 # Cabletel DOOEL Skopje route 188.8.131.52 255.255.224.0 # GIV Ivan LTD Gostivar route 184.108.40.206 255.255.224.0 # NETCETERA DOOEL Skopje route 220.127.116.11 255.255.192.0 # Inel Dooel Kavadarci route 18.104.22.168 255.255.240.0 # INFEL-KTV DOO route 22.214.171.124 255.255.224.0 # KDS-Kabel Net DOOEL route 126.96.36.199 255.255.224.0 # Macedonia On-Line route 188.8.131.52 255.255.0.0 # Makedonski Telekom route 184.108.40.206 255.255.0.0 # Makedonski Telekom route 220.127.116.11 255.255.224.0 # Makedonski Telekom route 18.104.22.168 255.254.0.0 # Makedonski Telekom route 22.214.171.124 255.255.128.0 # Makedonski Telekom route 126.96.36.199 255.255.224.0 # Makedonski Telekom route 188.8.131.52 255.255.128.0 # MEGANET route 184.108.40.206 255.255.240.0 # Miksnet route 220.127.116.11 255.255.240.0 # Miksnet route 18.104.22.168 255.255.240.0 # NEOTEL Skopje route 22.214.171.124 255.255.224.0 # NEOTEL Skopje route 126.96.36.199 255.255.192.0 # NEOTEL Skopje route 188.8.131.52 255.255.128.0 # NEOTEL Skopje route 184.108.40.206 255.255.128.0 # ONE Telecom route 220.127.116.11 255.255.192.0 # ONE Telecom route 18.104.22.168 255.255.240.0 # ONE Telecom route 22.214.171.124 255.255.240.0 # ONE Telecom route 126.96.36.199 255.255.240.0 # ONE Telecom route 188.8.131.52 255.255.240.0 # PET NET DOO Gevgelija route 184.108.40.206 255.255.240.0 # T-Mobile Makedonija route 220.127.116.11 255.255.192.0 # T-Mobile Makedonija route 18.104.22.168 255.255.224.0 # TELESMART TELEKOM DOO route 22.214.171.124 255.255.224.0 # TRD " Net Kabel" route 126.96.36.199 255.255.224.0 # UltraNet d.o.o. route 188.8.131.52 255.255.224.0 # "Sv. Kiril i Metodij"
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