Wireguard doesn't route internet traffic to remote LAN

Creating a bug report/issue

I have searched the existing open and closed issues

Required Information

  • DietPi version | v9.8
  • Distro version | bookworm 0
  • Kernel version | 6.1.21-v7+ #1642 SMP Mon Apr 3 17:20:52 BST 2023 armv7l GNU/Linux
  • Architecture | armhf
  • SBC model | RPi 2 Model B (armv7l)
  • Power supply used | 5V 2A
  • SD card used | SanDisk Class A1

Additional Information

I recently gave a new life to my old RPi2 Model B with DietPi because I needed a simple headless server up 24/7 for emergency access to the internal network. I want to use it mainly for Wireguard, PiHole, Unbound and Docker (all installed software is listed below).

I tried setting up a Wireguard server configured to route all traffic through the remote network, but I’m only able to access the remote LAN, nothing past the gateway router (so no internet access, but hey at least PiHole is working fine).

I kept all the stock config, but I had to change the wg0 interface IP because it was clashing with the subnet in one of the networks I often connect from.

Remote LAN: 10.79.0.0/24 (Network is Dual-Stack)
VPN Net: 10.80.0.0/24

I tried to gather all the info that might be useful for troubleshooting the issue more easily.
Any help appreciated.

Steps to reproduce

  1. Configure wireguard interfaces:
wg0.conf
[Interface]
Address = 10.80.0.1/24
PrivateKey = REDACTED=
ListenPort = 51820

PostUp = sysctl net.ipv4.conf.%i.forwarding=1 net.ipv4.conf.$(ip r l 0/0 | mawk '{print $5;exit}').forwarding=1
PostUp = sysctl net.ipv6.conf.$(ip r l 0/0 | mawk '{print $5;exit}').accept_ra=2
PostUp = sysctl net.ipv6.conf.%i.forwarding=1 net.ipv6.conf.$(ip r l 0/0 | mawk '{print $5;exit}').forwarding=1
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -s 10.80.0.0/24 -o $(ip r l 0/0 | mawk '{print $5;exit}') -j MASQUERADE
PostUp = ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -t nat -A POSTROUTING -o $(ip r l 0/0 | mawk '{print $5;exit}') -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -s 10.80.0.0/24 -o $(ip r l 0/0 | mawk '{print $5;exit}') -j MASQUERADE
PostDown = ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o $(ip r l 0/0 | mawk '{print $5;exit}') -j MASQUERADE

# Test Client 
[Peer]
PublicKey = REDACTED=
AllowedIPs = 10.80.0.2/32
wg0-client.conf
[Interface]
Address = 10.80.0.2/24
PrivateKey = REDACTED=

# Comment the following to preserve the clients default DNS server, or force a desired one.
DNS = 10.79.0.2

[Peer]
PublicKey = REDACTED=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = MYPUBLICIP:51820

# Uncomment the following, if you're behind a NAT and want the connection to be kept alive.
PersistentKeepalive = 25

  1. Restart Wireguard service:
    systemctl restart wg-quick@wg0.service
  2. Import wg0-client.conf
  3. Test connection

Expected behaviour

  • Connection is established, both using DDNS and Public IP directly in config.
  • Remote Pi is reachable, SSH connection can be established
  • Remote LAN is reachable
  • DNS resolution works (PiHole+Unbound)
  • Internet is reachable (all traffic is routed)

Actual behaviour

Connection is established
Remote Pi is reachable, SSH connection can be established
Remote LAN is reachable
DNS resolution works
Internet is reachable

Extra details

sysctl -a | grep 'forwarding = 1'
net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.default.forwarding = 1
net.ipv4.conf.docker0.forwarding = 1
net.ipv4.conf.eth0.forwarding = 1
net.ipv4.conf.lo.forwarding = 1
net.ipv4.conf.wg0.forwarding = 1
net.ipv6.conf.eth0.forwarding = 1
net.ipv6.conf.wg0.forwarding = 1
sudo iptables -L FORWARD -v -n
Chain FORWARD (policy DROP 35686 packets, 2783K bytes)
 pkts bytes target     prot opt in     out     source               destination         
54877 4281K DOCKER-USER  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
54877 4281K DOCKER-ISOLATION-STAGE-1  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     0    --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 DOCKER     0    --  *      docker0  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     0    --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     0    --  docker0 docker0  0.0.0.0/0            0.0.0.0/0           
19191 1499K ACCEPT     0    --  wg0    *       0.0.0.0/0            0.0.0.0/0
sudo iptables -t nat -L POSTROUTING -v -n
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MASQUERADE  0    --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
 4718  345K MASQUERADE  0    --  *      eth0    10.80.0.0/24         0.0.0.0/0  
installed software (dietpi-software)
ID Install Name Dependencies
ID 17 =2 Git: Clone and manage Git repositories locally
ID 73 =2 Fail2Ban: prevents brute-force attacks with ip ban
ID 79 =2 LEMP: Nginx + MariaDB + PHP +Nginx +MariaDB +PHP
ID 85 =2 Nginx: Lightweight webserver
ID 88 =2 MariaDB: Persistent cached file-per-table database server
ID 89 =2 PHP: Hypertext Preprocessor for dynamic web content
ID 92 =2 Certbot: Obtain and renew Let’s Encrypt SSL certs for HTTPS
ID 93 =2 Pi-hole: block adverts for any device on your network +Git +PHP +webserver
ID 103 =2 DietPi-RAMlog: Makes /var/log a RAM disk, preserves file structure on reboot
ID 104 =2 Dropbear: Lightweight SSH server
ID 134 =2 Docker Compose: Manage multi-container Docker applications +Docker
ID 162 =2 Docker: Build, ship, and run distributed applications
ID 172 =2 WireGuard: an extremely simple yet fast and modern VPN
ID 182 =2 Unbound: validating, recursive, caching DNS resolver
ID 200 =2 DietPi-Dashboard: Official lightweight DietPi web interface (Rust)

usually this is related to Docker because Docker sets the policy for the FORWARD chain to DROP. Packet filtering and firewalls | Docker Docs

probably this helps

iptables -I DOCKER-USER -i eth0 -o wg0 -j ACCEPT
1 Like

I can confirm that the policies enabled by Docker were the culprit.
The VPN started working normally as soon as I entered the command.

Is the change going to be reverted after the next reboot/update?
Do I need to do something else in order to make it permanent?
(like adding the command to the PostUp sequence in Wireguard)

usually lost on reboot

you could try using PostUp sequence in Wireguard server configuration or iptables-persistent

1 Like

The wireguard traffic is allowed to go out of eth0, but the return traffic is dropped, because there isn’t any rule to allow the related packets or packets belonging to a connection. Like the 3rd line in the iptables -L FORWARD -v -n but without the limitation on the out interface.