How to Configure a WireGuard VPN Connection to NordVPN on a Mikrotik Router Running ROS v7.x

Hello everyone,

I wanted to share a guide on setting up a WireGuard VPN connection to NordVPN on a Mikrotik router running RouterOS v7.x. While NordVPN provides instructions for setting up an IKEv2/IPSec VPN connection—which works fine—you need to use mangle to route specific destinations, and you cannot implement a kill switch. Other protocols like L2TP/IPSec have been retired by NordVPN, and OpenVPN does not work with Mikrotik routers. Using WireGuard offers better flexibility, including the ability to implement a kill switch and route specific traffic without complex configurations.


Prerequisites

  • A Mikrotik router running RouterOS v7.x
  • A Linux system (e.g., Debian) to retrieve necessary keys
  • An active NordVPN subscription

Step 1: Install NordVPN and WireGuard on Linux

First, install the NordVPN client on your Linux system. You can find detailed instructions on the NordVPN support site:

Installing NordVPN on Linux distributions

Next, install WireGuard:

sudo apt install wireguard

Step 2: Retrieve Your Private Key and Server Information

Establish a VPN connection using the NordVPN client:

nordvpn connect

Then, retrieve your private key:

sudo wg show nordlynx private-key

Note: Keep your private key secure and do not share it.

Next, obtain the public key, IP address, and port of the connected NordVPN WireGuard server:

sudo wg show nordlynx

Example output:

peer: aaaaaaabbbbbbbbxxxxxxyyyyyyyyy=
endpoint: x.x.x.x:51820

Alternatively, to find other servers and their information, use the NordVPN API:

curl 'https://nordvpn.com/wp-admin/admin-ajax.php?action=servers_recommendations&filters\[servers_technologies\]\[identifier\]=wireguard_udp&limit=1' | python3 -m json.tool

Note: Each server has its own public key, but your private key remains the same.


Step 3: Configure WireGuard on the Mikrotik Router

Create the WireGuard Interface

/interface wireguard add listen-port=51820 mtu=1420 name=wg-nordvpn private-key="your_private_key"
  • Replace “your_private_key” with the private key you obtained earlier.

Add the Peer (NordVPN Server)

/interface wireguard peers add allowed-address=0.0.0.0/0 endpoint-address=your_server_address endpoint-port=51820 interface=wg-nordvpn persistent-keepalive=5s public-key="server_public_key"
  • Replace your_server_address with the endpoint address (e.g., us100.nordvpn.com).
  • Replace “server_public_key” with the public key of the NordVPN server.

Assign an IP Address to the Interface

/ip address add address=10.5.0.2 interface=wg-nordvpn network=10.5.0.0

Step 4: Configure Firewall Rules

Allow Incoming WireGuard Connections

/ip firewall filter add action=accept chain=input comment="Allow WireGuard" dst-port=51820 protocol=udp

Allow Specific IPs to Use the VPN

First, define the list of IP addresses that are allowed to use the VPN:

/ip firewall address-list add address=192.168.1.0/24 list=access_vpn

Create a Firewall Rule to Allow Forwarding:

/ip firewall filter add action=accept chain=forward comment="Allow VPN Traffic" out-interface=wg-nordvpn src-address-list=access_vpn

Configure NAT for Outgoing Traffic

/ip firewall nat add action=masquerade chain=srcnat out-interface=wg-nordvpn

Step 5: Configure Routing and Implement a Kill Switch

Create a New Routing Table

/routing table add fib name="private_route"

Add Routing Rules

Route traffic from specific hosts through the VPN:

/routing rule add action=lookup-only-in-table src-address=192.168.1.100/32 table=private_route

Or route traffic to specific destinations (e.g., NordVPN DNS server):

/routing rule add action=lookup-only-in-table dst-address=103.86.96.100/32 table=private_route

Note: 103.86.96.100 is one of the DNS servers provided by NordVPN.

Configure Routes for the New Table

Add a blackhole route as a kill switch:

/ip route add blackhole distance=5 routing-table=private_route

Add a route through the WireGuard interface:

/ip route add distance=2 gateway=wg-nordvpn@main routing-table=private_route

Step 6: Test the Configuration

  • Ensure that devices specified in the address list are routing traffic through the VPN.
  • Verify that the kill switch works by disabling the WireGuard interface and checking if traffic from the specified devices is blocked.

Conclusion

That’s it! You should now have a working WireGuard VPN connection to NordVPN on your Mikrotik router, complete with policy routing and a kill switch. This setup allows you to route specific traffic through the VPN and ensures that if the VPN connection drops, traffic will not leak through your regular internet connection.

Let me know how it works for you or if you have any questions!

Just to add that in some cases, you might need the router to adjust the TCP MSS, if TCP connections get stuck.

/ip firewall mangle
add action=change-mss chain=forward comment=“Clamp MSS to PMTU” new-mss=clamp-to-pmtu out-interface=wg-nordvpn
protocol=tcp tcp-flags=syn

There are two options, the one that was stated as well as:
add action=change-mss chain=forward new-mss=1380 out-interface=wg-nordvpn protocol=tcp tcp-flags=syn tcp-mss=1381-65535

