Per request, I am starting with a network diagram:
RouterOS runs a wireguard "server" for a road warrior setup. Sadly it's not possible to "bind" wireguard to specific interfaces, so they "listen" on any IP address. The road warrior uses 192.0.2.210:52810 as an endpoint. Now every reasonable person would expect that the response packet from such a request would have source address 192.0.2.210. Sadly RouterOS is always up for surprises and that's not the case. I assume due to an obscure implementation of wireguard, the source address is left unset and hence the operating system needs to decide what should be the source address for the locally generated packet. For me this is 192.0.2.177. Now you can imagine already that this breaks everything: The road warrier client requested a connection to 192.0.2.210 but gets a response from 192.0.2.177. It thinks this is MIM and discards the packet.
Now there is "pref-src" is exactly for this: It should determine the source address of a locally generated packet based on the route that is chosen. In my case the route comes from BGP and I could add a router filter to add pref-src. But for simplicity (and because it didn't work), I explicitly add a static route with low distance and pref-src set to 192.0.2.210:
/ip/route/add dst-address=0.0.0.0/0 routing-table=default_myas pref-src=192.0.2.210 gateway=192.0.2.176 distance=1
/ip/route/print detail where routing-table=default_myas
Flags: D - dynamic; X - disabled, I - inactive, A - active; c - connect, s - static, r - rip, b - bgp, o - ospf, i - is-is, d - dhcp, v - vpn, m - modem, y - bgp-mpls-vpn; H - hw-offloaded; + - ecmp
D b dst-address=0.0.0.0/0 routing-table=default_myas gateway=172.20.215.129 immediate-gw=192.0.2.185%wg-bg1-ftth distance=200 scope=40 target-scope=30 suppress-hw-offload=no
D b dst-address=0.0.0.0/0 routing-table=default_myas gateway=172.20.215.130 immediate-gw=192.0.2.176%wg-bg2-ftth distance=200 scope=40 target-scope=30 suppress-hw-offload=no
1 As dst-address=0.0.0.0/0 routing-table=default_myas pref-src=192.0.2.210 gateway=192.0.2.176 immediate-gw=192.0.2.176%wg-bg2-ftth distance=1 scope=30 target-scope=10 suppress-hw-offload=no
/tool/sniffer/export
# 2024-11-27 16:24:00 by RouterOS 7.15.3
# software id =
#
/tool sniffer
set filter-ip-protocol=udp filter-port=51820
/tool/sniffer/packet/print detail
18 time=59.738 num=19 direction=rx interface=wg-bg1-ftth src-address=*.*.5.88:63419 dst-address=192.0.2.210:51820 protocol=ip ip-protocol=udp size=176 cpu=2 ip-packet-size=176 ip-header-size=20 dscp=0
identification=64534 fragment-offset=0 ttl=49
19 time=59.738 num=20 direction=tx interface=wg-bg2-ftth src-address=192.0.2.177:51820 dst-address=*.*.5.88:63419 protocol=ip ip-protocol=udp size=120 cpu=1 ip-packet-size=120 ip-header-size=20 dscp=34
identification=32146 fragment-offset=0 ttl=64
You can see here, the request to 192.0.2.210:51820 enters via wg-bg1-ftth and the response (through perfectly valid interface wg-bg2-ftth) is sent with source 192.0.2.177:51820, despite explicitly asking RouterOS to use 192.0.2.210 via the pre-src in the default route.
While I don't think it's necessary, I re-post my entire config below.
Can anyone confirm that I am not totally crazy and this is a stupid bug in RouterOS?
If not, what the heck is wrong with this config?
# 2024-11-25 10:54:47 by RouterOS 7.15.3
# software id =
#
/interface bridge
add name=br-main vlan-filtering=yes
add arp=disabled fast-forward=no name=dum0 protocol-mode=none
/interface ethernet
set [ find default-name=ether1 ] disable-running-check=no
/interface wireguard
add listen-port=13231 mtu=1420 name=wg-bg1-ftth
add listen-port=13232 mtu=1420 name=wg-bg2-ftth
add listen-port=51820 mtu=1420 name=wg-mobile
/interface vlan
add comment=ADM interface=br-main name=vlan1 vlan-id=1
add comment=FTTH interface=br-main name=vlan2 vlan-id=2
add comment=LAN interface=br-main name=vlan3 vlan-id=3
add comment=SRV interface=br-main name=vlan4 vlan-id=4
add comment=ADU interface=br-main name=vlan10 vlan-id=10
add comment=DEV interface=br-main name=vlan11 vlan-id=11
add comment=DEVP interface=br-main name=vlan12 vlan-id=12
add comment=DMZ44 interface=br-main name=vlan44 vlan-id=44
/interface vrrp
add interface=vlan1 name=vrrp1
add interface=vlan3 name=vrrp3 sync-connection-tracking=yes vrid=3
add interface=vlan4 name=vrrp4 vrid=4
add interface=vlan11 name=vrrp11 vrid=11
add interface=vlan12 name=vrrp12 vrid=12
add interface=vlan44 name=vrrp44 vrid=44
/interface list
add name=LAN
add comment="Admin Interfaces" name=ADM
add name=DMZ
add name=SRV
add name=DEV
add name=DEVP
add name=WAN
add include=ADM,DEV,DEVP,DMZ,LAN,SRV name=trusted
add name=peers
add name=WANMYAS
add name=ISP
add name=MACHINES
/routing ospf instance
add disabled=no name=ospf-instance-1 redistribute=static router-id=192.0.2.210
/routing ospf area
add disabled=no instance=ospf-instance-1 name=ospf-area-1
/routing table
add disabled=no fib name=default_myas
add disabled=no fib name=default_isp
add comment="Dummy table, acts only as a routing mark" disabled=no fib name=default_isp_only
/interface bridge port
add bridge=br-main interface=ether1
add bridge=br-main interface=veth1 pvid=3
/ip firewall connection tracking
set enabled=yes
/ip neighbor discovery-settings
set discover-interface-list=none lldp-med-net-policy-vlan=1
/interface bridge vlan
add bridge=br-main tagged=br-main,ether1 vlan-ids=2
add bridge=br-main tagged=br-main,ether1 vlan-ids=3
add bridge=br-main tagged=br-main,ether1 vlan-ids=4
add bridge=br-main tagged=br-main,ether1 vlan-ids=10
add bridge=br-main tagged=br-main,ether1 vlan-ids=11
add bridge=br-main tagged=br-main,ether1 vlan-ids=12
add bridge=br-main tagged=br-main,ether1 vlan-ids=44
add bridge=br-main tagged=br-main untagged=ether1 vlan-ids=1
add bridge=br-main tagged=br-main,ether1 vlan-ids=33
/interface detect-internet
set internet-interface-list=static lan-interface-list=static wan-interface-list=static
/interface list member
add interface=vlan3 list=LAN
add interface=vlan1 list=ADM
add interface=vlan2 list=WAN
add interface=vlan44 list=DMZ
add interface=wg-bg1-ftth list=WAN
add interface=wg-bg2-ftth list=WAN
add interface=vrrp3 list=LAN
add interface=vlan4 list=SRV
add interface=wg-bg1-ftth list=peers
add interface=wg-bg2-ftth list=peers
add interface=vlan11 list=DEV
add interface=vlan12 list=DEVP
add interface=wg-bg1-ftth list=WANMYAS
add interface=wg-bg2-ftth list=WANMYAS
add interface=vlan2 list=ISP
add interface=vlan33 list=ISP
add interface=vlan11 list=MACHINES
add interface=vlan12 list=MACHINES
add interface=vrrp44 list=DMZ
add interface=vrrp1 list=ADM
add interface=vrrp12 list=DEVP
add interface=vrrp4 list=SRV
add interface=vrrp11 list=DEV
add interface=vrrp11 list=MACHINES
add interface=vrrp12 list=MACHINES
/interface wireguard peers
add allowed-address=0.0.0.0/0,::/0 endpoint-address=*.*.*.* endpoint-port=51821 interface=wg-bg2-ftth name=bgate2-ftth persistent-keepalive=5s public-key=“********************************************”
add allowed-address=0.0.0.0/0,::/0 endpoint-address=*.*.*.* endpoint-port=51821 interface=wg-bg1-ftth name=bgate1-ftth persistent-keepalive=5s public-key=“********************************************”
add allowed-address=10.2.33.10/32 client-address=10.2.33.10/32 interface=wg-mobile name=miPhone public-key=“********************************************”
/ip address
add address=10.2.1.2/24 interface=vlan1 network=10.2.1.0
add address=10.2.4.2/24 interface=vlan4 network=10.2.4.0
add address=10.2.79.2/24 interface=vlan3 network=10.2.79.0
add address=192.0.2.177/31 interface=wg-bg2-ftth network=192.0.2.176
add address=192.0.2.186/29 interface=wg-bg1-ftth network=192.0.2.184
add address=192.0.2.210/28 interface=vlan44 network=192.0.2.208
add address=172.20.215.132 interface=dum0 network=172.20.215.132
add address=10.2.80.2/24 interface=vlan10 network=10.2.80.0
add address=192.168.222.2/24 interface=vlan11 network=192.168.222.0
add address=192.168.223.2/24 interface=vlan12 network=192.168.223.0
add address=10.2.79.254 interface=vrrp3 network=10.2.79.254
add address=10.2.33.1/24 interface=wg-mobile network=10.2.33.0
add address=192.168.223.254 interface=vrrp12 network=192.168.223.254
add address=192.168.222.254 interface=vrrp11 network=192.168.222.254
add address=10.2.1.254 interface=vrrp1 network=10.2.1.254
add address=10.2.4.254 interface=vrrp4 network=10.2.4.254
add address=192.168.5.102/24 interface=vlan33 network=192.168.5.0
add address=192.0.2.222 interface=vrrp44 network=192.0.2.222
/ip dhcp-client
add add-default-route=no interface=vlan2 script=":if (\$bound=1) do={\
\n /ip route set [find where comment=\"default_isp\"] gateway=\$\"gateway-address\" disabled=no\
\n } else={\
\n /ip route set [find where comment=\"default_isp\"] disabled=yes\
\n }\r\
\n\r\
\n" use-peer-ntp=no
/ip firewall address-list
add address=10.2.0.0/16 list=own_hosts
add address=192.0.2.0/24 list=own_hosts
add address=*.*.*.* list=border_gates
add address=*.*.*.* list=border_gates
add address=*.*.*.* list=own_hosts
add address=*.*.*.* list=own_hosts
add address=192.168.222.0/24 list=own_hosts
add address=192.168.223.0/24 list=own_hosts
add address=172.20.215.128/27 list=own_hosts
add address=0.0.0.0/8 comment="defconf: RFC6890" list=no_forward_ipv4
add address=169.254.0.0/16 comment="defconf: RFC6890" list=no_forward_ipv4
add address=224.0.0.0/4 comment="defconf: multicast" list=no_forward_ipv4
add address=255.255.255.255 comment="defconf: RFC6890" list=no_forward_ipv4
add address=127.0.0.0/8 comment="defconf: RFC6890" list=bad_ipv4
add address=192.0.0.0/24 comment="defconf: RFC6890" list=bad_ipv4
add address=192.0.2.0/24 comment="defconf: RFC6890 documentation" list=bad_ipv4
add address=198.51.100.0/24 comment="defconf: RFC6890 documentation" list=bad_ipv4
add address=203.0.113.0/24 comment="defconf: RFC6890 documentation" list=bad_ipv4
add address=240.0.0.0/4 comment="defconf: RFC6890 reserved" list=bad_ipv4
add address=0.0.0.0/8 comment="defconf: RFC6890" list=not_global_ipv4
add address=10.0.0.0/8 comment="defconf: RFC6890" list=not_global_ipv4
add address=100.64.0.0/10 comment="defconf: RFC6890" list=not_global_ipv4
add address=169.254.0.0/16 comment="defconf: RFC6890" list=not_global_ipv4
add address=172.16.0.0/12 comment="defconf: RFC6890" list=not_global_ipv4
add address=192.0.0.0/29 comment="defconf: RFC6890" list=not_global_ipv4
add address=192.168.0.0/16 comment="defconf: RFC6890" list=not_global_ipv4
add address=198.18.0.0/15 comment="defconf: RFC6890 benchmark" list=not_global_ipv4
add address=255.255.255.255 comment="defconf: RFC6890" list=not_global_ipv4
add address=224.0.0.0/4 comment="defconf: multicast" list=bad_src_ipv4
add address=255.255.255.255 comment="defconf: RFC6890" list=bad_src_ipv4
add address=0.0.0.0/8 comment="defconf: RFC6890" list=bad_dst_ipv4
add address=224.0.0.0/4 comment="defconf: RFC6890" list=bad_dst_ipv4
add address=10.2.0.0/16 list=private_lans
add address=192.168.0.0/16 list=private_lans
add address=172.20.215.128/27 list=border_gates
add address=10.2.4.10 list=hairpin_dst
add address=10.2.4.20 list=hairpin_dst
add address=10.2.0.0/16 list=hairpin_src
add address=192.168.222.0/24 list=hairpin_src
add address=192.168.223.0/24 list=hairpin_src
/ip firewall filter
add action=accept chain=input comment="defconf: accept ICMP after RAW" protocol=icmp
add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untracked
add action=accept chain=input comment="SSH access from everywhere" dst-port=1983 protocol=tcp
add action=accept chain=input comment=Wireguard dst-port=51820 protocol=udp
add action=accept chain=input dst-port=8291 protocol=tcp src-address-list=private_lans
add action=accept chain=input dst-port=3784,4784,3785 in-interface-list=peers protocol=udp src-address-list=own_hosts
add action=accept chain=input in-interface-list=peers protocol=ospf
add action=accept chain=input dst-port=179 in-interface-list=peers protocol=tcp src-address-list=own_hosts
add action=accept chain=input dst-port=53 protocol=udp src-address-list=own_hosts
add action=accept chain=input dst-port=53 protocol=tcp src-address-list=own_hosts
add action=drop chain=input comment="defconf: drop all not coming from trusted" in-interface-list=!trusted
add action=accept chain=forward comment="PortFW: For some reason, Fasttrack doesn't work for these." connection-mark=conn_portfw connection-state=established,related
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" connection-state=established,related hw-offload=yes
add action=accept chain=forward comment="defconf: accept established,related, untracked" connection-state=established,related,untracked
add action=jump chain=forward comment="Traffic rules for new connections" connection-state=new jump-target=traffic_rules
add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid log=yes log-prefix=INVALID
add action=drop chain=forward comment="defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat connection-state=new in-interface-list=WAN
add action=drop chain=forward comment="defconf: drop bad forward IPs" src-address-list=no_forward_ipv4
add action=drop chain=forward comment="defconf: drop bad forward IPs" dst-address-list=no_forward_ipv4
add action=accept chain=forward comment="Check if counters >0. If not, DROP here" log=yes log-prefix="[ACPT]"
add action=accept chain=traffic_rules comment="Allow all ICMP echo" icmp-options=8:0-255 protocol=icmp
add action=accept chain=traffic_rules comment="Allow from ISPs only when DNAT" connection-nat-state=dstnat in-interface-list=ISP
add action=accept chain=traffic_rules comment="Allow internet for public 44" in-interface-list=DMZ out-interface-list=WANMYAS
add action=log chain=traffic_rules comment="Log drops (not wan)" in-interface-list=!WANMYAS log=yes log-prefix="[BLOCKED]" out-interface-list=!WANMYAS src-address=!192.168.222.150
add action=drop chain=traffic_rules
/ip firewall mangle
add action=mark-routing chain=output comment="wg-tunnels: bgate1 over FTTH" dst-address=*.*.*.* dst-port=51821 new-routing-mark=default_isp_only passthrough=no protocol=udp
add action=mark-routing chain=output comment="wg-tunnels: bgate2 over FTTH" dst-address=*.*.*.* dst-port=51821 new-routing-mark=default_isp_only passthrough=no protocol=udp
/ip firewall nat
add action=masquerade chain=srcnat comment="wg-tunnels: FTTH" routing-mark=default_isp_only
add action=masquerade chain=srcnat comment="Hairpin all PortFWs" dst-address-list=hairpin_dst src-address-list=hairpin_src
add action=masquerade chain=srcnat comment="defconf: masquerade WAN interface" out-interface=vlan2
/ip firewall raw
add action=accept chain=prerouting comment="defconf: enable for transparent firewall"
add action=accept chain=prerouting comment="defconf: accept DHCP discover" dst-address=255.255.255.255 dst-port=67 in-interface-list=LAN protocol=udp src-address=0.0.0.0 src-port=68
add action=drop chain=prerouting comment="defconf: drop bogon IP's" src-address-list=bad_ipv4
add action=drop chain=prerouting comment="defconf: drop bogon IP's" dst-address-list=bad_ipv4
add action=drop chain=prerouting comment="defconf: drop bogon IP's" src-address-list=bad_src_ipv4
add action=drop chain=prerouting comment="defconf: drop bogon IP's" dst-address-list=bad_dst_ipv4
add action=drop chain=prerouting comment="defconf: drop non global from WAN" in-interface-list=WAN src-address-list=not_global_ipv4
add action=drop chain=prerouting comment="defconf: drop forward to local lan from WAN" dst-address-list=private_lans in-interface-list=WAN
add action=drop chain=prerouting comment="defconf: drop local if not from default IP range" in-interface-list=LAN src-address=!10.2.79.0/24
add action=drop chain=prerouting in-interface-list=DEV src-address=!192.168.222.0/24
add action=drop chain=prerouting in-interface-list=DEVP src-address=!192.168.223.0/24
add action=drop chain=prerouting comment="defconf: drop bad UDP" port=0 protocol=udp
add action=jump chain=prerouting comment="defconf: jump to ICMP chain" jump-target=icmp4 protocol=icmp
add action=jump chain=prerouting comment="defconf: jump to TCP chain" jump-target=bad_tcp protocol=tcp
add action=accept chain=prerouting comment="defconf: accept everything else from LAN" in-interface-list=trusted
add action=accept chain=prerouting comment="defconf: accept everything else from WAN" in-interface-list=WAN
add action=drop chain=prerouting comment="defconf: drop the rest"
add action=drop chain=bad_tcp comment="defconf: TCP flag filter" protocol=tcp tcp-flags=!fin,!syn,!rst,!ack
add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,syn
add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,rst
add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,!ack
add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,urg
add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=syn,rst
add action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=rst,urg
add action=drop chain=bad_tcp comment="defconf: TCP port 0 drop" port=0 protocol=tcp
add action=accept chain=icmp4 comment="defconf: echo reply" icmp-options=0:0 limit=5,10:packet protocol=icmp
add action=accept chain=icmp4 comment="defconf: net unreachable" icmp-options=3:0 protocol=icmp
add action=accept chain=icmp4 comment="defconf: host unreachable" icmp-options=3:1 protocol=icmp
add action=accept chain=icmp4 comment="defconf: protocol unreachable" icmp-options=3:2 protocol=icmp
add action=accept chain=icmp4 comment="defconf: port unreachable" icmp-options=3:3 protocol=icmp
add action=accept chain=icmp4 comment="defconf: fragmentation needed" icmp-options=3:4 protocol=icmp
add action=accept chain=icmp4 comment="defconf: echo" icmp-options=8:0 limit=5,10:packet protocol=icmp
add action=accept chain=icmp4 comment="defconf: time exceeded " icmp-options=11:0-255 protocol=icmp
add action=drop chain=icmp4 comment="defconf: drop other icmp" protocol=icmp
/ip route
add check-gateway=ping comment=default_isp disabled=no distance=1 dst-address=0.0.0.0/0 gateway=*.*.*.* routing-table=default_isp scope=30 suppress-hw-offload=no target-scope=10
/routing bgp connection
add as=64513 disabled=no local.address=172.20.215.132 .role=ibgp name=BorderGate1 remote.address=172.20.215.129/32 .as=64513 routing-table=default_myas
add as=64513 disabled=no local.address=172.20.215.132 .role=ibgp name=BorderGate2 remote.address=172.20.215.130/32 .as=64513 routing-table=default_myas
/routing ospf area range
add area=ospf-area-1 disabled=no prefix=172.20.215.128/27
add area=ospf-area-1 disabled=no prefix=192.0.2.0/24
/routing ospf interface-template
add area=ospf-area-1 auth=md5 auth-id=1 auth-key=**************** cost=100 dead-interval=10s disabled=no hello-interval=5s interfaces=wg-bg1-ftth,wg-bg2-ftth
add area=ospf-area-1 disabled=no interfaces=dum0 passive
add area=ospf-area-1 disabled=no interfaces=vlan44 passive
/routing rule
add action=lookup-only-in-table comment="Connections must never go through other links" disabled=no routing-mark=default_isp_only table=default_isp
add action=lookup comment="main table" disabled=no table=main
add action=lookup comment="default 44net" disabled=no src-address=192.0.2.0/24 table=default_myas
add action=lookup comment="default sonic" disabled=no table=default_isp
/tool sniffer
set filter-ip-address=192.0.2.210/32 filter-ip-protocol=udp filter-port=51820