Wireguard on one of multiple WAN interfaces

Hi,
after many failed attempts to set up my Mikrotik router I decided to ask for help here.
My current mikrotik config is attached.

The story:
I have 2 ISP connected to my router

  • WAN_1 - fiber, behind NAT, the main connection as it is the fastest one
  • WAN_2 - LTE, public IP, used just for WG and as a failower in case WAN_1 is down

I need to access my HO and all resources in the network. I decided to setup Wireguard and as I have public IP only on WAN2 I would like it be utilized in that scenario.

The problem I have right now is that for some reason I cannot establish WG handshake (no connection), as soon as I disable WAN_1 interface WG starts to work.
I assume I have sth wrong with routing tables or I am marking (firewall mangle) connections in wrong way.

I read mikrotik documentation aboput PCC, policy routing, firewall mangle etc, but as Mikrotik not very experienced user I could not identify the root cause of the issue.

As the last attempt I added IP rule for to_WAN_2 marked conenction to only look up routes in to_WAN_2 routing table but without success.

Could you provide any ideas how I could fix the config? Or I just approached the problem from wrong side…

Best regards


# 2023-09-25 08:18:28 by RouterOS 7.11.2
# software id = R1N2-1JGC
#
# model = C53UiG+5HPaxD2HPaxD
/interface bridge
add admin-mac=78:9A:18:03:94:50 auto-mac=no comment=defconf name=LAN_BRIDGE
/interface ethernet
set [ find default-name=ether2 ] comment=fiber name=WAN_1
set [ find default-name=ether3 ] comment=lte name=WAN_2
set [ find default-name=ether1 ] comment="mikrotik switch"
set [ find default-name=ether5 ] comment=nas
/interface wifiwave2
set [ find default-name=wifi2 ] channel.band=2ghz-ax .skip-dfs-channels=\
    10min-cac .width=20/40mhz configuration.mode=ap .ssid=topsecret2G \
    disabled=no name=wifi2G security.authentication-types=wpa2-psk,wpa3-psk
set [ find default-name=wifi1 ] channel.band=5ghz-ax .skip-dfs-channels=\
    10min-cac .width=20/40/80mhz configuration.mode=ap .ssid=topsecret5G \
    disabled=no name=wifi5G security.authentication-types=wpa2-psk,wpa3-psk
/interface wireguard
add listen-port=13231 mtu=1420 name=wireguard1
/interface list
add comment=defconf name=WAN
add comment=defconf name=LAN
/ip pool
add name=dhcp ranges=10.0.0.3-10.0.0.254
/ip dhcp-server
add address-pool=dhcp interface=LAN_BRIDGE lease-time=1h name=defconf
/routing table
add disabled=no fib name=to_WAN_1
add disabled=no fib name=to_WAN_2
add comment=wireguard disabled=yes fib name=TO_WG
/interface bridge port
add bridge=LAN_BRIDGE comment=defconf interface=ether4
add bridge=LAN_BRIDGE comment=defconf interface=ether5
add bridge=LAN_BRIDGE comment=defconf interface=wifi5G
add bridge=LAN_BRIDGE comment=defconf interface=wifi2G
add bridge=LAN_BRIDGE interface=ether1
/ip neighbor discovery-settings
set discover-interface-list=LAN
/interface list member
add comment=defconf interface=LAN_BRIDGE list=LAN
add comment=mobile interface=WAN_2 list=WAN
add comment=fiber interface=WAN_1 list=WAN
add interface=wireguard1 list=LAN
/interface wireguard peers
add allowed-address=10.0.10.2/32 interface=wireguard1 public-key=\
    "XXX"
add allowed-address=10.0.10.3/32 interface=wireguard1 public-key=\
    "XXX"
/ip address
add address=10.0.0.1/24 comment=defconf interface=LAN_BRIDGE network=10.0.0.0
add address=10.0.10.1/28 interface=wireguard1 network=10.0.10.0
/ip dhcp-client
add add-default-route=no comment=defconf interface=WAN_2
add interface=WAN_1
/ip dhcp-server network
add address=10.0.0.0/24 comment=defconf dns-server=10.0.0.11,8.8.8.8 gateway=\
    10.0.0.1 netmask=24
