Use WireGuard with Proton VPN on specific port

No, it certainly didn't work thank to your NAT rule from the screenshot above. That NAT rule has no effects (you can verify by looking at the packet and byte counters of the rule that will all stay at 0). In the NAT table there are only 4 built-in chains: dstnat, input, output, and srcnat. Any other chains, such as forward that you typed in the screenshot, are custom chains, (like those chains that people normally create in the filter table for special handling of ICMP or some ineffective "brute force" prevention). Rules in custom chain (such as the forward chain in the NAT table that you created above) are not hit at all, unless there was a jump rule that has been matched, with the jump target set to the custom chain.

Even if you somehow also added a jump rule in the NAT table specifying jump-target=forward and that rule was hit and the firewall jumped to your chain=forward rule from the screenshot, that rule will not be matched, because what you specified in the rule, out-interface=ProtonVPN, is part of the matching conditions for the rule, not an action that performs any change. The rule is only matched if the out-interface is already ProtonVPN.

Furthermore, a NAT rule can only affect the routing decision if its action is one of those that modify the destination address. Such rules obviously should not be applied to the packets that you send out to the internet (while web browsing for example) because you don't want to change the address of the servers you are sending the packets to.

OK. It was working though. I did not add a jump rule. Who knows. It seems to be fine now following the routing rule that you specified.

// EDIT - UPDATED [2026-02-07, 2026-02-08] //

// EDIT - UPDATED [2026-03-12] - removed check-gateway=ping. I noticed that check-gateway=ping causes issues with routes for secure VPN tunnels i.e. router-Switzerland-US type WG tunnels. Sometimes pings fail for such round trips rendering the routes USI :: unreachable,static,inactive. Also, lowered the recursive routes’ route-distances to 3,6,9,12,15//

This is what I got and seems to be working, I have three ProtonVPN WG instances with route distances 1, 5, 10 for fail-over (not implementing KILLSWITCH). I have NextDNS DOH setup, so i don’t care much about the ProtonVPN DNS in my setup.

REFERENCE: https://protonvpn.com/support/wireguard-mikrotik-routers/

REFERENCE: https://data-discourse.cdn.mikrotik.com/original/3X/c/3/c344ca2c451fc4d2cf2b84245daffec6b38cd9b4.pdf

/interface/wireguard

/interface wireguard
## WG1
add comment="ProtonVPN WG1 [US-CO-189]" listen-port=13231 mtu=1420 name=\
    wg1-protonvpn private-key="YOUR-PRIVATE-KEY"
## WG2
add comment="ProtonVPN WG2 [US-IL-268]" listen-port=13232 mtu=1420 name=\
    wg2-protonvpn private-key="YOUR-PRIVATE-KEY"
## WG3
add comment="ProtonVPN WG3 [CH-US-003]" listen-port=13233 mtu=1420 name=\
    wg3-protonvpn private-key="YOUR-PRIVATE-KEY"
## WG4
add comment="ProtonVPN WG4 [IS-US-001]" listen-port=13234 mtu=1420 name=\
    wg4-protonvpn private-key="YOUR-PRIVATE-KEY"
## WG5
add comment="ProtonVPN WG5 [CH-US-003-ALT]" listen-port=13235 mtu=1420 name=\
    wg5-protonvpn private-key="YOUR-PRIVATE-KEY"
/interface wireguard peers
## WG1
add allowed-address=0.0.0.0/0,::/0 client-address=10.22.2.2/32 \
    client-allowed-address=0.0.0.0/0,::/0 client-dns=10.22.2.1 comment=\
    "ProtonVPN WG2 [US-IL-268]" endpoint-address="VPN-ENDPOINT-IPv4" \
    endpoint-port=51820 interface=wg2-protonvpn name=peer2-protonvpn \
    persistent-keepalive=25s public-key="PUBLIC-KEY"

## WG2
add allowed-address=0.0.0.0/0,::/0 client-address=10.11.1.2/32 \
    client-allowed-address=0.0.0.0/0,::/0 client-dns=10.11.1.1 comment=\
    "ProtonVPN WG1 [US-CO-189]" endpoint-address="VPN-ENDPOINT-IPv4" \
    endpoint-port=51820 interface=wg1-protonvpn name=peer1-protonvpn \
    persistent-keepalive=25s public-key="PUBLIC-KEY"

## WG3
add allowed-address=0.0.0.0/0,::/0 client-address=10.33.3.2/32 \
    client-allowed-address=0.0.0.0/0,::/0 client-dns=10.33.3.1 comment=\
    "ProtonVPN WG3 [CH-US-003]" endpoint-address="VPN-ENDPOINT-IPv4" \
    endpoint-port=51820 interface=wg3-protonvpn name=peer3-protonvpn \
    persistent-keepalive=25s public-key="PUBLIC-KEY"

## WG4
add allowed-address=0.0.0.0/0,::/0 client-address=10.44.4.2/32 \
    client-allowed-address=0.0.0.0/0,::/0 client-dns=10.44.4.1 comment=\
    "ProtonVPN WG4 [IS-US-001]" endpoint-address="VPN-ENDPOINT-IPv4" \
    endpoint-port=51820 interface=wg4-protonvpn name=peer4-protonvpn \
    persistent-keepalive=25s public-key="PUBLIC-KEY"

## WG5
add allowed-address=0.0.0.0/0,::/0 client-address=10.55.5.2/32 \
    client-allowed-address=0.0.0.0/0,::/0 client-dns=10.55.5.1 comment=\
    "ProtonVPN WG5 [CH-US-003-ALT]" endpoint-address="VPN-ENDPOINT-IPv4" \
    endpoint-port=51820 interface=wg5-protonvpn name=peer5-protonvpn \
    persistent-keepalive=25s public-key="PUBLIC-KEY"

/interface

/interface vlan add comment="VPN-LAN [VID 12]" interface=bridge1 \
name=vlan12-vpnlan vlan-id=12

## VLAN INTERFACE USED FOR FIREWALL
/interface list add name=VPNLAN
/interface list member add interface=vlan12-vpnlan list=VPNLAN

## PHYSICAL PORTS [NOT USED IN FIREWALL]
/interface list add name=VPNLAN_PHY
/interface list member add interface=sfp-sfpplus7 list=VPNLAN_PHY
/interface list member add interface=sfp-sfpplus8 list=VPNLAN_PHY

## ProtonVPN TUNNEL INTERFACES - VPN-OUT [FOR FIREWALL MASQUERADE]
/interface list add name=VPN-OUT
/interface list member add interface=wg1-protonvpn list=VPN-OUT
/interface list member add interface=wg2-protonvpn list=VPN-OUT
/interface list member add interface=wg3-protonvpn list=VPN-OUT
/interface list member add interface=wg4-protonvpn list=VPN-OUT
/interface list member add interface=wg5-protonvpn list=VPN-OUT

## ProtonVPN TUNNEL INTERFACES - INET [FOR FIREWALL FILTER RULES ONLY]
/interface list add name=INET
/interface list member add interface=wg1-protonvpn list=INET
/interface list member add interface=wg2-protonvpn list=INET
/interface list member add interface=wg3-protonvpn list=INET
/interface list member add interface=wg4-protonvpn list=INET
/interface list member add interface=wg5-protonvpn list=INET

/ip/address

/ip address
## VPNLAN-VLAN12
add address=192.168.12.1/22 comment=VPNLAN-VLAN12 interface=vlan12-vpnlan \
    network=192.168.12.0
## WG1
add address=10.11.1.2/30 comment="ProtonVPN [WG1]" interface=wg1-protonvpn \
    network=10.11.1.0
## WG2
add address=10.22.2.2/30 comment="ProtonVPN [WG2]" interface=wg2-protonvpn \
    network=10.22.2.0
## WG3
add address=10.33.3.2/30 comment="ProtonVPN [WG3]" interface=wg3-protonvpn \
    network=10.33.3.0
## WG4
add address=10.44.4.2/30 comment="ProtonVPN [WG4]" interface=wg4-protonvpn \
    network=10.44.4.0
## WG5
add address=10.55.5.2/30 comment="ProtonVPN [WG5]" interface=wg5-protonvpn \
    network=10.55.5.0

/ip dns