So, for my use case, I only want one device 10.10.15.x/32 to use nordlynx, but I want to be able to access that device from anywhere in the network. As I have it now, I was able to whitelist 10.10.15.0/24, 10.10.10.0/24, etc. Is this possible doing it through routeros?

The easiest way to provide access to a third party wireguard service is via WIFI.
Simply make a virtual WLAN just for internet access to nord…
If you have the option one can dedicate a vlan and ensure those needing access at their desks, have a managed switch next to the PC ( old hexes are great for this ) and then they can plug their PC into the correct port when wanting to go out nord for internet.

As for your requirement one user/device to go out nord, is fairly easy using routing rules vice anything more complex.
What I dont understand is that you want to be able to access that device from anywhere.
Can you elaborate the use cases in more detail.
why does device need to go out nord
why do users need to access device.
something missing in the equation to understand

Great guide, it works pefectly, thank you very much.

I’d like to use a list of destinations instead of inserting them one by one in the rules list. I tried (mainly with mangle) but I failed.

Do you think it would be possible?

Rereading your first post, BOLLOCKS…
Prerequisites

A Mikrotik router running RouterOS v7.x
A Linux system (e.g., Debian) to retrieve necessary keys
An active NordVPN subscription

Why??
NordVPN will give you the private key to use on the Mikrotik Router Interface creation. That creates a public key that will already be known to Nordvpn.
The only thing you need to do is:

a. configure the interface name=wireguardnord with private key given to you by Nord

b. add the address given by Nord to the router 10.20.30.X/24 \

c. add allowed-addresses=0.0.0.0/0 interface=wireguardnord endpoint-address= endpoint-port=XXXXX persistent-keep-alive=…
if Nord gives a preshared key, then that is also entered here.

b. Add a sourcenat rule for any traffic going out wireguard so that all traffic gets the expected source address given to you by NordVpn, and thus accepted at the remote end.

c. once you decide what traffic is to use nordvpn then
i. adjust firewall rules
ii. adjust routing ( either by mangles or routing rules )

d. perhaps modify some DNS settings depending if and what Nord gave you for DNS settings.

Hello Team

i am trying to setup also the NordVPN via Wireguard

But the New routing table is not working
How to troubleshoot this ?

Ignore post . problem solved

Gents, in order to make it work, should it be on fresh install? Being trying with other VPN as well for a month now and can’t set it up on my chateau. Today I bought nord and still can’t make it work. Any thoughts? Thanks on advance.

Provide
a. the config settings provided… ( minus endoint address use x.x.x.x.x and any keys )
b. router config
/export file=anynameyouwish ( minus router serial number, any public WANIP information, keys )

Here are the files, thanks again
vpn.rsc (101 Bytes)
anynameyouwish.rsc (1.71 KB)

You have hidden to much information to be of real assistance.
The only thing that should not be entered is

a. NORD VPN settings

  • private key
  • public key
  • endpoint address

The rest should have been available for viewing.

b. Router settings

  • serial number ( check )
  • endpoint-address ( check )
  • public key (check)
  • any public local WANIP or gateway information

What is also not clear is if this router is facing the internet or behind an upstream router or modem/router due to inadequate complete config especially firewall rules and any indication of the local WAN situation which is needed to establish from the getgo a wireguard connection.

Also what happens if the wireguard is not available??

Its lte router i think all of them if not ask for public ip they are behind cgnat. If wireguard is disabled i ve internet, so killswitch at least the one i set it, seems to not working.

I believe now the confs are correct, at least as you need them.
anynameyouwish.rsc (2.33 KB)
vpn (2).rsc (139 Bytes)

Okay,

  1. Modify allowed IPs from:
    /interface wireguard peers
    add allowed-address=0.0.0.0/0,::/0 endpoint-address=
    endpoint-port= interface=wg-nordvpn name=peer1 public-key=“”

    TO:
    /interface wireguard peers
    add allowed-address=0.0.0.0/0 endpoint-address=“as provided”
    endpoint-port=51820 interface=wg-nordvpn name=peer1 public-key=“as provided” persistent-keep-alive=25s

2. From
add address=10.5.0.2/16 interface=wg-nordvpn network=10.5.0.0

