TL;DR https://github.com/zloom/ss-wg-tunnel
WireGuard is a popular VPN protocol integrated everywhere. It is part of the Linux kernel, it is dead simple by itself, and open source — as every security tool should be. It works perfectly: you can run a server with a single Docker command. Previously, I used it as my VPN tool with this simple compose
:
services:
wireguard:
image: lscr.io/linuxserver/wireguard:latest
container_name: wireguard
cap_add:
- NET_ADMIN
- SYS_MODULE # optional
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- PEERS=10
volumes:
- /path/to/wireguard/config:/config
ports:
- 51820:51820/udp
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
restart: unless-stopped
You only need a remote server with Linux and Docker, then copy this file to the server and run with docker compose up
. Clients are available for every platform — they work perfectly on mobile and desktop. All your traffic goes as expected.
It has only one big disadvantage: it uses UDP and has a unique fingerprint, so your provider can easily block your traffic. A year or two ago it stopped working on my home internet.
What is the alternative?
There is one well-known tool — Shadowsocks. Just like WireGuard, you can run a server pretty easily:
services:
shadowsocks:
image: shadowsocks/shadowsocks-libev:v3.3.5
container_name: shadowsocks
ports:
- 8388:8388
- 8388:8388/udp
environment:
- METHOD=chacha20-ietf-poly1305
- PASSWORD=your_password
restart: always
It works well, but the problem is the clients. It’s not as convenient: there is an Android client and it works, but apps and browsers ignore it. On PC, you can run a local client which acts as a local proxy, so you need to configure your apps to use it. For example, I use Firefox with it — I added this in network settings:
With that, you can use Firefox with VPN — it works fine, even DNS leaks are prevented. Unfortunately, not every app respects the system proxy settings. In Windows it’s a bit better; in Linux the situation is worse.
Shadowsocks also works fine on Android TV, so you can watch whatever you want with just Shadowsocks. An important point: inside a protected perimeter, WireGuard traffic is not blocked because it is de facto an industry standard.
So I came to an obvious solution: combine them.
The complex part here is the Server B content — a combination of WireGuard and Shadowsocks. In total, it took me about a month to put it into a ready-to-use compose
file 😅.
Here is the full setup in Docker Compose: https://github.com/zloom/ss-wg-tunnel
Clone and run with:
docker compose up
Main limitations:
This works reliably only on Docker Desktop. The main challenge was setting up a multihop network between containers — quite tricky work. The key difference is that Docker Engine provides less network isolation than Docker Desktop: it uses the host network stack, so configuring routes inside containers becomes complicated. On Desktop, Docker runs in a fully isolated VM, so there’s no interference with the host network.
In this setup, all tools except WireGuard are written in Golang — this is intentional. I plan to combine everything into a single Golang app later. I originally wanted to use wireguard-go too, but ran into routing issues. Switching to the kernel version of WireGuard solved the problem.
When running your server with this setup, you might face issues with Docker Desktop autostart. I worked around this by adding a custom daemon. It’s not polished yet, so I haven’t included it in the repo.
Besides Docker, you also need a server: a VPS in your country or your own PC at home. I initially planned to run it on a Raspberry Pi because it’s compact, but when I found it works only on Docker Desktop, I repurposed my old PC and put it in the garage (its coolers are noisy!). If you run it at home, you’ll also need a static IP and a router that supports port forwarding. The setup is not too hard. In the end, I got a stable VPN server that works without manual intervention, even after reboots, and has a nice dashboard!
I hope this setup will help you build your own site-to-site VPN!
© 2024 Anton Zalialdinov. All Rights Reserved.