Link Search Menu Expand Document

WireGuard Private Internet Access

Thanks to and, this is how I made a whole subnet go out on the internet through a NordVPN WireGuard connection.

Table of contents
  1. Prerequisites
  2. Getting started
  3. Linux
    1. WireGuard
    2. NordLynx
    3. Private key
  4. OPNSense configuration
    1. WireGuard
      1. Local
      2. Endpoints
      3. General
    2. Assignments
  5. Gateways
  6. Rules
    1. Kill switch
  7. NAT
  8. DNS
  9. Troubleshooting
    1. DNS leaktest
    2. Public IP
    3. Recommended server
      1. 4 servers closest to you
      2. Display servers in specific country
      3. Display 4 servers with WG in specific country
  10. Authors
  11. Acknowledgments


  • OPNsense 20.7.8_4-amd64
  • Ubuntu 20.04
  • NordVPN user account

Getting started

Even though WireGuard requires static IPs, NordVPN has deviced a solution which makes this connection as secure as any other available protocol for both authentication and session data, namely double NAT’ing. Read more here:

We need to fetch our private key and the corresponding site’s public key. Since there are no documentation for 3rd party apps yet, we’ll have to use what is available to do this for now, using the linux cli, WireGuard itself and software from NordVPN.

Subnet which will travel through NordVPN WireGuard interface is - named 10_VPN.

WireGuard tunnel interface is named WG_NordVPN_FR.

NordVPN WireGuard gateway is GW_WG_NordVPN_FR.



Install WireGuard on a linux machine. Check tutorial here;

sudo apt install wireguard


Install NordVPN. Check tutorial here;

