Routing all traffic through a wireguard interface

Hello,

Several users have recently asked how to route all traffic through a wireguard interface, just setting Allowed IPs to 0.0.0.0/0 + ::/0 (or similar with /1 masks) is doomed to fail because there must be an exception at least for the IP address of the wg server.
A workaround is to play with the metric of a static route to the server, it works but must be actively maintained if the IP address changes.

Here is a much cleaner solution, it is derived from the wg-quick utility.

As the UI doesn’t provide for PostUp and PreDown scripts, the method uses mwan3 in order to act on ifup and ifdown events.

First declare the wg interface in /etc/config/mwan3, like below. Set the name and table value to suit your needs:

config interface 'wgxxx'
        option family 'ipv4'
        option interval '60'
        list flush_conntrack 'connected'
        list flush_conntrack 'disconnected'
        option enabled '1'

then add the following code to /etc/mwan3.user:

table=51820
wgname="wgxxx"

[ x"$ACTION" = x"ifup" ] && [ x"$INTERFACE" = x"$wgname" ] && {
        logger -t "mwan3.user[$$]" -p notice " add rules/routes $ACTION interface $INTERFACE device $DEVICE"
        wg set $INTERFACE fwmark $table                                                                     
        ip -4 route add default dev $INTERFACE table $table                                                 
        if [ $(ip -4 rule show 2>/dev/null | grep -c "lookup $table") -eq 0 ]; then                         
                ip -4 rule add not fwmark $table table $table                                               
        fi                                                                                                  
        if [ $(ip -4 rule show 2>/dev/null | grep -c "from all lookup main suppress_prefixlength 0") -eq 0 ]; then
                ip -4 rule add table main suppress_prefixlength 0                                                 
        fi                                                                                                        
        ip -6 route add default dev $INTERFACE table $table                                                       
        if [ $(ip -6 rule show 2>/dev/null | grep -c "lookup $table") -eq 0 ]; then                               
                ip -6 rule add not fwmark $table table $table                                                     
        fi                                                                                                        
        if [ $(ip -6 rule show 2>/dev/null | grep -c "from all lookup main suppress_prefixlength 0") -eq 0 ]; then
                ip -6 rule add table main suppress_prefixlength 0                                                 
        fi                                                                                                        
}

[ x"$ACTION" = x"ifdown" ] && [ x"$INTERFACE" = x"$wgname" ] && {
        logger -t "mwan3.user[$$]" -p notice " delete rules/routes $ACTION interface $INTERFACE device $DEVICE"
        while [ $(ip -4 rule show 2>/dev/null | grep -c "lookup $table") -gt 0 ]; do                              
                ip -4 rule delete table $table                                                                    
        done                                                                                                      
        while [ $(ip -4 rule show 2>/dev/null | grep -c "from all lookup main suppress_prefixlength 0") -gt 0 ]; do
                ip -4 rule delete table main suppress_prefixlength 0                                              
        done                                                                                                      
        while [ $(ip -6 rule show 2>/dev/null | grep -c "lookup $table") -gt 0 ]; do                               
                ip -6 rule delete table $table                                                                    
        done                                                                                                      
        while [ $(ip -6 rule show 2>/dev/null | grep -c "from all lookup main suppress_prefixlength 0") -gt 0 ]; do
                ip -6 rule delete table main suppress_prefixlength 0                                              
        done                                                                                                      
}

Allowed IPs must be set to

0.0.0.0/1 + 128.0.0.0/1 + ::/1 + 8000::/1

At the end, restart mwan3:

/etc/init.d/mwan3 restart

and add wireguard_watchdog to cron:

echo '* * * * * /usr/bin/wireguard_watchdog' >> /etc/crontabs/root
/etc/init.d/cron restart

Local traffic (DHCP, DHCPv6, router sollicitation and so on) is still processed normally.

@Talleyrand: could you test this ?

Regards,

1 Like

Thank you flebourse,

I did a factory reset to clear out the router, then recreated the wg interface and peer with info from my VPN provider and edited/restarted as per your instructions. The one thing I changed was substituting the table number suggested by you with another which matched the port my VPN provider wants me to use (the number you used seemed to match a standard port number for wg VPNs).

The effect was no internet and no handshake of wg. After a factory reset and recreation of the wg interface I am back to having internet and handshake, but no routing through the established tunnel.

Will redo later today to make sure there were no typos or other mistakes but prognosis is not good. I tried to be careful the first time. If any of the steps could be misunderstood by a novice let me know. I used the vi command system to enter the new text in the mwan files via the CLI interface in the web UI.