/ip dns
set allow-remote-requests=yes
/ip dns static
add address=10.0.0.1 comment=defconf name=router.lan
/ip firewall filter
add action=accept chain=input comment="allow WireGuard traffic" src-address=\
    10.0.10.0/28
add action=accept chain=input comment="allow wireguard" dst-port=13231 log=\
    yes protocol=udp
add action=accept chain=input disabled=yes in-interface=WAN_2
add action=accept chain=input comment=\
    "defconf: accept established,related,untracked" connection-state=\
    established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=\
    invalid
add action=accept chain=input comment="defconf: accept ICMP" protocol=icmp
add action=accept chain=input comment=\
    "defconf: accept to local loopback (for CAPsMAN)" dst-address=127.0.0.1
add action=drop chain=input comment="defconf: drop all not coming from LAN" \
    in-interface-list=!LAN
add action=accept chain=forward comment="defconf: accept in ipsec policy" \
    ipsec-policy=in,ipsec
add action=accept chain=forward comment="defconf: accept out ipsec policy" \
    ipsec-policy=out,ipsec
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=drop chain=forward comment="defconf: drop invalid" \
    connection-state=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
/ip firewall mangle
add action=mark-connection chain=prerouting connection-mark=no-mark \
    in-interface=WAN_2 log=yes new-connection-mark=WAN2 passthrough=yes
add action=mark-routing chain=prerouting connection-mark=WAN2 in-interface=\
    LAN_BRIDGE log=yes new-routing-mark=to_WAN_2 passthrough=yes
add action=mark-routing chain=output connection-mark=WAN2 log=yes \
    new-routing-mark=to_WAN_2 passthrough=yes
/ip firewall nat
add action=masquerade chain=srcnat comment="defconf: masquerade" \
    ipsec-policy=out,none out-interface-list=WAN
/ip route
add disabled=no distance=1 dst-address="" gateway=X.X.X.1 routing-table=\
    to_WAN_2 suppress-hw-offload=no
add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=X.X.X.1 \
    pref-src="" routing-table=main suppress-hw-offload=no
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=192.168.1.1 \
    pref-src="" routing-table=to_WAN_1 suppress-hw-offload=no
add disabled=no distance=1 dst-address=10.0.10.0/28 gateway=wireguard1 \
    routing-table=to_WAN_2 suppress-hw-offload=no
add disabled=no distance=1 dst-address="" gateway=WAN_2 pref-src="" \
    routing-table=to_WAN_2 suppress-hw-offload=no
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=X.X.X.1 \
    pref-src="" routing-table=to_WAN_2 suppress-hw-offload=no
add disabled=no distance=1 dst-address=10.0.0.0/24 gateway=LAN_BRIDGE \
    routing-table=to_WAN_2 suppress-hw-offload=no
add disabled=no dst-address=X.X.X.0/16 gateway=WAN_2 routing-table=\
    to_WAN_2 suppress-hw-offload=no
/ipv6 firewall address-list
add address=::/128 comment="defconf: unspecified address" list=bad_ipv6
add address=::1/128 comment="defconf: lo" list=bad_ipv6
add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6
add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6
add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6
add address=100::/64 comment="defconf: discard only " list=bad_ipv6
add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6
add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6
add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6
/ipv6 firewall filter
add action=accept chain=input comment=\
    "defconf: accept established,related,untracked" connection-state=\
    established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=\
    invalid
add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\
    icmpv6
add action=accept chain=input comment="defconf: accept UDP traceroute" port=\
    33434-33534 protocol=udp
add action=accept chain=input comment=\
    "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\
    udp src-address=fe80::/10
add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \
    protocol=udp
add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\
    ipsec-ah
add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\
    ipsec-esp
add action=accept chain=input comment=\
    "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=input comment=\
    "defconf: drop everything else not coming from LAN" in-interface-list=\
    !LAN
add action=accept chain=forward comment=\
    "defconf: accept established,related,untracked" connection-state=\
    established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" \
    connection-state=invalid
add action=drop chain=forward comment=\
    "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6
add action=drop chain=forward comment=\
    "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6
add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \
    hop-limit=equal:1 protocol=icmpv6
