Obfuscating Wireguard: hide VPN traffic with Shadowsocks
Use Shadowsocks to obfuscate Wireguard traffic and bypass firewalls.
Wireguard is probably one of the most important network innovations that has blessed Linux (and everything else) in recent years. Its predecessor, OpenVPN, is slow and cumbersome to configure and use. Wireguard, on the other hand, utilizes a faster crypto algorithm and only relies on common Linux networking tools. Moreover, it can be (and already is!) deployed everywhere! For example, cloudflare warp is pure Wireguard.
So, if Wireguard is so good, why not just use it on all your devices? You can forget about leaking your IP addresses or being DDoSed ever! The problem is, despite all of Wireguard's goodies, there is one minor issue:
Say you don't want your ISP to figure out that you are using a VPN for some reason. Maybe your ISP throttles VPN traffic. Perhaps they forbid users from using one in the first place due to shitty local regulations. In this case, Wireguard alone is not adequate enough to hide your traffic.
Wireguard traffic: Easily identifiable?
Sometimes, my Wireguard traffic will get disconnected when I attempted to use it over college WiFi. At first I thought that the VPN server was broken and spent hours debugging it. While in fact, the school firewall detected my VPN connection and dropped it (I have no idea why).
Believe it or not, hiding its own traffic, or "obfuscating", is not the focus point of Wireguard. Its website specifically stated that "Obfuscation should happen at a layer above Wireguard". It is kind of counter-intuitive, as it shouldn't be hard to just implement obfuscation in the Wireguard protocol in the first place, given it uses chacha20-poly1305
cipher. On contrast,
The network tool Wireshark already has Wireguard identification support in its source code for a long time. If anyone with Wireshark can do it, it is not hard to imagine your corporate or school network intentionally filtering out Wireguard VPN traffic (GFW wink wink).
For residential ISPs, they seldom filter out VPN traffic intentionally. But that does not stop them from deliberately slowing down Wireguard traffic with all those UDP traffic de-prioritization crap.
Moreover, isn't it better if the ISP does not know you are using a VPN at all?
Great, how to hide my Wireguard traffic?
With some help from our old friend: shadowsocks
. According to its front page,
However, this lightweight proxy supports tunneling TCP and UDP traffic, with AEAD ciphers for extra confidentiality. It is perfect for hiding our Wireguard UDP traffic, and from my personal experience, is proven to circumvent the strongest censorship currently possible.
Installing Shadowsocks
If your server runs Debian or Ubuntu,
sudo apt install shadowsocks-libev
If your servers runs Arch Linux or Manjaro,
sudo pacman -S shadowsocks-libev
Using the same procedure as before, install shadowsocks
on your local computer. If your computer runs macOS,
brew install shadowsocks-libev
Run Shadowsocks on your server
After installing it, create shadowsocks
server's config file with the following content, and name it as wg-tun.json
.
{
"server": "0.0.0.0",
"server_port": <desired port>,
"password": "<desired password>",
"timeout": 300,
"method": "chacha20-ietf-poly1305",
"mode": "tcp_and_udp"
}
Here, <desired port>
is the server port listened by shadowsocks. <desired password>
is a secret password for authenticating shadowsocks connections. It's basically a second password.
Then, run shadowsocks server on your Wireguard server by executing
ss-server -c wg-tun.json
Tunnel Wireguard
Create shadowsocks
tunnel's config file on your local computer with the following content as wg-tun.json
.
{
"server": "<Wireguard server's IP address>",
"server_port": <server port>,
"local_address": "0.0.0.0",
"local_port": 5634,
"password": "<server password>",
"timeout": 300,
"method": "chacha20-ietf-poly1305",
"mode": "tcp_and_udp",
"tunnel_address": "127.0.0.1:<Wireguard server's port>"
}
Here, <server port>
and <server password>
are from last step.
<Wireguard server's IP address>
is your shadowsocks server's IP. Since we are hosting Wireguard and shadowsocks on the same server, they should be identical.
<Wireguard server's port>
is ListenPort
of Wireguard server.
Then, run shadowsocks
tunnel on your local computer by executing
ss-tunnel -c wg-tun.json
Configure Wireguard to use the tunnel
Open your Wireguard client's config.
In section [Peer]
, change value of entry Endpoint
into 127.0.0.1:5634
, the local Wireguard endpoint tunneled through shadowsocks
. Your configuration file should look similar to this:
Restart your Wireguard client. Now all your Wireguard traffic are hidden from ISPs!
My Wireguard still gets randomly disconnected
Well, we only hid the fact that you are using Wireguard. Even after shadowsocks, your VPN tunnel still uses UDP. It is possible that your network unconditionally filters out UDP traffic for unethical reasons such as "UDP stresses the network out" or "preventing abuse".
It is technically still solvable. There are plenty of ways to fake a TCP connection from UDP packets. However, that topic is for another article. For hiding your VPN traffic from the ISP alone, shadowsocks
is more than good enough.