Did you change the “wgname” variable ?
I have the following output for the wg command:

root@lgrrutx:~# wg
interface: wgtls
  public key: (hidden)
  private key: (hidden)
  listening port: 36329

peer: (hidden)
  preshared key: (hidden)
  endpoint: x.y.z.t:51820
  allowed ips: 0.0.0.0/1, 128.0.0.0/1, ::/1, 8000::/1
  latest handshake: 14 seconds ago
  transfer: 2.15 GiB received, 223.51 MiB sent
  persistent keepalive: every 25 seconds

Could you show the output of:

ip -4 rule show
ip -6 rule show

and

ip -4 route show
ip -6 route show

Idem for the output of wg ?

I changed the wgname to the exact name of my wg interface. Will redo in a second and post the output.

The name of the interface is used in /etc/mwan3.user and /etc/config/mwan3.
Have you set both correctly ?

I think I did. But I have reset the router and am now re-entering the edits to make sure. Will post outputs as soon as I’m done.

Apologies for the wall of text, but here we go.

With the tunnel installed and no edits I have internet and a tunnel handshake but the traffic does not go through the tunnel.

Wg output in this case:

root@RUTX10:~# wg
interface: Residwg
public key: (EDITED)
private key: (hidden)
listening port: 48574

peer: (EDITED)
endpoint: (EDITED, format is 1.2.3.4):48574
allowed ips: 0.0.0.0/0
latest handshake: 1 minute, 20 seconds ago
transfer: 8.98 KiB received, 33.14 KiB sent
persistent keepalive: every 25 seconds

Ip rule output in this case:

root@RUTX10:~# ip -4 rule show
0: from all lookup local
32766: from all lookup main
32767: from all lookup default

root@RUTX10:~# ip -6 rule show
0: from all lookup local
32766: from all lookup main
4200000001: from all iif lo failed_policy
4200000003: from all iif eth1 failed_policy
4200000013: from all iif br-lan failed_policy
4200000024: from all iif Residwg failed_policy

Ip route output in this case:

root@RUTX10:~# ip -4 route show
default via 192.168.1.1 dev eth1 proto static src 192.168.1.3 metric 2
10.0.138.0/24 dev Residwg proto kernel scope link src 10.0.138.123
192.168.1.0/24 dev br-lan proto static scope link metric 1
192.168.1.0/24 dev eth1 proto static scope link metric 2

root@RUTX10:~# ip -6 route show
fdd2:d0fe:b3c6::/64 dev br-lan proto static metric 1 pref medium
unreachable fdd2:d0fe:b3c6::/48 dev lo proto static metric 2147483647 pref medium
fe80::/64 dev br-lan proto kernel metric 256 pref medium
fe80::/64 dev eth1 proto kernel metric 256 pref medium

After edits there is no internet through the router regardless of whether tunnel is turned on or off. Windows still indicates a connection (Edit: after a while it catches up and says no connection) but when trying to access any web page it will first say that it can’t find the DNS, then that I am not connected.

Wg output efter edits:

root@RUTX10:~# wg
interface: Residwg

(The first time I did it I got a listening port as well, 33342 which is not the one the tunnel should be using. After that just the above)

Ip rule output after edits:

root@RUTX10:~# ip -4 rule show
0: from all lookup local
2061: from all fwmark 0x3d00/0x3f00 blackhole
2062: from all fwmark 0x3e00/0x3f00 unreachable
32766: from all lookup main
32767: from all lookup default

root@RUTX10:~# ip -6 rule show
0: from all lookup local
2061: from all fwmark 0x3d00/0x3f00 blackhole
2062: from all fwmark 0x3e00/0x3f00 unreachable
32764: not from all fwmark 0xbdbe lookup 48574
32765: not from all fwmark 0xbdbe lookup 48574
32766: from all lookup main
4200000001: from all iif lo failed_policy
4200000003: from all iif eth1 failed_policy
4200000013: from all iif br-lan failed_policy

IP route output after edits:

root@RUTX10:~# ip -4 route show
default via 192.168.1.1 dev eth1 proto static src 192.168.1.3 metric 2
192.168.1.0/24 dev br-lan proto static scope link metric 1
192.168.1.0/24 dev eth1 proto static scope link metric 2

root@RUTX10:~# ip -6 route show
fdd2:d0fe:b3c6::/64 dev br-lan proto static metric 1 pref medium
unreachable fdd2:d0fe:b3c6::/48 dev lo proto static metric 2147483647 pref medium
fe80::/64 dev br-lan proto kernel metric 256 pref medium
fe80::/64 dev eth1 proto kernel metric 256 pref medium

Allowed IPs should be 0.0.0.0/1 + 128.0.0.0/1 + ::/1 + 8000::/1 not 0.0.0.0/0
The ip -4 rule show output should contain rules similar to:

1001:	from all lookup main suppress_prefixlength 0
1002:	not from all fwmark 0xca6c lookup 51820

You may have different rules numbers. Idem for ip -4 route show:

0.0.0.0/1 dev wgtls proto static scope link metric 8 
default via 10.5.200.1 dev wlan1 proto static src 10.5.200.102 metric 4 
10.5.200.0/23 dev wlan1 proto static scope link metric 4 
ip-of-the-wg-server via 10.5.200.1 dev wlan1 metric 4 

So it seems that the code in /etc/mwan3.user has not been executed.

Could you show the relevant section of /etc/config/mwan3 (do a cut and paste I want to see the indentation) ?

Allowed IPs: the 0.0.0.0/0 is from just having the tunnel, before applying the fixes. I have used 0.0.0.0/1 + 128.0.0.0/1 there as well before with no detectable change in functionality.

Here is what I have post-editing in terms of allowed IPs:

image

Here is the section of /etc/config/mwan3 I added, together with a bit of what was there for reference:

…and here is the /etc/mwan3.user

(sorry, here is the table/wgname bit as well, missed that above:)

  1. Regarding the cron file - are both lines supposed to be added?

I took the first to be the addition, the second to be a command line for restart which I executed without error messages.

  1. I left a long list of #-lines in the /etc/mwan3.user file above my addition, is that a problem?

Apologies for asking/possibly doing dumb things. But your help is much appreciated.

Hummm.
Maybe you can add logs to /etc/mwan3.user to see what is going on:
In the ifup section:

        logger -t "mwan3.user[$$]" -p notice " add rules/routes $ACTION interface $INTERFACE device $DEVICE"

and in the ifdown section:

        logger -t "mwan3.user[$$]" -p notice " delete rules/routes $ACTION interface $INTERFACE device $DEVICE"

The logs can be read with logread -f, or send them to a remote syslog.

I have never used interface names with capital letters, could you try with residwg not Residwg ?

The /etc/init.d/cron restart is just a command to restart cron after the addition of the wireguard_watchdog line.
Did you restart mwan3 after modifying /etc/config/mwan3 ?
=> /etc/init.d/mwan3 restart

I left a long list of #-lines in the /etc/mwan3.user file above my addition, is that a problem?

No.

Capital letters purged from the interface name (by erasing and recreating the interface since you may not change the name once it’s established). Both config and user mwan files also adjusted. Logger lines added. Mwan restarted for good measure. (It was restarted before as well, that was clear in your instruction)

Do you have something interesting in the logs ?

Logread -f gives me a running list of attempts to do the handshake (I assume).
Most look like this:

Sat Nov 4 20:01:02 2023 daemon.notice netifd: residwg (13300): Try again: `wireguard.5july.net:48574’. Trying again in 6.19 seconds…

Here are some lines which seem to contain error messages:

Sat Nov 4 19:58:00 2023 cron.err crond[8138]: USER root pid 13033 cmd /usr/bin/wireguard_watchdog

Sat Nov 4 19:59:36 2023 daemon.notice netifd: residwg (12601): Configuration parsing error
Sat Nov 4 19:59:41 2023 daemon.notice netifd: residwg (13288): grep: /tmp/wireguard/default-status: No such file or directory

root@lgrrutx:~# kdig +noall +answer wireguard.5july.net
wireguard.5july.net.	30	IN	A	98.128.186.116
wireguard.5july.net.	30	IN	A	176.10.248.203

The tunnel isn’t established because the name resolution fails. Could you re-check the value you have entered in the endpoint host field. Check it also in /etc/config/network, to be sure (there must not be any https:// in it).
There is no need to destroy an interface in order to change the name, just modify it in /etc/config/network.

Interesting. In the vanilla setup before editing I use the www address from the setup files provided and it’s fine. Changed to one of the addresses indicated and now I get some sort of empty handshake with 148 bytes sent 0 received from the wg command.

This keeps coming back in logread:

Sat Nov 4 20:25:00 2023 cron.err crond[8138]: USER root pid 22471 cmd /usr/bin/wireguard_watchdog

…ah. Thank you. So far I’ve managed to do all I need in the web interfaces of my routers so I’m a complete newbie to fiddling with the files directly.