/ip dns static add address=10.11.1.1 name=ProtonVPN-WG-1 type=A
/ip dns static add address=10.22.2.1 name=ProtonVPN-WG-2 type=A
/ip dns static add address=10.33.3.1 name=ProtonVPN-WG-3 type=A
/ip dns static add address=10.44.4.1 name=ProtonVPN-WG-4 type=A
/ip dns static add address=10.55.5.1 name=ProtonVPN-WG-5 type=A

/routing

## DEFAULT RULE - MAIN TABLE (CREATED AUTOMATICALLY FOR ISP-WAN AND OTHER ROUTES)
/routing rule add action=lookup-only-in-table \
comment="Local traffic lookups" disabled=no min-prefix=0 table=main

## ProtonVPN TABLE
/routing table add disabled=no fib name=protonvpn

## ProtonVPN RULES
## IPv4
/routing rule add action=lookup-only-in-table comment="Uplink traffic lookups from VPN-LAN [IPv4]" \
disabled=no dst-address=0.0.0.0/0 interface=vlan12-vpnlan min-prefix=0 \
src-address=192.168.12.0/22 table=protonvpn

## [optional] IPv6 - doesn't work, created for consistency only [optional]
/routing rule add action=lookup-only-in-table comment="Uplink traffic lookups from VPN-LAN [IPv6]" \
disabled=no dst-address=::/0 interface=vlan12-vpnlan min-prefix=0 \
src-address=fd12::/56 table=protonvpn

/ip/route

/ip route

## WG1
add comment="wg1-protonvpn (02 - The \"Lower\" Half)" disabled=no distance=15 \
    dst-address=0.0.0.0/1 gateway=10.11.1.1%wg1-protonvpn routing-table=\
    protonvpn scope=30 target-scope=10
add comment="wg1-protonvpn (01 - The \"Upper\" Half)" disabled=no distance=15 \
    dst-address=128.0.0.0/1 gateway=10.11.1.1%wg1-protonvpn routing-table=\
    protonvpn scope=30 target-scope=10
    
## WG2
add comment="wg2-protonvpn (02 - The \"Lower\" Half)" disabled=no distance=12 \
    dst-address=0.0.0.0/1 gateway=10.22.2.1%wg2-protonvpn routing-table=\
    protonvpn scope=30 target-scope=10
add comment="wg2-protonvpn (01 - The \"Upper\" Half)" disabled=no distance=12 \
    dst-address=128.0.0.0/1 gateway=10.22.2.1%wg2-protonvpn routing-table=\
    protonvpn scope=30 target-scope=10

## WG3
add comment="wg3-protonvpn (01 - The \"Upper\" Half)" disabled=no distance=9 \
    dst-address=128.0.0.0/1 gateway=10.33.3.1%wg3-protonvpn routing-table=\
    protonvpn scope=30 target-scope=10
add comment="wg3-protonvpn (02 - The \"Lower\" Half)" disabled=no distance=9 \
    dst-address=0.0.0.0/1 gateway=10.33.3.1%wg3-protonvpn routing-table=\
    protonvpn scope=30 target-scope=10
    
## WG4
add comment="wg4-protonvpn (02 - The \"Lower\" Half)" disabled=no distance=6 \
    dst-address=0.0.0.0/1 gateway=10.44.4.1%wg4-protonvpn routing-table=\
    protonvpn scope=30 target-scope=10
add comment="wg4-protonvpn (01 - The \"Upper\" Half)" disabled=no distance=6 \
    dst-address=128.0.0.0/1 gateway=10.44.4.1%wg4-protonvpn routing-table=\
    protonvpn scope=30 target-scope=10

## WG5
add comment="wg5-protonvpn (01 - The \"Upper\" Half)" disabled=no distance=3 \
    dst-address=128.0.0.0/1 gateway=10.55.5.1%wg5-protonvpn routing-table=\
    protonvpn scope=30 target-scope=10
add comment="wg5-protonvpn (02 - The \"Lower\" Half)" disabled=no distance=3 \
    dst-address=0.0.0.0/1 gateway=10.55.5.1%wg5-protonvpn routing-table=\
    protonvpn scope=30 target-scope=10

/ip firewall nat

[NOTE: VPN-LAN_IPs := 192.168.12.0/22]

