Bypassing the censorship in Russia Link to heading

The level of censorship in Russia has been increasing over last few decades and was pushed to the new heights after the war has started. In the following post I would like to discuss the options we have to bypass the restrictions (of course you can just buy VPN subscription and be done with that, but we are the engineers, right?).

Suppose we are connected to our network provider and want to access the resource that is blocked by government firewall. From network perspective what we need is to route our traffic, or information flow, through some server in internet. This server should be reachable by us and at the same time this resource should be able to access the resource that is blocked in our home network.

Suppose we have our virtual private server (VPS) with public IP address 55.55.55.55: we can directly access it and from this we can connect to our blocked resource. The preferable route of the traffic is shown in violet. If we do not have this route we will be never able to get to our blocked destination.

svg

Option 1: Outline Link to heading

One of the easiest solutions is to install Outline1 on your private: it allows to easily create and manage your own VPN server. The whole pipeline consists of three steps:

  1. Install Outline Manager on your VPS.
  2. Generate access keys and distribute them across the clients (friends, family, etc.).
  3. Clients connect to VPN using these keys and Outline Client app for their favourite platform (Windows, Linux, Android).

The how-to for Outline is described here.

Option 2: XRay or V2Ray Link to heading

XRay2 is the successor of V2Ray3 – the collection of tools that help users build their own basic communication networks. In China this tool is very popular for bypassing the Great Firewall and accessing the blocked content. XRay works as proxy tool: it starts the local proxy on client machine and routes all the traffic from this proxy to one or another destination.

The configuration and route rules are very flexible: requests can be re-routed based on their target ip, domain or even protocol. New rules can be created very easily. The killer-feature of XRay for me is its ability to re-route only the requests to blocked websites through VPS and directly access all the others.

Server setup Link to heading

Issue the following command4 on your server:

bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install-geodata

Verify that the configuration file /usr/local/etc/xray/config.json was created. Create more clients if required:

