WireGuard to Shadowsocks: Ready Docker Setup

WireGuard to Shadowsocks: Ready Docker Setup

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:

VPN firefox config

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.
VPN Site-to-site schema

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 😅.

Setup

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!

VPN Garage server

I hope this setup will help you build your own site-to-site VPN!

Related Posts

© 2024 Anton Zalialdinov. All Rights Reserved.