Strange firewall dnat rule to make WireGuard work on dual-interface server

Simone Rossetto simros85 at gmail.com
Sun Sep 1 10:27:56 CEST 2019


Hello all, I have a routing problem on my server regarding WireGuard
incoming connections and I managed to solve it using strange (at least for
me) iptables rules.

This is the setup: one server with two interfaces (eth0 with IP 192.168.0.1
and eth1 with IP 192.168.1.1), both of them connected to an external router
so both of them can be used to reach internet. The default route is through
eth1 except for some connections that need to pass through eth0. I
accomplished this behavior with a new routing table and fwmark on packets
as follow:

    # new routing table to eth0
    ip rule add fwmark 11 table adsl
    ip route add default via 192.168.0.1 dev eth0 table adsl

    # set mark 11 on incoming packets from eth0 and for some outgoing
packets
    iptables -t mangle -A PREROUTING -m conntrack --ctstate
RELATED,ESTABLISHED -j CONNMARK --restore-mark
    iptables -t mangle -A INPUT -i eth0 -m conntrack --ctstate NEW -j MARK
--set-xmark 11
    iptables -t mangle -A INPUT -m conntrack --ctstate NEW -j CONNMARK
--save-mark
    iptables -t mangle -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED
-j CONNMARK --restore-mark
    iptables -t mangle -A OUTPUT [...] --ctstate NEW -j MARK --set-xmark 11
    iptables -t mangle -A POSTROUTING -m conntrack --ctstate NEW -j
CONNMARK --save-mark

    # change source IP for new connections that need to bo routed to eth0
    iptables -t nat -A POSTROUTING -s 192.168.1.1/32 -m conntrack --ctstate
NEW -m mark --mark 11 -j SNAT --to-source 192.168.0.1

This works well for any other connection but not for WireGuard incoming
connections. If I cat the connection tracking I get two "unreplied"
connections instead of a successful one

    cat /proc/net/nf_conntrack | grep 44
    ipv4     2 udp      17 26 src=192.168.1.1 dst=37.160.28.111 sport=44
dport=1503 [UNREPLIED] src=37.160.28.111 dst=192.168.0.1 sport=1503
dport=1024 mark=11 zone=0 use=2
    ipv4     2 udp      17 26 src=37.160.28.111 dst=192.168.0.1 sport=1503
dport=44 [UNREPLIED] src=192.168.0.1 dst=37.160.28.111 sport=44 dport=1503
mark=11 zone=0 use=2

where 44 is the UDP WireGuard port.
The first line seams an outgoing connection from 192.168.1.1 (eth1) to an
external IP that waits for a reply on IP 192.168.0.1 (why different??) and
port 1024 (?! where does it come from??), the second line is the real
incoming connection from outside to port 44. The incoming connection is
correctly marked with mark 11, as the outgoing "reply", but not a working
"reply".

To make WireGuard work I need to add the following iptables pre-routing rule

    iptables -t nat -A PREROUTING -d 192.168.0.1/32 -p udp -m udp --dport
44 -m conntrack --ctstate NEW -j DNAT --to-destination 192.168.1.1

that is change the destination address of new WireGuard connections from
192.168.0.1 (eth0, where they actually come from) to 192.168.1.1 (eth1)
where they should not transit. Adding this rule the connection tracking is
as follow:

    cat /proc/net/nf_conntrack | grep 44
    ipv4     2 udp      17 167 src=37.160.28.111 dst=192.168.0.1 sport=1503
dport=44 src=192.168.0.1 dst=37.160.28.111 sport=44 dport=1503 [ASSURED]
mark=11 zone=0 use=2

a single established connection to IP 192.168.0.1 even I set a dnat to
192.168.1.1.

Is there a reason for this behavior or could it be a bug in WireGuard?
Or, perhaps, I set something odd and the dnat is a workaround?


Thanks, bye
Simone
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.zx2c4.com/pipermail/wireguard/attachments/20190901/ac368cd3/attachment-0001.html>


More information about the WireGuard mailing list