I have a wireguard connection (interface name wg0) to a trusted machine inside an admin network at $DAYJOB. Usually, I don't want to use wg0 for all my traffic, only for IP addresses in the range. This is easily accomplished with a stanza like so in /etc/wireguard/wg0.conf:

# ...
AllowedIPs  =

But for one firefox profile, I do want to route everything through wg0, even traffic not destined for Furthermore, for DNS, I usually use dnscrypt-proxy + dnsmasq, but for wg0 traffic I want to use the nameserver at $DAYJOB.

I can almost match these constraints by having a network namespace created with ip netns and a veth pair. Inside the namespace, simply replace my default resolv.conf with one containing the alternative nameserver. The only problem is that I haven't quite figured out how to use wg0 as the sole way for packets to leave the namespace.

  • Non-default DNS used: ✓
  • Traffic from the namespace destined for is correctly routed through wg0: ✓
  • All other traffic exiting the namespace also goes via wg0: ✗

Wireguard has documentation related to netns but it seems to assume you don't still need the wireguard interface outside the namespace. I do want everything outside the namespace to still have access to the wireguard interface.

Some sources, eg 1, suggest something similar using vlans. However, it seems like wireguard interfaces do not support vlans. Here is what happens:

$ sudo ip link add link wg0 name wg0.4 type vlan id 4
$ sudo ip netns add ns-wg-test-1
$ sudo ip link set wg0.4 netns ns-wg-test-1
$ sudo ip netns exec ns-wg-test-1 su -c "/bin/bash -l" $USER
$ sudo ip addr add dev wg0.4
$ sudo ip link set dev wg0.4 up
RTNETLINK answers: Cannot assign requested address

So now I'm equivocating between various alternative approaches which all have problems.

Possibility 1: Add a second wireguard interface. That will require making a bunch of redundant configs in /etc/wireguard/wg1.conf. It's not clear that this is even workable or a good idea. It seems inelegant to have multiple wireguard interfaces and redundant configs.

Possibility 2: Add some combination of ip route and iptables -A rules to force everything exiting the namespace to then be channelled into wg0. However, I haven't come across any examples or documentation which makes it clear how to force the routing of all traffic incoming from one interface to go out via another interface. And again, I have a certain amount of skepticism that this would even be a good approach.

Possibility 3: Have faith in the wireguard documentation. Put wg0 inside the namespace, and tell all traffic outside the namespace to go via a veth pair connected to the namespace. Inside the namespace, there could be routing/firewall rules to forward everything from the veth pair to wg0. The problem with this solution is that, even if it works, it requires the namespace to always be active. I would like traffic destined for to always find its way to wg0 regardless of whether I remembered to activate the namespace this morning.

So the question is: what is the best or most canonical way to share a wireguard interface with a network namespace, while still retaining access to wireguard outside of the namespace?

This isn't opinion-based. I'll know the answer is right when I can see a working example which is robust, efficient, secure, and scriptable. It doesn't need to be cross-platform. I am doing this solely on Void Linux (or sometimes Arch Linux).

Alternatively, if the whole enterprise is not a good idea, or not possible for some reason, a negative answer could consist of arguments, evidence, and citations to explain why. I'll still mark it as correct if nothing better comes along.

  • 1
    VLAN relies on layer 2. WireGuard is layer 3 (ip or ipv6, no other type) => no VLAN. Possibility 1 seems the simplest. Simple is part of the KISS principle...
    – A.B
    Feb 13, 2021 at 11:02
  • @A.B Good point about layer 2 vs layer 3. Actually I could probably just symlink wg0.conf -> wg1.conf. This could work.
    – cryptarch
    Feb 14, 2021 at 0:13
  • Yes, you're right, of course. A pity that wireguard configuration doesn't seem to be very modular then. Maybe templates is the way to go.
    – cryptarch
    Feb 14, 2021 at 21:03

2 Answers 2


So the question is: what is the best or most canonical way to share a wireguard interface with a network namespace, while still retaining access to wireguard outside of the namespace?

IMO, a good approach would be to use policy-based routing for this. E.g, "any packet coming from interface A should use routing table B", where interface A is the veth/bridge interface outside the netns and routing table B only containing routes via your wireguard interface (and of course the route back to the originating network namespace). Using iproute2, something along these lines:

# echo "100 dayjob" >> /etc/iproute2/rt_tables
# ip route add <wireguard glue net> dev wg0 table dayjob
# ip route add default via <wireguard gw> dev wg0 table dayjob
# ip route add <netns net> dev <veth/bridge interface> table dayjob
# ip rule add iif <veth/bridge interface> lookup table dayjob
  • Interesting idea! Thanks, I'll probably try this out
    – cryptarch
    Feb 16, 2021 at 19:07

You question asks to route the firefox traffic through your server. A simpler approach would be to configure the profile to use a SOCKS proxy.

Simply ssh to your server with ssh -D 1080 SERVERNAME:

 -D [bind_address:]port
         [...] Currently the SOCKS4 and SOCKS5 protocols are supported, and ssh will
         act as a SOCKS server.

Also configure network.proxy.socks_remote_dns in firefox

  • It's a reasonable point, but the question isn't really an XY problem. I already have the namespace active anyway, for other things like sshing through to our servers. The namespace needs to be there so that I can switch dns. So the question isn't just "how to make all firefox traffic go through another location", it's really "given that I'll be using wireguard and network namespaces anyway, how can the integration between them be improved?"
    – cryptarch
    Feb 15, 2021 at 20:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .