I have a server lanserver
running in my private LAN that is connected to a public server publicserver
using Wireguard. publicserver
forwards TCP connections to certain ports to lanserver
through the Wireguard connection using an iptables DNAT
rule.
On lanserver
, Wireguard is set up as a NetworkManager connection. It is routing all internet traffic through Wireguard using AllowedIPs = 0.0.0.0/0, ::/0
. This causes the following ip rules to be set up on lanserver
:
[root@lanserver ~]# ip rule show
0: from all lookup local
31100: from all lookup main suppress_prefixlength 0
31101: not from all fwmark 0xcb2e lookup 52014
32766: from all lookup main
32767: from all lookup default
[root@lanserver ~]# ip route show table 52014
default dev wg0 proto static scope link metric 50
This setup works properly. An incoming TCP connection to publicserver
gets forwarded to lanserver
using the iptables rule. The response is sent back through publicserver
because the ip rule 31101
matches it.
There is one exception: When I try to open a TCP connection to publicserver
using IPv6 from my personal computer pc
, which is also inside my private LAN, it does not work. The problem seems to be that both pc
and lanserver
have an IPv6 address in the same public subnet. publicserver
forwards the connection to lanserver
successfully, but the response is not routed back through the Wireguard connection but directly to pc
due to ip rule 31100
.
How can I make sure that all responses for connections coming in through the Wireguard interface on lanserver
are also sent back through the Wireguard interface, regardless of whether their source IP is in a local subnet?
I can think of solutions in the following directions:
- Disable IPv6 on
lanserver
, causing it to not be on the same subnet aspc
. Not a very good solution. - Use
SNAT
onpublicserver
for the port forward. Not an acceptable solution, since some of the services behind the forwarded ports need to know the true source IP. - Explicitly mention the local IPv6 subnet in the
AllowedIPs
of the Wireguard peer. This does not work because the IPv6 subnet changes every 24 hours. - Add a custom IP rule that somehow matches all connections coming in through
wg0
and uses the routing table52014
for them. I'm not sure how exactly to specify such a rule. Also, the problem is that the number of the routing table changes every time the Wireguard connection is restarted. The right place to create such a rule would probably be thePostUp
script, but NetworkManager does not seem to allow specifying one.