This script automates the process of setting up a Wireguard Point-To-Point VPN tunnel on OPNsense to connect to PIA's NextGen Wireguard servers.
It will create a Wireguard Instance and a Peer on your OPNsense deployment automatically. It will then maintain the tunnel to keep it up and connected, with an automated check every 5 minutes.
You can also create a CRON job, allowing you to manually change the PIA server you are connected to.
Warning: This is for Advanced Users
- OPNsense 23.7.10 or later
- WireGuard Plugin Installed
- HTTPS WebUI enabled
System: Settings: Administration -> Web GUI
Protocol: HTTPS
- Secure Shell Access enabled (This can be reverted once the tunnel is working.)
System: Settings: Administration -> Secure Shell
Enable Secure Shell
Permit root user login
Permit password login
If an older version of the script is already installed, jump to the Updating section
- Create a new user called something on the lines of "WireguardAPI"
- Go to
System: Access: Users
- Click the
Plus
(Add) on the top right - Username:
WireguardAPI
- Password: leave empty
- Tick
Generate a scrambled password to prevent local database logins for this user.
- Scroll to the bottom and click
Save
- Go to
- Now that the user is created we can give it permissions and generate an API key pair
- Scroll down to you see
Effective Privileges
, you want to give it the following permissions:Firewall: Alias: Edit
Firewall: Aliases
System: Static Routes
VPN: Wireguard
- Click the
Plus
sign onAPI Keys
, it'll download the keys in a txt file. We'll leverage this later. - Click
Save
- Scroll down to you see
- SSH to OPNsense and drop in to a terminal via
option 8
. - As
root
, run the below commands:fetch -o /conf https://raw.githubusercontent.com/FingerlessGlov3s/OPNsensePIAWireguard/main/PIAWireguard.py
fetch -o /conf https://raw.githubusercontent.com/FingerlessGlov3s/OPNsensePIAWireguard/main/ca.rsa.4096.crt
fetch -o /usr/local/opnsense/service/conf/actions.d https://raw.githubusercontent.com/FingerlessGlov3s/OPNsensePIAWireguard/main/actions_piawireguard.conf
- Download the latest Release from GitHub to your computer, to ensure it's a stable release
- Edit the
PIAWireguard.json
file using Notepad++ or your favourite IDE.- The following variables need to be filled in:
opnsenseURL
Should only need to change this if you use a differentTCP Port
for the WebUI or changed theListen Interfaces
, the provided URL is correct if you've left those unchanged.opnsenseKey
WireguardAPI key you downloaded from step 2.2apikeys.txt
opnsenseSecret
WireguardAPI secret you downloaded from step 2.2apikeys.txt
piaUsername
Your PIA usernamepiaPassword
Your PIA passwordinstances
As we support creation of multiple tunnels, Example config has one instance but you can have as many as you like. Theinstances
are key value pairs. Changeinstancename
to something likelondon
if you using theuk
region since but the instance name can be what you'd like it to be.regionId
Change to your PIA region id (see below for details)portForward
Enable port forwarding (note region support required)opnsenseWGPort
outgoing port for OPNsense, this needs to be different for each tunnel and not already be in use for something else on OPNsense
- Region ID info
- You can get your PIA region id by running
ListRegions.py
on your local device. - If you don't have Python installed on your local device you can use this Online Python Tool
- Copy the contents of the file and then click
Run
. This will list the name and region id of each PIA region, for you choose from.
- Copy the contents of the file and then click
- It is also possible to get PIA region ids running the main script using the argument
--listregions
- You can get your PIA region id by running
- The following variables need to be filled in:
- Copy the
PIAWireguard.json
file to/conf/
on your OPNsense router using SCP or Filezilla etc, make sure you using the root user of OPNsense when you connect, otherwise you'll get access denied messages.- Example
scp .\PIAWireguard.json [email protected]:/conf/PIAWireguard.json
- Example
- SSH to OPNsense and drop in to a terminal
option 8
. (If you've closed the previous SSH connection.) - Run the following commands
- Enable the file to be executed:
chmod +x /conf/PIAWireguard.py
- Restarted the service:
service configd restart
- Execute the script, in debug mode with output:
/conf/PIAWireguard.py --debug
- Enable the file to be executed:
- Go to Interfaces: Assignments in OPNsense, so we can assign the new interface for the tunnel/tunnels
- At the bottom of the interfaces you'll see
New interface
, on the drop down selectwg0
, unless you already had one set up then selectwg1
etc... - Give it a description like
WAN_PIAWG
- Once selected click the
+
button - A new
WAN_PIAWG_INSTANCENAME
interface will show on the list, which will be the new wg interface, click on it to edit. - Tick
Enable Interface
, click save and Apply Changes. nothing else
- At the bottom of the interfaces you'll see
- Go to
System: Gateways: Single
, so we can set up the PIA gateway for the tunnel/tunnels- At the bottom right click the
+
button to add a new gateway - Make sure
Disabled
is unchecked - Enter the name
WAN_PIA_INSTANCENAME_IPv4
- Interface select
WAN_PIAWG_INSTANCENAME
- Tick
Far Gateway
- Untick
Disable Gateway Monitoring
- Click
Save and Apply Changes
- At the bottom right click the
- Also reccomended you set your Main gateway to have a lower Priority number than the created ones for the PIA tunnel
- Go back to the SSH terminal, run the following command
/conf/PIAWireguard.py --debug --changeserver instancename
- Now OPNsense should be setup to use the PIA VPN tunnel as an internet gateway. If you go back in to
System: Gateways: Single
, you should seeWAN_PIA_INSTANCENAME_IPv4
now has a gateway IP and is pinging - Now we need to set up a cron job to make sure the tunnel says up, and changes server when necessary. Go to System: Settings: Cron
- Click the
plus
button at the bottom right of the table - Enter
*/5
in the minute box - Enter
*
in the hours box - Select
PIA WireGuard Monitor Tunnels
on the command dropdown - Give it a Description of your choice.
- Click Save
- Click the
- Last thing we need to set up is maximum MSS for TCP packets, which is 40 bytes smaller than the MTU of WireGuard. By default Wireguard uses 1420 bytes MTU. So we need to set an MSS maximum of 1380. (Without this you may have issues loading websites or slow speeds).
- Goto
Firewall: Settings: Normalization
- Click
Add
- Interface select
WAN_PIA_INSTANCENAME_IPv4
- Enter Description of
Maximum MSS for PIA WireGuard Tunnel
- Max MSS to
1380
- Click
Save
(you will notice it'll now list this as OPT rather than the interface name, don't worry it's still correct, just edit it to verify you made the right selection) - Click
Apply Changes
- Goto
- OPNsense should now look after the tunnel itself encase the tunnel disconnects, every 5 minutes it'll check the status and change server if the server has gone down.
- You'll need to create your own NAT and Firewall rules to use this tunnel, an advanced user should be able to do this.
- There is now a guide on OPNsense Docs, which will help you here. Step 7 onwards.
Note: If your having speed issues, you may need to change PIA server region or lower the default MTU from 1420, advanced users should understand how to do this.
Since 2024/01/05 the script has gone a complete overhaul. The major change is the script is now able to handle multiple instances of the tunnel. IE you can establish connections to multiple regions.
The main impact, is that our InstanceName needs to be unique since we'll have multiple instances.
{instancename}
is replaced with the name for your specific instance in the config file, examplelondon
would be comepia-london
for the WireGuard instance name. See Example config below.
Update Steps:
- Delete the current cron entry.
- Populate the new
PIAWireguard.json
based on your old config file - Upload new
PIAWireguard.py
andPIAWireguard.json
file to/conf/
- Upload new
actions_piawireguard.conf
file to/usr/local/opnsense/service/conf/actions.d/
- Run
service configd restart
to refresh new actions file via SSH - There's a few bits in the WireGuard section in OPNsense you need to rename
- Rename current WG instance name to
pia-{instancename}
fromPIA
- Rename current WG peer to
pia-{instancename}-server
fromPIA-Server
- Rename current WG instance name to
- If your using port forwarding rename the alias to
pia_{instancename}_port
fromPIA_Port
- Ensure you applied all changes
- Run the new script via SSH in debug mode and ensure it's working
python3 PIAWireguard.py --debug
, should returninstancename tunnel up - last handshake x seconds ago
as the last log entry - Then run again but this time forcing a it to change server
python3 PIAWireguard.py --debug --changeserver instancename
, to ensure all changes will apply and work. - If all is working correctly, then re-create the cron entry, see above for example as command name changed to
PIA WireGuard Monitor Tunnels
- Now double check all your configured routes and rules, ensure IP leaking isn't happening etc
See releases, starting from the version you have installed, to see if there's anything you need to do, usually it's just upgrade the py script itself. Release description will have the required commands, and notes for upgrading.
Example config
{
"opnsenseURL": "https://127.0.0.1:443",
"opnsenseKey": "/FQDXExojUWWuBdnPEPCUt98vnrQOdLxFqypTIEhE41304uYgA68ZJw7fveXBpXkMHqiAdx04cRAlLwh",
"opnsenseSecret": "p+Gi4uE1xypuGIptbhrDylGKcNd9vaRpQ298eH0k6SFRQ6Crw4fLk0cIA0eSuKvWEN0hKx8JaIGUtNPq",
"piaUsername": "p1234567",
"piaPassword": "EncryptAllTheThings",
"tunnelGateway": null,
"opnsenseWGPrefixName": "pia",
"instances": {
"london": {
"regionId": "uk",
"dipToken": "",
"dip": false,
"portForward": true,
"opnsenseWGPort": "51815"
}
}
}
Note: Passwords and keys in the example are not real
You may list the arguments you can pass in to the script by doing the following "/conf/PIAWireguard.py --help` an example output is below.
usage: PIAWireguard.py [-h] [--debug] [--listregions] [--changeserver [instancename]]
Python script to automate connections to PIA's WireGuard Servers. Source:
https://github.com/FingerlessGlov3s/OPNsensePIAWireguard
optional arguments:
-h, --help show this help message and exit
--debug Enable debug logging
--listregions List available regions and their properties
--changeserver [instancename]
Change server for instance name or "all" for all instances
--debug
shows debug logging, to see what the script is doing or maybe not doing
--listregions
lists all of the available PIA regions
--changeserver [instancename]
allows you to rotate/change the server your connected to for that instance. \
Example: /conf/PIAWireguard.py --debug --changeserver instance2
will change the server that instance2 is connecting too and print all debug messages.
To use port forwarding Enable portForward
variable in the json file for the intance from false
to true
. This will create an alias in your system called pia_instancename_port
, which you can then use in your Port Forwarding rule. This alias will self update when required.
If you need a way to find out this port for an internal application, you can go to the following URL of your OPNsense to get the port, as its published publicly to devices that can reach the HTTPS port of OPNsense
https://opnsense.lan/wg0_port.txt
Note: Not all server locations support port forwarding.
If you have purchased a Dedicated IP from PIA. Add your DIP token to dipToken
in the json file for the instance, then to enable the usage simply set dip
to true
. Remember PIA only give you the DIP token once, so make sure you have backed up the token somewhere.
I have developed this functionality by reserve engineering the PIA client, at this moment in time manual connections for DIP is not offically supported by PIA.
Note: I have not tested DIP in a while, so if this works for you let me know, if not create a GitHub issue.
In some deployments, people may be running dual or even triple WAN configurations, in this case due to how WireGuard is configured in FreeBSD (OPNsense), it'll route the PIA tunnel over the default WAN interface. Some people will want to change this to use another WAN interface as the gateway to route the PIA tunnel over.
To accommodate this functionality, this is built in to the script. You will need to get the name of your wanted gateway, for example WAN2_DHCP
, then set this as the tunnelGateway
variable value in the json file (value needs to be in double quotes). When the script then runs it'll add/change a static route to enforce the PIA tunnel to use that gateway (interface).
You'll find your gateway names in System: Gateways: Single
, making sure its the IPv4 one.
You will find that if the VPN tunnel isn't up, that traffic that should flow over it, will instead head straight out your WAN interface. You can setup a "VPN Kill Switch" to prevent this.
Firewall - Rules - WAN
- Create a new rule
Action - Block
Quick - Apply the action immediately on match
Interface - WAN
Direction - Out
Description - "Don't let traffic headed for VPN out the WAN"
Match local tag = NO_WAN_EGRESS
- Save this rule
- Repeat for other WAN interfaces, if you have a dual WAN setup, for most people this is not needed.
Firewall - Rules - LAN
(Or whatever interface has VPN rules)- Edit the rule where the gateway is the VPN tunnel
- Click
Advanced features Show/Hide
- Under
Set local tag
add inNO_WAN_EGRESS
- Save this rule
WireGuard
is a registered trademarks of Jason A. Donenfeld.
Private Internet Access
is owned by Private Internet Access, Inc. All Rights Reserved