Trouble with Wireguard over WiFi Hotspot

I am currently trying to create a VPN access point at home, and have successfully configured Wireguard and Wifi Hotspot Mode on a Raspberry Pi running DietPi. The Raspberry Pi can access the internet when Wireguard is running but after having configured the WiFi Hotspot mode I’m having trouble connecting the clients (The Pi can still access the web after WiFi Hotspot mode is turned on). The clients can join the WiFi, but can’t browse the web. When Wireguard is turned off, the clients can browse the web. Am I doing something wrong?

Many thanks for your report. Can you specify your setup a bit:
You installed WireGuard as VPN server on the Pi? Generally when connecting via WiFi hotspot, the VPN server is not required and not used and shouldn’t have an effect on neither the Pi’s nor WiFi client’s internet access. When remote clients are connected via VPN, the WiFi hotspot shouldn’t play a role. Basically both serve different needs: WiFi hotspot for (W)LAN connections and VPN server for remote connections.

But indeed for both iptables is used to allow/set the required forward rules and probably they are conflicting, especially I think the iptables rules for the WiFi hotspot clear out those for the VPN. Can you show the following:

iptables -n -L
iptables -t nat -n -L

I’ll have a look at this in the code. Probably ordering VPN start-up after WiFi interface configuration solves it already, respectively to test quickly, restarting the VPN when the WiFi hotspot is up:

systemctl restart wg-quick@wg0

Yes basically first question is if Wireguard is used as server or client (to connect to a public VPN provider)

You installed WireGuard as VPN server on the Pi?

  • I’m using Wireguard as a VPN client on the Pi, which means that im connecting to a VPN server.

iptables -n -L returns:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

iptables -t nat -n -L returns:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
root@DietPi:~# iptables -t nat -n -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0

I’ve tried running systemctl restart wg-quick@wg0 and it didn’t fix it.

can you share following once VPN is connected

ip a; ip r

usually wg-quick@wg0 should not have any efect as this is just bringing up a server config while you are running it as client. Therefore it should be wg-quick@, if I’m not mistaken.

ip a; ip r returns:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether e4:5f:01:76:1b:cb brd ff:ff:ff:ff:ff:ff
    inet 192.168.42.1/24 brd 192.168.42.255 scope global wlan0
       valid_lft forever preferred_lft forever
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0e:c6:1c:a2:36 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.2/24 brd 192.168.0.255 scope global eth0
       valid_lft forever preferred_lft forever
8: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet 100.69.176.255/32 scope global wg0
       valid_lft forever preferred_lft forever
default via 192.168.0.1 dev eth0 onlink 
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.2 
192.168.42.0/24 dev wlan0 proto kernel scope link src 192.168.42.1

MichaIng
do you know if default routing would need to go to wg0 interface while VPN is up?

With WireGuard, routes are not directly touched, but it uses routing tables/rules to force all packets through the tunnel, different than OpenVPN does. So the default route must stay on eth0, that is correct, also in case of OpenVPN (which creates just two additional, more specific routes).

Can you show:

ip rule show

Definitely possible that the client config is /etc/wireguard/wg0.conf, the names can be freely chosen and the service instance then needs to have the name of the config file without “.conf”. The question is whether the established routing rules/tables override the WiFi/LAN hotspot routes, so that requests to LAN members are also passed through the tunnel, like a strict killswitch. Wouldn’t be smart though.

ip rule show returns:

0:	from all lookup local
32764:	from all lookup main suppress_prefixlength 0
32765:	not from all fwmark 0xca6c lookup 51820
32766:	from all lookup main
32767:	from all lookup default

Okay, so by default routes are in the “main” table, the “default” table is empty and reserved for some post-processing, the “local” table is for local/loopback and broadcast requests only. The table “51820” and the two rules with priorities 32765 and 32764 are from WireGuard, hence have higher priority than the main rule. While ip r shows only the “main” table routes, you can list other routes via ip r l table , so you can review the WireGuard routes via:

ip r l table 51820

With higher priority than the main rule, packets without the firewall mark “0xca6c” are routed using the WireGuard routing table, I guess hence WireGuard sets this mark for packets itself sends to the VPN server, which must to through eth0 directly. We could add this mark for defined requests (i.e. those to then wlan0 interface) to assure they are not tunnelled through the VPN. The other higher priority rule applies the “main” table again but with some condition I don’t understand…

… okay here it is: https://stackoverflow.com/a/68988919/16145737
So the “32764” priority rule assures that the “main” table is applied for all requests which would hit anything else than the default route, which actually implies all LAN/WLAN requests, including those to any 192.168.42.X IP, where the 192.168.42.0/24 route applies which has a prefix length of 24, not affected by “suppress_prefixlength 0”. Ah “0xca6c” is hexadecimal for “51820”, matching the routing table name, now I’m interested what this number means to WireGuard :smiley:.

Okay, so LAN and WiFi connections are not affected by WireGuard, that is good. Now I have an idea what the issue could be. Can you please show:

cat /etc/iptables.ipv4.nat

Forwarding/NAT rules are applied for wlan0 <> eth0 but need to be applied for wlan0 <> wg0 as well.

cat /etc/iptables.ipv4.nat returns:

# Generated by iptables-save v1.8.7 on Tue Jan 18 12:53:09 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i wlan0 -o eth0 -j ACCEPT
COMMIT
# Completed on Tue Jan 18 12:53:09 2022
# Generated by iptables-save v1.8.7 on Tue Jan 18 12:53:09 2022
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
# Completed on Tue Jan 18 12:53:09 2022

Please try like that:

cat << '_EOF_' > /etc/iptables.ipv4.nat
# Generated by iptables-save v1.8.7 on Tue Jan 18 12:53:09 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i wlan0 -o eth0 -j ACCEPT
-A FORWARD -i wg0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i wlan0 -o wg0 -j ACCEPT
COMMIT
# Completed on Tue Jan 18 12:53:09 2022
# Generated by iptables-save v1.8.7 on Tue Jan 18 12:53:09 2022
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o eth0 -j MASQUERADE
-A POSTROUTING -o wg0 -j MASQUERADE
COMMIT
# Completed on Tue Jan 18 12:53:09 2022
_EOF_
iptables-restore < /etc/iptables.ipv4.nat