Seamless bypassing of network censorship

In my home country (Russia), censorship has taken quite a big turn after the government decided to block the Telegram Messenger.

Since early 2018, I am unable to join quite a lot of genuine websites like bitbucket.org. Only because the government blocks millions of IPs just to attempt to block Telegram.

Just a year ago, I was all sorts of proud with Internet in my country. For as little as $9, you can get 100MB/s connection in Russia. But the recent silly bans resulting in disruption of access to regular websites, makes every cent worth it.

In a more civilised country, the ISPs and the government would be sued for these access issues. But not in Russia.

So what can we do? We can bypass the restrictions via VPN, but it is cumbersome (and slow) to always be connected to the VPN only to be able to retain access to a handful of blocked websites.

Ideally, we should only use VPN or a proxy server just for the blocked websites. And other websites would be accessed directly, and retain good network performance. So meet Automatic Proxy Configuration in your home network!

Pre-requisites

There are some things you should have in order to achieve seamless access to banned websites.

The Proxy Server

I work as a server engineer so quite many of my clients are OK to allow using their server for this purpose. Alternatively, you can just set it up yourself, by getting the smallest Linode and putting Privoxy on it.

Naturally, you have to firewall it in a way that only your IP address (or the IP ranges of your provider, if you don’t have static IP) is able to access it.

The Router

You need a home network router with DD-WRT firmware on it. You might be able to use something else, but for the sake of this tutorial, we describe how to get things done with DD-WRT.

Proxy Configuration File

You need to prepare the proxy configuration file that lists websites which will use proxy.
You can use this as a template:

function FindProxyForURL(url, host) {

    if (dnsDomainIs(host, ".linkedin.com") || shExpMatch(host, "*.linkedin.com"))
        return "PROXY 1.2.3.4:8118";

    if (dnsDomainIs(host, "bitbucket.org"))
        return "PROXY 1.2.3.4:8118";

    // DEFAULT RULE: All other traffic, goes directly.
    return "DIRECT";

}

DD-WRT setup

Suppose that your router’s IP address is 192.168.10.1.

You need to enable JIFS in your router and plug-in a USB stick into it. The stick has to be formatted via FAT filesystem. The USB stick is optional, but it allows to store some files web accessible from your router’s IP address.

If you want things to work without USB, you just need a startup script to write proxy configuration file upon startup.

rm -rf /tmp/www
# /jifs/www will be available at router-ip/user
ln -sf /jffs/www /tmp/www

/www/user is a symlink to /tmp/www in a standard DD-WRT setup. So you can create proxy configuration file /www/user/proxy.js with the following contents of proxy configuration file above.

If you’ve done things right, opening http://192.168.10.1/user/proxy.js in your browser will show contents of the file.

Next, in web admin of your router, proceed to Services -> DNSMasq and for “Additional DNSMasq Options”, specify:

dhcp-option=br0,252,http://192.168.10.1/user/proxy.js

Optionally, add cache-size=1500 to ensure DNS cache efficiency of your router.

This will allow your router to deliver message to its DNS clients, indicating URL of the proxy configuration file.

OS setup

Naturally, you need to configure the router IP to be the DNS server for all your network devices. Which is the best way in terms of performance, anyway.

Aside from that you need to specify either “Automatic proxy configuration” (just a checkbox in OS X), or put the proxy configuration file location in settings: http://192.168.10.1/user/proxy.js.

OS X Specifics

If you have edited your proxy configuration file and want Safari to re-read it, you can run this in Terminal:

networksetup -listallnetworkservices | awk 'NR>1' | while read SERVICE ; do
    if networksetup -getautoproxyurl "$SERVICE" | grep '^Enabled: Yes' >/dev/null; then
      networksetup -setautoproxystate "$SERVICE" off
      networksetup -setautoproxystate "$SERVICE" on
      echo "$SERVICE" bounced.
    fi
  done

You may also like...

Leave a Reply

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