TO
add address=10.5.0.2**/24 i**nterface=wg-nordvpn network=10.5.0.0

  1. From
    add action=masquerade chain=srcnat
    add action=masquerade chain=srcnat out-interface=wg-nordvpn

    TO:
    /ip firewall nat
    add action=masquerade chain=srcnat out-interface=lte1
    add action=masquerade chain=srcnat out-interface=wg-nordvpn

  2. from
    /ip route
    add blackhole distance=5 routing-table=private_route
    add distance=2 gateway=wg-nordvpn@main routing-table=private_route
    /routing rule
    add action=lookup-only-in-table src-address=192.168.1.100/32 table=
    private_route

    TO:
    /ip route
    add dst-address=0.0.0.0/0 gateway=wg-nordvpn routing-table=private_route

    /routing rule
    add action=lookup-only-in-table dst-address=50.50.50.0/24 table=main
    add action=lookup-only-in-table src-address=50.50.50.0/24 table=private_route

  3. from:
    _/ip dhcp-server network
    add address=50.50.50.0/24 dns-server=1.1.1.1,1.0.0.1,9.9.9.9 gateway=_
    TO:
    /ip dhcp-server network
    add address=50.50.50.0/24 dns-server=103.86.96.100 gateway=50.50.50.1

  4. to ensure the router knows about this address…
    /ip route
    add dst-address=103.86.96.100 gateway=wg-nordvpn routing-table=main

  5. from:
    add action=accept chain=forward comment=“Allow VPN Traffic” out-interface=
    wg-nordvpn src-address-list=access_vpn

    TO:
    add action=accept chain=forward comment=“Allow VPN Traffic” out-interface=
    wg-nordvpn src-address=50.50.50.0/24

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

What is not clear to me, never having configured LTE is whether or not there is an option for
default route and default DNS in LTE settings etc… as there is no IP DHCP client etc.
You should let us know what you have done here ( but no public IP information or passwords etc..)

  1. Add
    /ip dns
    set server=1.1.1.1,9.9.9.9

  2. Finally, a discussion about black hole. My assessment is that you dont need one. I get the sense that you dont want the users on 50.50 to use the regular internet for traffic to the WWW.
    a. because the subnet is directed to wireguard table, via the routing rule, it will never go out main table. Normally one uses the action _lookup only in tabl_e to ensure this fact.
    However it is actually not necessary as the router has no way with wireguard protocol to know if the interface has gone down and is not available so it will never have to ask or answer the action question in the routing rule.
    To feel a bit more confident about that, firewall rules help to ensure there is no local wan traffic.
    So I would do something like.
    {FORWARD CHAIN}
    add action=fasttrack-connection chain=forward connection-state=established,related
    add action=accept chain=forward connection-state=established,related,untracked
    add action=drop chain=forward connection-state=invalid
    add action=accept chain=forward comment=“Subnet to wireguard” out-interface=wg-nordvpn src-address=50.50.50/0/24
    add action=drop chain=forward comment=“drop all else”

In this way the subnet has no access to the WAN out the LTE1.
You will note that we also have setup the users to use the provided DNS through the Tunnel and thus no leakage out LTE for dns requests by users.
To make this a little stronger one can
/ip firewall nat
add chain=dstnat action=dst-nat src-address=50.50.50.0/24 dst-port=53 protocol=udp to-address=103.86.96.100
add chain=dstnat action=dst-nat src-address=50.50.50.0/24 dst-port=53 protocol=tcp to-address=103.86.96.100

Love you brother <3. Im posting hastily cause it seems its working, im still at step 8.

Sorry for my newbie state but what exactly do you need about this one?

"What is not clear to me, never having configured LTE is whether or not there is an option for
default route and default DNS in LTE settings etc… as there is no IP DHCP client etc.
You should let us know what you have done here ( but no public IP information or passwords etc..) "

As for No.9, what i need - want is for web to stay all the time inside the tunnel in order to avoid any leakage. I dont ve anyone else on my router, its for private usage. The greek government strict few rules, so using vpn became mandatory. I added the firewall nat rules for udp and tcp on port 53. The only ones i didnt add still are those

add action=fasttrack-connection chain=forward connection-state=established,related
add action=accept chain=forward connection-state=established,related,untracked
add action=drop chain=forward connection-state=invalid
add action=accept chain=forward comment=“Subnet to wireguard” out-interface=wg-nordvpn src-address=50.50.50/0/24
add action=drop chain=forward comment=“drop all else”

Do you want me to add them as well? I want the net to be safe as possible. I really thank you, for your time, effort and how helpful and straight forward were your intructions <3

Yes, the rules provide good security and prevent leakage as you desire.
They only allow lan traffic out the wireguard tunnel.

As to the other question, just to confirm that you have a default route enabled in LTE settings.
I am assuming you do otherwise the tunnel could not be established.

For router security also recommend the following rules.
/ip firewall filter
{ input chain default rules to keep }
add action=accept chain=input connection-state=established,related,untracked
add action=drop chain=input connection-state=invalid
add action=accept chain=input protocol=icmp
add action=accept chain=input dst-address=127.0.0.1

(admin rules)
add action=accept chain=input in-interface=bridge-lan src-address=50.50.50.0/24
add action=drop chain=input comment="drop all else
" { insert this rule here, but last of all rules aka ensure the allow src address rule is in place prior }

NOTE: You do not need the wireguard rule on the input chain as there is not incoming handshake to your router being a peer client for handshake.
By the way the reason why we sourcenat the wireguard interface is so that all the users IP addresses are natted to the wireguard IP address assigned to you, as the far remote end is only expecting one source IP address to hit their server.

For this one, i got this error while trying to add

[admin@MikroTik] /ip/firewall/filter> add action=accept chain=forward comment=“Subnet
to wireguard” out-interface=wg-nordvpn src-address=50.50.50/0/24
value of range must have netmask after ‘/’ either as number or as ip value