## INTERCEPT DNS PACKETS OF VPN TRAFFIC ##
## UDP 53
/ip firewall nat add action=redirect chain=dstnat \
comment="Intercept DNS traffic for VPN-LAN - redirect (udp 53) [IPs+Interface]" \
dst-port=53 in-interface-list=VPNLAN protocol=udp src-address-list=VPNLAN_IPs to-ports=53
#
/ip firewall nat add action=redirect chain=dstnat \
comment="Intercept DNS traffic for VPN-LAN - redirect (udp 53) [IPs]" \
dst-port=53 protocol=udp src-address-list=VPNLAN_IPs to-ports=53
#

## TCP 53
/ip firewall nat add action=redirect chain=dstnat \
comment="Intercept DNS traffic for VPN-LAN - redirect (tcp 53) [IPs+Interface]" \
dst-port=53 in-interface-list=VPNLAN protocol=tcp src-address-list=VPNLAN_IPs to-ports=53
#
/ip firewall nat add action=redirect chain=dstnat \
comment="Intercept DNS traffic for VPN-LAN - redirect (tcp 53) [IPs]" \
dst-port=53 protocol=tcp src-address-list=VPNLAN_IPs to-ports=53


## MASQUERADE FOR VPN TRAFFIC ##
/ip firewall nat add action=masquerade chain=srcnat \
comment="MASQ: Allow VPN-OUT Access from VPN-LAN [IPs+Interface]" in-interface-list=VPNLAN \
out-interface-list=VPN-OUT src-address-list=VPNLAN_IPs
#
/ip firewall nat add action=masquerade chain=srcnat \
comment="MASQ: Allow VPN-OUT Access from VPN-LAN [Interface]" disabled=yes in-interface-list=VPNLAN \
out-interface-list=VPN-OUT

// EDIT - UPDATED [2026-02-07, 2026-02-08] //

Check:

/ip/route/print
Flags: D - DYNAMIC; I - INACTIVE, A - ACTIVE; c - CONNECT, s - STATIC, d - DHCP
Columns: DST-ADDRESS, GATEWAY, ROUTING-TABLE, DISTANCE
#     DST-ADDRESS       GATEWAY                  ROUTING-TABLE  DISTANCE
  DAc 10.11.1.0/30      wg1-protonvpn            main                  0
  DAc 10.22.2.0/30      wg2-protonvpn            main                  0
  DAc 10.33.3.0/30      wg3-protonvpn            main                  0
  DAc 10.44.4.0/30      wg4-protonvpn            main                  0
  DAc 10.55.5.0/30      wg5-protonvpn            main                  0
....
....
....
;;; wg2-protonvpn (02 - The "Lower" Half)
0   s 0.0.0.0/1         10.22.2.1%wg2-protonvpn  protonvpn            12
;;; wg1-protonvpn (02 - The "Lower" Half)
1   s 0.0.0.0/1         10.11.1.1%wg1-protonvpn  protonvpn            15
;;; wg3-protonvpn (02 - The "Lower" Half)
2   s 0.0.0.0/1         10.33.3.1%wg3-protonvpn  protonvpn             9
;;; wg4-protonvpn (02 - The "Lower" Half)
3   s 0.0.0.0/1         10.44.4.1%wg4-protonvpn  protonvpn             6
;;; wg5-protonvpn (02 - The "Lower" Half)
4  As 0.0.0.0/1         10.55.5.1%wg5-protonvpn  protonvpn             3
;;; wg2-protonvpn (01 - The "Upper" Half)
5   s 128.0.0.0/1       10.22.2.1%wg2-protonvpn  protonvpn            12
;;; wg1-protonvpn (01 - The "Upper" Half)
6   s 128.0.0.0/1       10.11.1.1%wg1-protonvpn  protonvpn            15
;;; wg3-protonvpn (01 - The "Upper" Half)
7   s 128.0.0.0/1       10.33.3.1%wg3-protonvpn  protonvpn             9
;;; wg4-protonvpn (01 - The "Upper" Half)
8   s 128.0.0.0/1       10.44.4.1%wg4-protonvpn  protonvpn             6
;;; wg5-protonvpn (01 - The "Upper" Half)
9  As 128.0.0.0/1       10.55.5.1%wg5-protonvpn  protonvpn             3

The above setup is working flawlessly.

Please critique and comment, if any.

It's somewhat very similar to what I am doing. My setup is working very well for me right now. Others may be able to provide more in depth comment.

What I will say is if your put your Wireguard Connection as WAN connections instead of LAN, then you can eliminate the masquerade firewall rule. They really are WAN connections.

I need to post my latest config in another thread so I'll come back here and post it here as well for you.

My biggest heartburn with Proton right now is that you cannot stream anything from Disney owned sites (ESPN, Disney, Hulu, etc) over the Proton connection. I've been hitting up Proton support for over 2 months now on this. I've also seen my connection go strangely down for no reason at times.

Second complaint is speed. I wish I could utilize more of my 2.5 Gbps downlink over the VPN but the best I can see is a little over a gigabit.

All this is why someone suggesting using a VPS with Mikrotik's Cloud Hosted Router license of RouterOS. Well, that's opened up another whole can of worms (hence the other thread!) :smiley:

The only can of worm, with CHR, is if you use it to access your oWN router or subnets from a remote device, like an IPHONE connecting through the wireguard CHR (server for handshake) to home.

The reasons is that VPS could get hacked and if you have that traffic allowed on the home router, that could be a problem. So just dont allow CHR WG traffic to reach home router config or home LAN subnets by firewall rules and good to go. Just use the CHR and VPS for outgoing traffic. Not like proton in that the location of the VPS, will determine which country the WANIP is affiliated with.

Remember its not needed either because if your home router has:
a. a public IP, you can run a separate wireguard just for remote access back to your router for config or subnets, OR
b. a non-public IP, then you use BTH wireguard available on the route to accomplish same.

There is an edge case if one has 2 or more routers without public IP, one can use a CHR to connect them in a secure manner, but thats a story for another day.

As far at that configuration its very suspect to me...........
The challenge is that you seem to want to be able to use three different wireguard tunnels accessing potentially 3 different locations ( diff countries??? )
Now if they have the same endpoint but a different port, then I imagine you could have all three tunnels up at the same time.
However, the problem is how do you decide which tunnel you will put the users through???
Routing becomes a challenge, and I dont think routing rules will cut it.

Are the wireguard addresses for each instance provided to you different?
Have they provided DNS addresses for each, or not.........

Looks like this user has two in the US and one in China?

image

US-CO is USA Colorado
US-IL is USA Illinois
CH-US - I'm assuming CH is China? Or could be Chile.

So a couple things. First, all the Proton servers have unique endpoint IPs. So that is not a problem. The routing rules are doable as you can create a different routing table for each connection. Then you can set different devices to use different connections. I have 3 different Proton servers I use - I have different devices using each one. What is nice about this is if one goes down (which did happen recently), it's very easy to switch your devices over to a different one.

AS for the addresses, I think the user has things a little mixed up. Proton allows you to use any number of different 10.0.0.0 addresses in the format of 10.x.0.2 for the client and 10.x.0.1 for DNS. So I use 10.1.0.2, 10.2.0.2, 10.3.0.2, etc. I don't think you can use the format that @thewickerman666 posted above of 10.11.1.1, 10.22.2.1, etc.

Agreed. No need to allow connections from the CHR back to home when home has its own abilities. The only advantage where you could use it is you now have a fixed IP address and can easily port forward specific traffic if needed as opposed to using Dynamic DNS.

Thank you @NA9D. Will be nice to see your setup. Much appreciate your perusal of my setup and comments.

CH is Switzerland. CH-US :: Home router to CH to US[NY].
The routing [route distance] seems to work the failover as desired.

With my setup DisneyPlus is also working, ensure you have some US endpoint thats all that is needed, imo.

Yes IP addresses of the endpoint are three different ones. Yes, the DNS’s are the 10.1.11.1, 10.2.22.1, 10.3.33.1 same as the client, didn’t make sense when i downloaded the config file from my ProtonVPN account dashboard. Like I said i don’t care much about DNS as I’m using NextDNS DoH DNS in my CCR2004 Gateway Router.

Hmm.. You are viewing Disney content over ProtonVPN? I have not had such luck and yes, all my endpoints are in the US. Maybe they fixed the issue. I'll try again...

What I heard is, DisneyPlus and various banks monitor if they have large number of connections with different usernames from the re-used public IPs flag it to be blocked, perhaps I got lucky.

I don’t watch DisneyPlus too often over WG protonVPN due to intermittent latency issues. So please don’t read too much into my feedback.