add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\
    icmpv6
add action=accept chain=forward comment="defconf: accept HIP" protocol=139
add action=accept chain=forward comment="defconf: accept IKE" dst-port=\
    500,4500 protocol=udp
add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\
    ipsec-ah
add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\
    ipsec-esp
add action=accept chain=forward comment=\
    "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=forward comment=\
    "defconf: drop everything else not coming from LAN" in-interface-list=\
    !LAN
/routing rule
add action=lookup-only-in-table disabled=no routing-mark=to_WAN_2 table=\
    to_WAN_2
/system clock
set time-zone-name=Europe/Warsaw
/system logging
add action=qnap prefix=mikrotik
/system note
set show-at-login=no
/tool graphing interface
add
/tool graphing resource
add
/tool mac-server
set allowed-interface-list=LAN
/tool mac-server mac-winbox
set allowed-interface-list=LAN
/tool sniffer
set filter-interface=wireguard1

(1) DHCP server network is a bit funny… remove the netmask… Also why 10.0.0.11 ???

modify from:
/ip dhcp-server network
add address=10.0.0.0/24 comment=defconf dns-server=10.0.0.11,8.8.8.8 gateway=
10.0.0.1 netmask=24
TO:
/ip dhcp-server network
add address=10.0.0.0/24 comment=defconf dns-server=8.8.8.8 gateway=10.0.0.1

(2) What goes to ether1 ??

(3) Remove the static default DNS entry
/ip dns static
add address=10.0.0.1 comment=defconf name=router.lan

(4) Put your input chain rules in a more standard location and why are you blocking wan2 ??? no need!!
Assuming also that both wireguard addresses are Admin related that you are allowing to the router for config purposes.

/ip firewall address-list
add address=10.0.10.0/24 list=Authorized comment=“admin remote wireguard access”
add address=10.0.0.X/32 list=Authorized comment=“admin local desktop/laptop access”
add address=10.0.0.Y/32 list=Authorized comment=“admin local iphone/ipad access”
ip firewall filter
add action=accept chain=input comment=
“defconf: accept established,related,untracked” connection-state=
established,related,untracked
add action=drop chain=input comment=“defconf: drop invalid” connection-state=
invalid
add action=accept chain=input comment=“defconf: accept ICMP” protocol=icmp
add action=accept chain=input comment=
“defconf: accept to local loopback (for CAPsMAN)” dst-address=127.0.0.1
add action=accept chain=input comment=“allow wireguard” dst-port=13231 log=
yes protocol=udp

add action=accept chain=input comment=“admin access” src-address-list=Authorized
add action=accept chain=input comment=“user access services” dst-port=53
protocol=udp in-interface-list=LAN
add action=accept chain=input comment=“user access services” dst-port=53
protocol=tcp in-interface-list=LAN
add action=drop chain=input comment='drop all else"{ do not add until allow authorized rules are in place }

  1. If not using IPV6 disable it… and remove all the ipv6 rules…
    /ipv6 settings
    set disable-ipv6=yes forward=no

  2. You have to use WAN2 for vpn handshake as as that is the only public IP. Confirm that you have no access to forward ports on ISP1 ??

  3. I have no idea what mess you have made of IP routes and mangles, but I dont understand what you have done or were trying to do…
    Remove all the mangles, not necessary!

What I suggest is basic recursive routing for Primary WAN1 and Failover to WAN2 but ensuring WAN2 is available at all times for wireguard connectivity.

add check-gateway=ping distance=2 dst-address=0.0.0.0/0 gateway=1.0.0.1 scope=10 target-scope=12
add distance=2 dst-address=1.0.0.1/32 gateway=192.168.1.1 scope=11 target-scope=11
add comment=SecondaryISP distance=5 dst-address=0.0.0.0/0 gateway=X.X.X.1 scope=10 target-scope=30

This basically ensures that the primary is accessible from both your home to the provider and from the provider to the WWW.
If the primary is down, the router looks on table main and finds the alternate route through WAN2.

Now lets deal with the incoming VPN handshake, how do we ensure traffic coming on WAN2, leaves on WAN2, when WAN1 is designated the priority.
We will use the table you have created, another route to point to the table, and routing rule to point to the route via the table.

