Building a Split-Tunneling Personal VPN Gateway: A Practical Setup with WireGuard, sing-box, and Gluetun
In a previous article, I introduced a fairly straightforward chained VPN setup: all devices first connect to a self-hosted WireGuard server, and the server then forwards traffic to Gluetun, which finally sends it to the Internet through an upstream VPN provider. The core value of that setup was clear: Each device only needs to be configured with WireGuard once; The upstream VPN only needs to be maintained on the server side; Phones, computers, tablets, and home devices can all be connected to the same virtual LAN; The exit IP is provided by a commercial VPN, corporate VPN, or another upstream VPN, rather than directly exposing the VPS IP; The whole system can be deployed with Docker, minimizing pollution of the host environment; Compared with connecting directly to a VPN provider, the provider only sees the exit of your VPN gateway, namely your VPS server, instead of the real IP address of each individual device; In addition, your local ISP and similar parties cannot easily tell whether you are using a mainstream VPN service, because they can only see that you are connecting to a VPN gateway, namely your VPS server. Where the traffic eventually goes remains unknown to them. However, as my use cases expanded, the original structure gradually started to reveal some limitations. The most typical issue was that traffic control was not fine-grained enough. By default, all traffic had to enter the upstream VPN tunnel, which could trigger risk-control mechanisms or cause access problems for certain services. It was also not very convenient to perform traffic engineering and apply different exit strategies to different services. Although split routing could be achieved with iptables and routing tables, the rules became difficult to maintain once they grew in number. ...