WireGuard netns bridge

WireGuard netns bridge is a shell script which creates a new network namespace with a WireGuard interface as its default route, where the UDP socket of the WireGuard interface is in the existing network namespace. The new network namespace can be connected to the host using a veth device which is created by the script, and the veth device on the host can be bridged to an external WiFi (using hostapd) or Ethernet adapter to allow additional clients to connect through the VPN. This setup is similar to the one described in https://www.wireguard.com/netns. The main advantage of using network namespaces is that the IP address ranges between the existing network namespace and the new network namespaces can still overlap and not interfere. This is important on public WiFi networks, where the operator of the WiFi network can use whatever IP address ranges it wants, and the operator could choose IP address ranges which could strategically implant routing table entries by way of the IP address and subnet mask (see IP Configuration Rant) to cause legitimate traffic to a server on the other side of the VPN to be routed towards an operator-controlled host instead.


The desire for non-interfering VPN networks originated with an old OpenVPN setup in layer 2 mode. The setup involved running a DHCP and DNS server on the VPN server's TAP interface, and not using any IP address configuration on the OpenVPN level. If, on the client, the OpenVPN TAP interface was bridged to an external interface, which was usually a secondary Ethernet port or a WiFi adapter using hostapd, then anything connected on that Ethernet port or WiFi adapter connected directly to the VPN server, and it would work even if the VPN client were to be connected to a network with overlapping IP address ranges, which could be the case if the VPN client host were to be connected to public WiFi. The downstream clients were also considered to be under a "kill switch", which effectively disconnected them from the Internet if the VPN connection was severed. (The host was not, but it was hardened to the point where it could still remain safe on public WiFi, such as using only encrypted connections for applications like apt-get, either disabling the SSH server or disabling password authentication on the SSH server, disabling unnecessary ports, and enabling HTTPS-only mode on the web browser (Firefox)[1].) The final setup before I switched to WireGuard was that the bridge would receive an IPv6 address through SLAAC on the VPN server, and clients connected to the Ethernet port or WiFi adapter received both IPv4 and IPv6 addresses. This was very useful as I hopped between multiple WiFi networks on and off the University of Illinois campus.

After I went back to the University of Illinois after the whole COVID fiasco, the VPN setup switched to WireGuard. Unlike OpenVPN, WireGuard was layer 3 only. To allow a similar setup with WireGuard instead of OpenVPN, it was necessary to have some sort of layer 3 "router" and run the DHCP and DNS server directly on the VPN client, rather than on the server. The only way we could feasibly achieve a similar non-interfering setup without massive complication was to create a new network namespace and run the DHCP and DNS server within that namespace. The WireGuard netns bridge script was created to facilitate that operation.

See also

  1. I also had an SSH server on the other side of the VPN, which allowed me to create a SOCKS server to use with the web browser -- this was pre-Universal Relay. There were two profiles, one called "default" which connected through the proxy, the other called "uiuc-login" which did not use a proxy since it was originally used to authenticate into the University of Illinois's captive portal. This was before HTTPS-only mode existed on Firefox, so I had to be careful not to trust non-encrypted websites on the uiuc-login profile before HTTPS-only mode was available.