/routing table
add comment=“wg handshake” fib name=TO_WAN2

/ip route
add dst-address=0.0.0.0/0 gateway=X.X.X.1 routing-table=TO_WAN2

/routing rule
add action=lookup-only-in-table src-address=X.X.X.1 table=to_WAN2

In other words, although the handshake can reach WAN2, the reply coming from WAN2 (source) needs to be forced out via WAN2,
to avoid being routed out WAN1 as WAN1 has priority in main table.

Alternatively this could have been accomplished with mangling… but I prefer the routing rule approach whenever possible - less complex.
First we mark traffic coming in on WAN, the we on output force it to a different table (not main) by route-marking the traffic. We also have to ensure we adjust the fastrack firewall rule.

/ip firewall mangle
add chain=prerouting action=mark-connection connection-mark=no-mark
in-interface=WAN_2 new-connection-mark=incomingWAN2 passthrough=yes

add chain=output action=mark-routing connection-mark=incomingWAN2
new-routing mark=TO_WAN2 passthrough=no

Note1: add action=fasttrack-connection chain=forward comment=“defconf: fasttrack”
connection-state=established,related hw-offload=yes connection-mark=no-mark

Note2: USES the same table and IP route we created above.

I have a lot of experience with Mikrotik and multiple connections. I have come across this once the past that even with all the correct routing and mangle rules Wireguard will only work on the default (lowest route) interface. I did start writing a forum post on this but ran out of time to finish it.
If I have time I will do some more diagnostics on this and add to your thread. Just wanted to let you know that it might not be your fault. I think there might be an issue here. I will try to do some diagnostics on this again.

Not true from my experience, I suspect your config was faulty or it was a temporary bug in one version of firmware.
Traffic will flow where you tell it to flow.
The biggest change from the past was that routing rules had priority over mangles and now that is no longer the case, so one has to be sure to be more precise in what is being mangled to avoid conflicts in complex configs. In the above config, without mangling, the routing rule will work. If one elects to mangle, then the routing rule is not required.

@anav thank you for your response, it helped to solve my issue
I agree routing rules are sufficient in my scenario and much easier to understand and apply than firewall mangling
Also I appreciate suggestions related to firewall improvements in matter of security

some responses to questions:

(1) DHCP server network is a bit funny… remove the netmask… Also why 10.0.0.11 ???

10.0.0.11 is my local DNS server (AdGuard)

(2) What goes to ether1 ??

another mikrotik router which is just acting as switch right now

(4) Put your input chain rules in a more standard location and why are you blocking wan2 ??? no need!!

hm, I believe I do not have any rule blocking WAN2

Assuming also that both wireguard addresses are Admin related that you are allowing to the router for config purposes.

correct

You have to use WAN2 for vpn handshake as as that is the only public IP. Confirm that you have no access to forward ports on ISP1 ??

ISP1 is just black hole, I have no possibilities there

/routing rule
add action=lookup-only-in-table > src-address=X.X.X.1 > table=to_WAN2

it made it work

Thanks

Correct I was referring to a disabled rule that was not quite a blocking rule, upon closer inspection, it can be removed.
add action=accept chain=input disabled=yes in-interface=WAN_2

I suspect this ^^. It was some time ago.
I have just re-tested (using in/out mangle rules, not fixed routing as it was a road-warrior setup) on a more recent firmware, and it is working as one would expect.

@anav, could you elaborate a bit more on the quoted section, I do not understand why to use gateway=1.0.0.1?

Basically the resursive idea is to see if you can actually reach a WWW “LIVE” site via your ISP. This is done because too many times, one can reach their ISP, {connectivity from home/business to ISP} but the ISP has become disconnected from the internet itself… So the MT router does not switch to WAN2.
With recursive we VERY BASICALLY are saying, can I reach google, or cloudflare or any other public DNS site which is usually available 99% of the time.

Recursive is a matter of stating the furthest hop.
Can I reach the WWW from the public DNS
Then the closer hop
Can I reach the public DNS from my ISP
+++++++++++++++++++++++++++++++++++++++++

ronalda 2, that sounds like chatgpt jibberish, in any case, useless crap.