Spoiler
{
    "inbounds": [
        {
            "port": 11123, // Port you want to use from server side, select freely
            "protocol": "vmess",
            "settings": {
                "clients": [
                    {
                        "id": "37292d7c-ac1c-44ef-8c20-5864a6d62ac5" // Client 1, generate your own UUID
                    },
                    {
                        "id": "9d5ca145-070e-4c88-92d7-a32a167dde6e" // Client 2, generate your own UUID
                    }
                ]
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom"
        }
    ]
}

Client setup Link to heading

For client we have to create config.json file and set up the configuration, then we can use this same file for all our clients (Linux, Windows, Android) and change only UUIDs. I will leave mine config.json here for convenience. Do not forget to change the configuration parameters.

Spoiler
{
    "inbounds": [
        {
            "port": 10808,          // Port for proxy on client side, you can use your own
            "listen": "127.0.0.1",
            "protocol": "socks",
            "settings": {
                "udp": true
            },
            "sniffing": {
                "enabled": true,
                "destOverride": [
                    "http",
                    "tls"
                ]
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom",
            "tag": "direct"
        },
        {
            "protocol": "vmess",
            "settings": {
                "vnext": [
                    {
                        "address": "55.55.55.55", // IP address of our VPS server
                        "port": 11123,            // Port on the server
                        "users": [
                            {
                                "id": "37292d7c-ac1c-44ef-8c20-5864a6d62ac5" // You have to change it for other users
                            }
                        ]
                    }
                ]
            },
            "tag": "vpn"
        },
        {
            "protocol": "blackhole",
            "settings": {},
            "tag": "block"
        }
    ],
    "routing": {
        "domainStrategy": "IPIfNonMatch",
        "rules": [
            {   // Rule 1: we want to route all ads to tag 'block'
                "type": "field",
                "outboundTag": "block",
                "domain": [
                    "geosite:category-ads-all"
                ]
            },
            {
                // Rule 2: we want to access all internal networks directly
                "type": "field",
                "outboundTag": "direct",
                "ip": [
                    "geoip:private"
                ]
            },
            {
                // Rule 3: we also want to acess some resources directly
                "type": "field",
                "outboundTag": "direct",
                "domain": [
                    "domain:leroymerlin.ru",
                    "geosite:yandex",
                    "domain:mirconnect.ru",
                    "domain:vk.com",
                    "domain:sberbank.ru"
                ]
            },
            {
                // Rule 4: the list of resources that have to be routed to our vpn tag.
                "type": "field",
                "outboundTag": "vpn",
                "domain": [
                    "domain:meduza.io",
                    "domain:istories.media",
                    "geosite:twitter",
                    "geosite:facebook",
                    "geosite:instagram",
                    "geosite:category-media",
                    "geosite:category-entertainment"
                ]
            }
        ]
    }
}
Depending on the target platform the following setup options are available:

  • Linux – install XRay in the same manner as for server, edit the /usr/local/etc/xray/config.json as described earlier, use systemctl restart xray or service xray restart if something goes wrong.
  • Windows – download the binaries from 5, add binary to autostart while providing the path to config.json file.
  • Android – download APK from 6, install, import config.json.

Option 3: Wireguard Link to heading

As another option we can use Wireguard7 to organize the tunnels between our VPS and host to bypass the restrictions. Another benefit of Wireguard is the easiness of deployment site-to-site VPN. Connecting several distant local area networks (LAN - for example your home and villiage networks behind routers) using VPN has the following benefits:

  1. we can access the clients of all LANs directly by internal IPs;
  2. we can forward not all the traffic through VPN, but only the traffic between our LANs, while accessing all the other website directly, without loading our VPS server.

Let’s assume we want to connect our home network (192.168.101.0/24 subnet), countryhouse network (192.168.102.0/24 subnet) and the laptop. The two LANs are managed by OpenWrt routers. As initial request we want our VPN to tunnel only LAN-to-LAN traffic. If in future we want to tunnel all the traffic through VPN we will have change only one line in our configuration, I will show which one.

Our VPS server has the same IP address 55.55.55.55 and we allocate 10.3.2.0/24 subnet for wireguard network. The scheme of our network is shown here:

svg

Having this setup we can access 192.168.102.0/24 hosts while being connected to 192.168.101.0/24 network and vice-versa. For example, we can access CCTV camera from our PC, and access the printer from the laptop. If we are connected to our OpenWrt routers (192.168.101.1 and 192.168.102.1) we do not even need to set up a wireguard tunnel to our VPS, OpenWrt will handle all the connections. If we are outside our routers, we will have to connect to our VPN using wireguard client for PC or smartphone.

Server setup Link to heading

Install wireguard on the server:allow traffic forwarding between interfaces:

sudo apt install wireguard

allow traffic forwarding between interfaces and enable proxy ARP:

sudo sysctl -w net.ipv4.ip_forward=1
sudo sysctl -w net.ipv4.conf.all.proxy_arp=1

Create and set up the config file for wireguard (/etc/wireguard/wg0.conf), where EXTERNAL_ETHERNET is the main internet interface on your server:

Spoiler
[Interface]
Address = 10.3.2.1/24
ListenPort = 51820
MTU = 1420
PrivateKey = YOUR_PRIVATE_KEY
PostUp = sysctl --write net.ipv4.ip_forward=1; sysctl --write net.ipv6.conf.all.forwarding=1; nft add table inet wireguard-wg0; nft add chain inet wireguard-wg0 wireguard_chain {type nat hook postrouting priority srcnat\;}; nft add rule inet wireguard-wg0 wireguard_chain oifname EXTERNAL_ETHERNET masquerade
PostDown = sysctl --write net.ipv4.ip_forward=0; sysctl --write net.ipv6.conf.all.forwarding=0; nft delete table inet wireguard-wg0
SaveConfig = false
# OpenWrt 192.168.101.0/24 config
[Peer]
PublicKey = YOUR_CLIENT_PUBLIC_KEY_1
PresharedKey = YOUR_PRESHARED_KEY_1
AllowedIPs = 10.3.2.2/32,192.168.101.0/24
# OpenWrt 192.168.102.0/24 config
[Peer]
PublicKey = YOUR_CLIENT_PUBLIC_KEY_2
PresharedKey = YOUR_PRESHARED_KEY_2
AllowedIPs = 10.3.2.3/32,192.168.102.0/24
# Laptop config
[Peer]
PublicKey = YOUR_CLIENT_PUBLIC_KEY_3
PresharedKey = YOUR_PRESHARED_KEY_3
AllowedIPs = 10.3.2.4/32
# laptop end
Replace all the keys with your own, generated by wg genkey command. Note that every client has unique public and preshared keys.

Client setup Link to heading

Create configs for your clients, note the AllowedIPs section, they differ depending on the client, OpenWrt 1 config:

# Openwrt 192.168.101.1
[Interface]
Address = 10.3.2.2/32
DNS = 10.3.2.1
ListenPort = 29516
MTU = 1280
PrivateKey = YOUR_PRIVATE_KEY
[Peer]
AllowedIPs = 192.168.102.0/24,10.3.2.0/24
Endpoint = YOUR_SERVER_IP:51820
PersistentKeepalive = 25
PresharedKey = YOUR_PRESHARED_KEY_1
PublicKey = YOUR_CLIENT_PUBLIC_KEY_1

OpenWrt 2 config:

# Openwrt 192.168.102.1
[Interface]
Address = 10.3.2.3/32
DNS = 10.3.2.1
ListenPort = 29341
MTU = 1280
PrivateKey = YOUR_PRIVATE_KEY
[Peer]
AllowedIPs = 192.168.101.0/24,10.3.2.0/24
Endpoint = YOUR_SERVER_IP:51820
PersistentKeepalive = 25
PresharedKey = YOUR_PRESHARED_KEY_2
PublicKey = YOUR_CLIENT_PUBLIC_KEY_2

Laptop config:

# Laptop 10.3.2.4
[Interface]
Address = 10.3.2.4/32
DNS = 10.3.2.1
ListenPort = 54921
MTU = 1280
PrivateKey = YOUR_PRIVATE_KEY
[Peer]
AllowedIPs = 192.168.101.0/24,192.168.102.0/24,10.3.2.0/24
Endpoint = YOUR_SERVER_IP:51820
PersistentKeepalive = 25
PresharedKey = YOUR_PRESHARED_KEY_3
PublicKey = YOUR_CLIENT_PUBLIC_KEY_3

If you want to send all the traffic through VPN tunnel, just change AllowedIPs string on the client to 0.0.0.0/0.

While rolling out this setup on OpenWrt I created the special VPN zone for firewall and assigned this zone to wireguard interface. The rules of the zone are the following:

  • VPN => LAN: accept input, accept output, accept forward, allow masquerading;
  • LAN => VPN: accept input, accept output, accept forward.

The OpenWrt will start up the wireguard automatically. If you want to start the wireguard tunnel on you laptop copy the config to /etc/wireguard/wg0.conf and issue the command:

sudo wg-quick up wg0

Now you should be able to ping and traceroute all the other LAN-clients succesfully (if everything works, of course):

laptop$ traceroute 192.168.102.135
traceroute to 192.168.102.135 (192.168.102.135), 30 hops max, 60 byte packets
 1  10.3.2.1 (10.3.2.1)  144.531 ms  145.366 ms  145.247 ms
 2  10.3.2.3 (10.3.2.3)  233.145 ms  233.032 ms  233.023 ms
 3  192.168.102.135 (192.168.102.135)  246.700 ms  250.677 ms  250.604 ms

Wireguard obfuscation Link to heading

Since WireGuard is frequently blocked by traffic analysis systems, obfuscating its traffic is often necessary.

This can be achieved by installing the Shadowsocks server and client components on all machines8, and then obfuscating WireGuard packets9.

Links Link to heading