sudo sh <(curl -sSf

Check internet IP address before you start:


NordVPN login:

sudo nordvpn login
Please enter your login details.
Email / Username:

Welcome to NordVPN! You can now connect to VPN by using 'nordvpn connect'.

Change from default VPN protocol OpenVPN to NordLynx (WireGuard):

sudo nordvpn set technology NordLynx
Technology is successfully set to 'NordLynx'.

Connect with NordVPN:

sudo nordvpn connect
Connecting to France #111
You are connected to France #111 (!

You’ll notice that your public IP has changed.


After a successfull connection, figure out the IP scheme of this particular connection:

sudo wg
interface: nordlynx
  public key: UTZ4PHmX5zAOSvdhqp0Ed8q4z0OHgMk8ztalChHaPU=
  private key: (hidden)
  listening port: 39069
  fwmark: 0xca6c

peer: 21dz9Y6HFRzaXKLpFpcZHjcI5AJQopJW/JZShKjTKkZ=
  allowed ips:
  latest handshake: 39 seconds ago
  transfer: 3.09 KiB received, 3.46 KiB sent
  persistent keepalive: every 25 seconds

(These are not valid keys by the way).

What about tunnel address?

ip address show nordlynx
8: tun0: <POINTOPINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    inet scope global nordlynx
        valid_lft forever preferred_lft forever

Allright. Whats the opposite side’s address?

PING ( 56(84) bytes of data. 
64 bytes from icmp_seq=1 ttl=64 time=6.86 ms

Let’s assume this is the gateway address :)

Private key

Now, figure out which private key you have for your user:

sudo wg show nordlynx private-key

(This is not a valid key by the way).

Now you have everything you need. Your private key, your public key, servers public key, the endpoint address and the port.

OPNSense configuration

Allright, we have what we need to get things going regards to configuring our OPNsense firewall.



Add a server by pressing the little + icon


  • Enabled: [-]
  • Name: NordVPN
  • Public Key: insert public key from sudo wg : UTZ4PHmX5zAOSvdhqp0Ed8q4z0OHgMk8ztalChHaPU=)
  • Private Key: insert private key from sudo wg show nordlynx private-key : FSzJDH1171AJKldoqohndlakO3918djals/jkdjkfl0=
  • Listen Port: 51822 (use a random port which is not in use on the system)
  • DNS Server:, (
  • Tunnel Address: insert inet address from ip addr show nordlynx :
  • Peers: Nothing selected, leave blank for now
  • Disable Routes: Check
  • Gateway:

Click Save.


Create a new Endpoint by hitting the + icon. Here you will copy the information from the [peer] section from sudo wg.

  • Name:
  • Public Key: insert public key from sudo wg (21dz9Y6HFRzaXKLpFpcZHjcI5AJQopJW/JZShKjTKkZ=)
  • Shared Secret:
  • Allowed IPs:
  • Endpoint Address:
  • Endpoint Port: 51820
  • Keepalive: 25

Click Save.

Now, go back to Local. Select the NordVPN WireGuard instance. Hit Edit (the little pencil).

  • Under Peers, select the newly created peer.

Click Save.


[-] Enable WireGuard

Hit Save.

After you have selected Save- go to List Configuration.

Because of our persistent keepalive - you should see the received and sent transfer is steadily increasing. You’ll also notice you have a successfull Handshake with the specific interface whenever this is > 0 (wg0).


Now go to Interfaces > Assignments. You’ll have a new interface you can assign (wg0).

Assign this interface. After assignment, click the name of the interface (OPT5 or something similar).

[x] Enable Interface

  • Description: WAN_WG_NordVPN_FR

Leave rest of the configuration as is. Click Save.

Apply the changes.


Go System > Gateways Click +Add gateway.

  • Name: GW_WG_NordVPN_FR
  • Description: PIA through WG_NordVPN_FR
  • Interface: WG_NordVPN_FR

  • IP adress:

  • Far Gateway [x]

Set rest to default.

Click Save, Apply.


Go to Rules.

Select the designated interface for your subnet which you would like to go out on internet through this WireGuard VPN.

Add Rule.

Allow any any IPv4, but be sure to select

  • Gateway: GW_WG_NordVPN - as your gateway under Advanced settings.

While we are at it, do this to enable a kill-switch for your traffic should the WireGuard interface go down:

  • Set local tag: NO_WAN_EGRESS

Click Add.

Add another rule on the same interface, but this time - make sure to select Block. Leave the rest as default. This will be our “kill switch”. Make sure the reject rule is below the allow rule.

Kill switch

Firewall > Rules > Floating > +Add

  • Action: Block
  • Interface: WAN
  • Direction: out
  • Description: NO_WAN_EGRESS match
  • Match local tag: NO_WAN_EGRESS


Firewall > NAT > Outbound Select Hybrid outbound NAT rule generation. Click Save and Apply Rules.

Then click +Add.

Interface: WG_NordVPN_FR Source adress: 10_VPN net Translation / target: Interface address Description: 10_VPN to WG_NordVPN_FR

Save. Apply changes.


Let us provide some security regards to DNS leaks on this 10_VPN interface of ours.

Services > DHCPv4

  • 10_VPN

Add DNS servers provided by NordVPN here, so that DHCP offers DNS servers provided by NordVPN:

  • DNS servers :,

If you have devices that have hardcoded DNS servers, you want to redirect those requests to NordVPN’ DNS servers. We’ll define an ALIAS and use NAT port forwarding to achieve this.

Firewall > Aliases. Hit the + icon.

  • Type: Host(s)
  • Content:,
  • Description: NordVPN DNS servers

Now, go to Firewall > NAT > Port Forward.


  • Interface: 10_VPN
  • Protocol: TPC / UDP
  • Source: 10_VPN net
  • Destination / Invert: checked
  • Destination: ALIAS_HOSTS_NordVPN_DNS
  • Destination port range: DNS
  • Redirect target IP: ALIAS_HOSTS_NordVPN_DNS
  • Redirect target port: DNS


DNS leaktest

resolvectl | grep 'DNS'

Current DNS Server:

Download from


Your IP: [France BE1800 K19]

You use 1 DNS server: [France BE1800 K19]

Public IP

Are you connected through a VPN?


Make sure you have curl and jq installed. curl is used to transfer data from a server and jq is a lightweight and flexible command-line JSON processor.

sudo apt install jq curl

4 servers closest to you

After installation, enter the command below to fetch the 4 recommended servers closest to you, with support for WireGuard:

curl -s "\[servers_technologies\]\[identifier\]=wireguard_udp&limit=4"|jq -r '.[]|.hostname, .station, (.locations|.[]|.country|, (.locations|.[]|.country|.name), (.technologies|.[].metadata|.[].value), .load' #your endpoint host #its ip address
Paris #city
France #country
K19dhzkuUGsQkosdahaDKjall18/00idianhkplaUJkmk= #Server public key
15 #Server load at the time.


Display servers in specific country

Bosnia and Herzegovina:

curl --silent | jq --raw-output '.[] | select(.country == "Bosnia and Herzegovina") | .domain'

Display the country ID:

curl --silent "" | jq --raw-output '.[] | select(.name == "Bosnia and Herzegovina") | [.name, .id] | "ID for \(.[0]) is \(.[1])"'

Display 4 servers with WG in specific country

curl -s "\[servers_technologies\]\[identifier\]=wireguard_udp&filters\[country_id\]=209&limit=4"|jq -r '.[]|.hostname, .station, (.locations|.[]|.country|, (.locations|.[]|.country|.name), (.technologies|.[].metadata|.[].value), .load'


Mr. Johnson