Gluetun likely doesn't have the proper firewall rules in place to enable this sort of traffic routing, simply because it's made for another use case (using the container's network stack directly with network_mode: "service:gluetun"
).
Try to first get this setup working with two vanilla Wireguard containers (instead of Wireguard + gluetun). If it does, you'll know that your Wireguard "server" container is properly set up. Then replace the second container that's acting as a VPN client with gluetun and run tcpdump again. You likely need to add a postrouting masquerade rule on the NAT table.
Here's my own working setup for reference.
Wireguard "server" container:
[Interface]
Address = <address>
ListenPort = 51820
PrivateKey = <privateKey>
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostUp = wg set wg0 fwmark 51820
PostUp = ip -4 route add 0.0.0.0/0 via 172.22.0.101 table 51820
PostUp = ip -4 rule add not fwmark 51820 table 51820
PostUp = ip -4 rule add table main suppress_prefixlength 0
PostUp = ip route add 192.168.16.0/24 via 172.22.0.1
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip route del 192.168.16.0/24 via 172.22.0.1
#peer configurations (clients) go here
and the Wireguard VPN client that I route traffic through:
# Based on my VPN provider's configuration + additional firewall rules to route traffic correctly
[Interface]
PrivateKey = <key>
Address = <address>
DNS = 192.168.16.81 # local Adguard
PostUp = iptables -t nat -A POSTROUTING -o wg+ -j MASQUERADE #Route traffic coming in from outside the container (host/other container)
PreDown = iptables -t nat -D POSTROUTING -o wg+ -j MASQUERADE
[Peer]
PublicKey = <key>
AllowedIPs = 0.0.0.0/0
Endpoint = <endpoint_IP>:51820
Note the NAT MASQUERADE
rule.
I think you already have a kill-switch (of sorts) in place with the two Wireguard container setup, since your clients lose internet access (except to the local network, since there's a separate route for that on the Wireguard "server" container") if any of the following happens:
wg-quick down wg0
inside the container)I can't be 100% sure, because I'm not a networking expert, but this seems like enough of a "kill-switch" to me. I'm not sure what you mean by leveraging the restart. One of the things that I found annoying about the Gluetun approach is that I would have to restart every container that depends on its network stack if Gluetun itself got restarted/updated.
But anyway, I went ahead and messed around on a VPS with the Wireguard+Gluetun approach and I got it working. I am using the latest versions of The Linuxserver.io Wireguard container and Gluetun at the time of writing. There are two things missing in the Gluetun firewall configuration you posted:
MASQUERADE
rule on the tunnel, meaning thetun0
interface.FORWARD
packets (filter table) by default. You'll have to change that chain rule toACCEPT
. Again, I'm not a networking expert, so I'm not sure whether or not this compromises the kill-switch in any way, at least in any way that's relevant to the desired setup/behavior. You could potentially set a more restrictive rule to only allow traffic coming in from<wireguard_container_IP>
, but I'll leave that up to you. You'll also need to figure out the best way to persist the rules through container restarts.First, here's the docker compose setup I used:
You already have your "server" container properly configured. Now for Gluetun: I exec into the container
docker exec -it gluetun sh
. Then I set the MASQUERADE rule on the tunnel:iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE
. And finally, I change the FORWARD chain policy in the filter table to ACCEPTiptables -t filter -P FORWARD ACCEPT
.Note on the last command: In my case I did
iptables-legacy
because all the rules were defined there already (iptables
gives you a warning if that's the case), but your container's version may vary. I saw different behavior on the testing container I spun up on the VPS compared to the one I have running on my homelab.Good luck, and let me know if you run into any issues!
EDIT: The rules look like this afterwards:
Output of
iptables-legacy -vL -t filter
:And the output of
iptables -vL -t nat
: