RouterOS blatantly ignores pref-src. Can this really be a bug?

I really think I am not that dumb but this wireguard is one of the biggest headaches I have come across to date. It exceeds all the OSPF and BFD trouble.

I did what you said and I agree this is how it should work. Let me start what I did:

/interface bridge
add arp=disabled fast-forward=no name=dum1 protocol-mode=none
/ip address
add address=172.20.215.1 interface=dum1 network=172.20.215.1
/ip firewall filter
add action=accept chain=input comment=test dst-port=41820,51820 log=yes log-prefix="[***WG-IN]" protocol=udp
add action=accept chain=output log=yes log-prefix="[***WG-OUT]" port=51820,41820 protocol=udp
/ip firewall nat
add action=dst-nat chain=dstnat dst-address=192.0.2.210 dst-port=41820 log=yes log-prefix="[***WG-DNAT]" protocol=udp to-addresses=172.20.215.1 to-ports=51820



  • Created a dummy interface “dum1” with address 172.20.215.1
  • Created a DNAT rule to port forward from 192.0.2.210:41820 to 172.20.215.1:51820
  • Client now connects to 192.0.2.210:41820 which would then be “port forwarded” to internal 172.20.215.1:51820
  • I agree with you that “their corresponding response packets will get un-NAT-ed accordingly and have their source address changed to 192.0.2.210, which is what you want”
  • What RouterOS does just doesn’t make any sense whatsoever.

Here is the log output:

15:13:06 wireguard,debug wg-mobile: [miPhone] ****: Receiving handshake initiation from peer (200.95.5.88:38846) extra:0 (einval) 
15:13:06 wireguard,debug wg-mobile: [miPhone] ****: Sending handshake response to peer (200.95.5.88:38846) 
15:13:06 firewall,info [***WG-DNAT] dstnat: in:wg-bg1-ftth out:(unknown 0), connection-state:new proto UDP, 200.95.5.88:38846->192.0.2.210:41820, len 176 
15:13:06 firewall,info [***WG-IN] input: in:wg-bg1-ftth out:(unknown 0), connection-state:new,dnat proto UDP, 200.95.5.88:38846->172.20.215.1:51820, NAT 200.95.5.88:38846->(192.0.2.210:41820->172.20.215.1:51820), len 176 
15:13:06 firewall,info [***WG-OUT] output: in:(unknown 0) out:vlan2, connection-state:new proto UDP, 125.170.121.236:51820->200.95.5.88:38846, len 120

WTF? Why is the source address of the return packet now 125.170.121.236? (This is the address of vlan2!). Because of DNAT, the return packet should be 192.0.2.210, that’s the whole point of doing it and now again it picks some other random address.

Before we go into adding src-nat rules (in case they should be required) I would really like to understand what the heck is going on here. It defies any logic.

Do you have any further advice what’s wrong here and why my DNAT rule is not cutting it?

EDIT: I also added a connection mark to the incoming connection via mangle … but the output packet is still as “connection-state:new” and does not include my connection mark either! It seems connection tracking fails to be able to track this wireguard connection. If this is really the case, how on earth are you able to use DNAT for this?


EDIT2: I have never been so lost as with this ~!#$*@ wireguard. I’ve spent again hours trying any conceivable combination of DNAT+SNAT but there just doesn’t seem to be any way:

SNAT does not work because:

  • Rewriting to any other (arbitrary) SADDR/SPORT works but only 192.0.2.210:51820 does not work!
  • 192.0.2.210:51820 does NOT work because wireguard already listens on it! —> Rewritten packet is discarded and never transmitted (does not appear in packet sniffer)

DNAT does not work:

  • Response packet is not identified as part of the existing connection (see above) It’s always connection-state:new
  • Without assigning dum1 to default_myas table, the source address has the source IP of the main table (see above)
  • When assigning dum1 to default_myas, the source address is, again, 192.0.2.177

DNAT+SNAT does not work:

  • Idea: Use DNAT to move to a different port (51820–>41820)
  • DNAT 192.0.2.210:41820 —> 172.20.215.1:51820
  • SNAT 192.0.2.177:51820 —> 192.0.2.210:41820
  • And we run into the same issue as why SNAT does not work: 192.0.2.210:41820 is already taken by the DNAT

I am really going in circles and it seems everything about wireguard is buggy as crazy :frowning: :frowning: :frowning: :frowning:

Can’t be that this is literally impossible?



EDIT3: Absolutely insane. The very reason that DNAT doesn’t work is believe my original question which is because pref-src is ignored. Of course, if the source address is again 192.0.2.177, it won’t be matched as a DNAT connection which would expect 172.20.215.1. But 172.20.215.1 is never chosen because of the default route. I can confirm this by forcing a dummy routing table that only contains “0.0.0.0/0 interface=dum1”. Then the source address is properly taken as 172.20.215.1 and I can see that DNAT works. But then the packet is routed into dum1 and never arrives. It’s really circles here! I don’t think that DNAT is a solution of my question. The core is really as to WHY RouterOS ignores my request for pref-src