I’m having trouble with a Wireguard client behind a RouterOS NAT.
Background:
I have a Wireguard endpoint at a static IP (WG-SERVER), and I’d like to connect to it from a client (WG-CLIENT) behind a CRS328-24P-4S+ which is configured to masquerade behind a dynamic IP address. The WG-CLIENT configuration has “PersistentKeepalive = 150”, which appears to function correctly.
Problem:
When WG-CLIENT comes up and performs a Wireguard handshake because of the PersistentKeepalive setting, I’m sniffing three packets along the path: two bound for WG-SERVER, and one from WG-SERVER back to WG-CLIENT. The handshake works successfully, and I’m able to transfer data between those hosts. However, if no additional data is transferred after the handshake for 10 seconds, the RouterOS connection tracking never bumps the timeout for the NAT entry from the “udp-timeout” value of 10 seconds to the “udp-stream-timeout” value of 180 seconds, and the NAT entry dies before the next keepalive handshake.
If I ping between the hosts within the 10 seconds after the handshake, the NAT entry timeout is reset to 180 seconds as it should. Future handshakes (every 150 seconds) then reset the entry’s timeout to 180 seconds and things work well until the session terminates.
I expected that by sending packets in both directions, the Wireguard handshake should trigger the “udp-stream-timeout” reset, but it does not and I can’t figure out why. I tried adding “PersistentKeepalive” to the WG-SERVER configuration for that peer, and while an additional packet from WG-SERVER to WG-CLIENT is sent during the initial handshake, the NAT entry still times out after 10 seconds.
Relevant config:
# 2023-06-16 15:18:56 by RouterOS 7.10
# software id = DXQ4-4HPK
#
# model = CRS328-24P-4S+
# serial number = QQQQQQQQQQQQ
/interface bridge port
add bridge=bridge ingress-filtering=no interface=sfp-sfpplus1
/ip address
add address=172.16.8.1/16 interface=bridge network=172.16.0.0
/ip dhcp-client
add interface=ether1 use-peer-dns=no use-peer-ntp=no
/ip firewall filter
add action=accept chain=input connection-state=established,related
add action=drop chain=input connection-state=invalid
add action=accept chain=input in-interface=ether1 protocol=icmp
add action=drop chain=input in-interface=ether1
/ip firewall nat
add action=masquerade chain=srcnat out-interface=ether1 src-address=172.16.0.0/16
Connection tracking settings (all defaults):
enabled: auto
active-ipv4: yes
active-ipv6: yes
tcp-syn-sent-timeout: 5s
tcp-syn-received-timeout: 5s
tcp-established-timeout: 1d
tcp-fin-wait-timeout: 10s
tcp-close-wait-timeout: 10s
tcp-last-ack-timeout: 10s
tcp-time-wait-timeout: 10s
tcp-close-timeout: 10s
tcp-max-retrans-timeout: 5m
tcp-unacked-timeout: 5m
loose-tcp-tracking: yes
udp-timeout: 10s
udp-stream-timeout: 3m
icmp-timeout: 10s
generic-timeout: 10m
max-entries: 479232
total-entries: 157
Handshake sniff:
Columns: INTERFACE, TIME, NUM, DIR, SRC-MAC, DST-MAC, SRC-ADDRESS, DST-ADDRESS, PROTOCOL, SIZE, CPU
INTERFACE TIME NUM DIR SRC-MAC DST-MAC SRC-ADDRESS DST-ADDRESS PROTOCOL SIZE CPU
sfp-sfpplus1 3.098 1 <- XX:XX:XX:XX:XX:XX YY:YY:YY:YY:YY:YY 172.16.8.2:39663 WG-SERVER-IP:51820 ip:udp 190 0
bridge 3.098 2 <- XX:XX:XX:XX:XX:XX YY:YY:YY:YY:YY:YY 172.16.8.2:39663 WG-SERVER-IP:51820 ip:udp 190 0
ether1 3.098 3 -> YY:YY:YY:YY:YY:YY ZZ:ZZ:ZZ:ZZ:ZZ:ZZ EXT-DYNAMIC-IP:39663 WG-SERVER-IP:51820 ip:udp 190 0
ether1 3.16 4 <- ZZ:ZZ:ZZ:ZZ:ZZ:ZZ YY:YY:YY:YY:YY:YY WG-SERVER-IP:51820 EXT-DYNAMIC-IP:39663 ip:udp 134 0
bridge 3.16 5 -> YY:YY:YY:YY:YY:YY XX:XX:XX:XX:XX:XX WG-SERVER-IP:51820 172.16.8.2:39663 ip:udp 134 0
sfp-sfpplus1 3.16 6 -> YY:YY:YY:YY:YY:YY XX:XX:XX:XX:XX:XX WG-SERVER-IP:51820 172.16.8.2:39663 ip:udp 134 0
sfp-sfpplus1 3.16 7 <- XX:XX:XX:XX:XX:XX YY:YY:YY:YY:YY:YY 172.16.8.2:39663 WG-SERVER-IP:51820 ip:udp 74 0
bridge 3.16 8 <- XX:XX:XX:XX:XX:XX YY:YY:YY:YY:YY:YY 172.16.8.2:39663 WG-SERVER-IP:51820 ip:udp 74 0
ether1 3.16 9 -> YY:YY:YY:YY:YY:YY ZZ:ZZ:ZZ:ZZ:ZZ:ZZ EXT-DYNAMIC-IP:39663 WG-SERVER-IP:51820 ip:udp 74 0
NAT entry:
6 SAC s protocol=udp src-address=172.16.8.2:39663 dst-address=WG-SERVER-IP:51820 reply-src-address=WG-SERVER-IP:51820
reply-dst-address=EXT-DYNAMIC-IP:50167 timeout=8s orig-packets=2 orig-bytes=236 orig-fasttrack-packets=0
orig-fasttrack-bytes=0 repl-packets=1 repl-bytes=120 repl-fasttrack-packets=0 repl-fasttrack-bytes=0
orig-rate=0bps repl-rate=0bps