After moving to a different country and having some days of vacations left, one of my concerns was to get the whole home IT setup working again. Precisely, for me this involves setting up my server again, building the network infrastructure and wireless access points as well as ensuring all my everyday services are up and running. One thing I came across when doing this, is the hassle of geoblocked streaming services which I still do want to use. So while my Netflix subscription still works out-of-the-box on my TV, the Amazon Prime Video service is not working anymore. Hence, in this article I will show you how circumventing the amazon geoblocking features is actually possible with only open-source tools.
I can still sign in to my Amazon account and see all the movies and shows. However, nothing is available to be watched in my country, i.e., in Denmark. After a while I realized, I am not looking at my German Amazon interface but the UK one. No surprise, I can login to the UK Prime Video service. But as my Prime subscription runs on the German branch, I do not have access to the UK movies and shows.
So, I had a look at the network traffic of my TV. I noticed that the communication with Amazon always started with a call to the website
atv-ext-eu.amazon.com. First, I thought this website uses some kind of geolocating my IP address and then determining to which branch I shall be redirected. During transmission of this address, I thought I can intercept the response and alter it to the German branch. Then, I would have my TV once again talking to the German Prime Video. However, there was no response and apparently the forwarding happens on the server-side.
Normally, people use proxies or VPN services circumventing these amazon geoblocking problems. Unfortunately, my TV neither comes with a proxy or even a VPN configuration possibility. One solution, thus, would be to configure my router to route every traffic via a German VPN. But, then I would always go through this bottleneck, even for services which do not need it. On the one hand my router does not allow for such a configuration, on the other hand, this is not a viable solution for me. Hence, I built my very own approach to solve this problem.
I have a small server in my network for different services anyway. The idea is simple: intercept all traffic from my TV and route it through a VPN endpoint in Germany.
First step is to configure the IP address of my home network server as the default gateway of my TV. Then, we need to make sure that the server actually forwards IP packets destined for other machines.
1sysctl -w net.ipv4.ip_forward=1
For the VPN connection, I ordered a small virtual private server in Frankfurt, Germany, with unlimited traffic and a decent enough bandwidth. This server and the server in my home network are configured to establish a wireguard connection. While the main setup is as usual I took some modifications. The general setup for a VPN server is well explained on the ArchLinux wiki.
The server will be the machine in Frankfurt.
1[Interface] 2Address = 10.42.0.1/24 3ListenPort = 51871 4PrivateKey = PRIVATEKEY_OF_VPN_SERVER 5 6PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE 7PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE 8 9[Peer] 10PublicKey = PUBLICKEY_OF_HOME_ROUTER 11AllowedIPs = 10.42.0.2/32, 192.168.42.180/32 12Endpoint = HOME_NETWORK_IP:51871 13PersistentKeepalive = 25
In contrast to the default wireguard VPN setups, I added the post up and down directives to ensure the VPN server actually performs network address translation. Obviously, you need to have iptables up and running for this. A second important point is, that we need to include all IP addresses in AllowedIPs which may redirect traffic through this VPN. As I have different subnets for the VPN itself and my actual home network, I have the wireguard address of my home server (10.42.0.2) and the local IP address of my TV (192.168.42.180).
Afterwards, we can just start the network interface with
wg-quick up wg0.
The client is the machine in my home network.
1[Interface] 2Address = 10.42.0.2/24 3ListenPort = 51871 4PrivateKey = PRIVATEKEY_OF_HOME_ROUTER 5 6[Peer] 7PublicKey = PUBLICKEY_OF_VPN_SERVER 8AllowedIPs = 0.0.0.0/0, ::/0 9Endpoint = VPN_ENDPOINT_IP:51871 10PersistentKeepalive = 25
As I wrote in the beginning, I use the server in my home network for several other services which are in parts also publicly available. These services I do not want to route through the VPN but through my original internet connection as I do have a much bigger bandwidth there.
With iptables, wireguard uses a second routing table to separate its rules from your normal routing. On my system, this second table got named
51820. Wireguard then just creates one rule which captures all traffic not marked with
51820 to go through the new second routing table. At the same time, wireguard itself is able to mark all traffic coming from the remote endpoint with that mark. Hence, it is routed using your default table. To prevent routing every traffic through the VPN, we exchange this mark filter for a better suited one. After starting the wireguard interface with
wg-quick up wg0, I remove the general routing rule which enforces all traffic to go through the VPN. Then, we replace it with a rule to only use the second routing table if we see packets coming to us on the plain network interface, i.e.,
enp3s0 on my system. This is done using the
iif (incoming interface) rule.
1ip rule del not fwmark 51820 lookup 51820 2ip rule add iif enp3s0 lookup 51820
Therefore, all traffic originating at the machine itself will be routed using the default table while only packets which arrive on
enp3s0 and are to be forwarded will use the second table.
Finally, now I can have every device in my home network choosing between two different gateways, the Danish one at
.1 and the German one via the wireguard VPN on
.19. Everything needed is just the change of the gateway on the corresponding device and appending the IP address on the VPN server to the
AllowedIPs in the wireguard configuration.
For now, everything is working fine: Prime Video and YouTube play well over this setup. But, for some unknown reason, I cannot connect to Netflix with this setup. The debugging showed it tries to reach three different servers while only two of these connections are successful. I still need to figure out what is wrong here…