Connecting to PIA using WireGuard on OPNsense

So I’ve been using PIA (Private Internet Access) as my VPN provider since 2014, over the years you could say they’ve had a bit of a bumpy road but nothing has come to light showing them giving out any logs/details to authorities, plus this has been tested twice in court to my knowledge and TorrentFreak talk about the second case on their blog. I’ve always connected to PIA via OpenVPN, which has worked well for many years and offering their service on different ports has also allowed me to get around the odd captive portal.

I’ve been running my own router in form of pfsense and in recent years OPNsense with OpenVPN connection to PIA to tunnel certain traffic as and when required. In the last year PIA announced their WireGuard service allowing users to now connect to their NextGen VPN servers using this latest VPN technology. You can read about how WireGuard works on their website. Since WireGuard is more performant, due to having less overheads plus each OS will eventually have a kernel module allowing even better performance over OpenVPN, than it may already have, allowing higher speeds, lower latency. Linux already has a kernel module, FreeBSD is also now having one developed but currently its not mature enough to be included in the FreeBSD source code. OPNsense currently uses the WireGuard-go implementation which is fast enough for my needs as my internet connection is only 50/5 (VDSL line) but I know of people getting 500/30 speeds over WireGuard-go on OPNsense no problem. I have no doubt once the kernel module is ready for FreeBSD, OPNsense will put this in to replace the go version.

So how do we connect OPNsense to PIA’s NextGen WireGuard VPN servers? So some VPN providers its very simple, you give your VPN provider your WireGuard public key, and then return they give you the connection details you require to connect to their WireGuard servers. When your a small VPN company this is very simple, since they have 16,777,214 IPs in the 10.0.0.0/8 IP range to play with, so after you take away a few thousand addresses for their management networks, still give them a lot of IPs they can permanently assign to their WireGuard users. Assuming they have servers just for serving WireGuard clients, the total number of addresses would be even smaller if they’re running OpenVPN on the same servers. So when your the size of PIA and each server hosts multiple VPN protocols and users have multiple devices, the issue of getting close to running out of IPs, which becomes a bit of an issue, if they are globally unique IPs. So PIA uses a different strategy to connect to their servers via WireGuard, they have an API on each VPN server, which you then ask for WireGuard connection details from, that allows you to connect to that one and only server. If you want to connect to another server you repeat this process again for another VPN server.

Since connecting to PIA’s WireGuard servers require an API, you need their client or script to do this process for you. PIA provide a github repo that contains manual connection scripts, that allows you to connect to their WireGuard servers without needing the official PIA client. So what we need is a OPNsense version of this script, so it can handle the API part of the connection process.

Now after a lot of searching it was very apparent such a script didn’t exist for OPNsense. I decided I would look in to getting a script created so I can take advantage of their WireGuard servers and if anyone else was interested in using PIA on OPNsense using WireGuard they too could do it. After a weekend of reading through the manual connections, talking to PIA staff in their IRC channel, I made this following script (Linked Below). I’ve iterated the script a little bit since I did my first commit to make sure any bugs were ironed out, it’s now pretty robust, unless your trying to do something special with it. The github repo contains a README of how to setup the script. It will take care of maintaining the connection to PIA and rotate servers when required. Just give the script some connection details and a region it’ll take care of the rest.

Repo: https://github.com/FingerlessGlov3s/OPNsensePIAWireguard

Hopefully others will find this script useful and I will keep it updated as and when required, if you get any issues or errors setting up the script don’t hesitate to open up an issue.

9 thoughts on “Connecting to PIA using WireGuard on OPNsense

  1. Tried to follow the instructions on the GitHub but getting timeout errors when I run:

    PIAWireguard.py debug

    I have the following:
    OPNsense version 22.1.7_1
    Python version 3.8

    ———- MESSAGES START ———-
    Traceback (most recent call last):
    File “/usr/local/lib/python3.8/site-packages/urllib3/connection.py”, line 174, in _new_conn
    conn = connection.create_connection(
    File “/usr/local/lib/python3.8/site-packages/urllib3/util/connection.py”, line 95, in create_connection
    raise err
    File “/usr/local/lib/python3.8/site-packages/urllib3/util/connection.py”, line 85, in create_connection
    sock.connect(sa)
    TimeoutError: [Errno 60] Operation timed out

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
    File “/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py”, line 703, in urlopen
    httplib_response = self._make_request(
    File “/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py”, line 386, in _make_request
    self._validate_conn(conn)
    File “/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py”, line 1040, in _validate_conn
    conn.connect()
    File “/usr/local/lib/python3.8/site-packages/urllib3/connection.py”, line 358, in connect
    self.sock = conn = self._new_conn()
    File “/usr/local/lib/python3.8/site-packages/urllib3/connection.py”, line 186, in _new_conn
    raise NewConnectionError(
    urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno 60] Operation timed out

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
    File “/usr/local/lib/python3.8/site-packages/requests/adapters.py”, line 440, in send
    resp = conn.urlopen(
    File “/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py”, line 785, in urlopen
    retries = retries.increment(
    File “/usr/local/lib/python3.8/site-packages/urllib3/util/retry.py”, line 592, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
    urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host=’127.0.0.1′, port=443): Max retries exceeded with url: /api/wireguard/server/searchServer/ (Caused by NewConnectionError(‘: Failed to establish a new connection: [Errno 60] Operation timed out’))

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
    File “/conf/PIAWireguard.py”, line 219, in
    r = requests.get(f'{opnsenseURL}/api/wireguard/server/searchServer/’, auth=(config[‘opnsenseKey’], config[‘opnsenseSecret’]), verify=urlVerify)
    File “/usr/local/lib/python3.8/site-packages/requests/api.py”, line 75, in get
    return request(‘get’, url, params=params, **kwargs)
    File “/usr/local/lib/python3.8/site-packages/requests/api.py”, line 61, in request
    return session.request(method=method, url=url, **kwargs)
    File “/usr/local/lib/python3.8/site-packages/requests/sessions.py”, line 529, in request
    resp = self.send(prep, **send_kwargs)
    File “/usr/local/lib/python3.8/site-packages/requests/sessions.py”, line 645, in send
    r = adapter.send(request, **kwargs)
    File “/usr/local/lib/python3.8/site-packages/requests/adapters.py”, line 519, in send
    raise ConnectionError(e, request=request)
    requests.exceptions.ConnectionError: HTTPSConnectionPool(host=’127.0.0.1′, port=443): Max retries exceeded with url: /api/wireguard/server/searchServer/ (Caused by NewConnectionError(‘: Failed to establish a new connection: [Errno 60] Operation timed out’))
    ———- MESSAGES END ———-

      1. That was it. I set the correct webui port number in the JSON config file and it worked like a charm!

        Now I have to get my firewall and NAT settings right.

        Thanks very much!

  2. Hi, thanks you for the script, i do not know how can i upload the script on the step 3, can you help me please?

  3. Hello, thank you for the hard work. It is much appreciated!
    While I did had this solution up and running last week, I cant seem to get working after upgrading OPNsense to 22.7.3_2. I’ve tried multiple servers, which all have the same results. I’m not sure out to resolve this cert issue (if that’s what this is). Please advise.
    Thanks again.

    GitHub Step 5:
    /conf/PIAWireguard.py debug

    Traceback (most recent call last):
    File “/usr/local/lib/python3.9/site-packages/urllib3/util/ssl_.py”, line 402, in ssl_wrap_socket
    context.load_verify_locations(ca_certs, ca_cert_dir, ca_cert_data)
    ssl.SSLError: [X509: NO_CERTIFICATE_OR_CRL_FOUND] no certificate or crl found (_ssl.c:4298)

    During handling of the above exception, another exception occurred:
    Traceback (most recent call last):
    File “/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py”, line 703, in urlopen
    httplib_response = self._make_request(
    File “/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py”, line 386, in _make_request
    self._validate_conn(conn)
    File “/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py”, line 1042, in _validate_conn
    conn.connect()
    File “/usr/local/lib/python3.9/site-packages/urllib3/connection.py”, line 414, in connect
    self.sock = ssl_wrap_socket(
    File “/usr/local/lib/python3.9/site-packages/urllib3/util/ssl_.py”, line 404, in ssl_wrap_socket
    raise SSLError(e)
    urllib3.exceptions.SSLError: [X509: NO_CERTIFICATE_OR_CRL_FOUND] no certificate or crl found (_ssl.c:4298)

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
    File “/usr/local/lib/python3.9/site-packages/requests/adapters.py”, line 489, in send
    resp = conn.urlopen(
    File “/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py”, line 787, in urlopen
    retries = retries.increment(
    File “/usr/local/lib/python3.9/site-packages/urllib3/util/retry.py”, line 592, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
    urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host=’vancouver412′, port=443): Max retries exceeded with url: /authv3/generateToken (Caused by SSLError(SSLError(136, ‘[X509: NO_CERTIFICATE_OR_CRL_FOUND] no certificate or crl found (_ssl.c:4298)’)))

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
    File “/conf/PIAWireguard.py”, line 551, in
    generateTokenResponse = requests.get(f”https://{piaMetaCn}/authv3/generateToken”, auth=(config[‘piaUsername’], config[‘piaPassword’]), verify=piaCA)
    File “/usr/local/lib/python3.9/site-packages/requests/api.py”, line 73, in get
    return request(“get”, url, params=params, **kwargs)
    File “/usr/local/lib/python3.9/site-packages/requests/api.py”, line 59, in request
    return session.request(method=method, url=url, **kwargs)
    File “/usr/local/lib/python3.9/site-packages/requests/sessions.py”, line 587, in request
    resp = self.send(prep, **send_kwargs)
    File “/usr/local/lib/python3.9/site-packages/requests/sessions.py”, line 701, in send
    r = adapter.send(request, **kwargs)
    File “/usr/local/lib/python3.9/site-packages/requests/adapters.py”, line 563, in send
    raise SSLError(e, request=request)
    requests.exceptions.SSLError: HTTPSConnectionPool(host=’vancouver412′, port=443): Max retries exceeded with url: /authv3/generateToken (Caused by SSLError(SSLError(136, ‘[X509: NO_CERTIFICATE_OR_CRL_FOUND] no certificate or crl found (_ssl.c:4298)’)))

    1. Hi Rich,

      Sounds like your missing some files, double check you’ve uploaded the `ca.rsa.4096.crt` which is used to verify the certificate of the VPN servers.

      1. Thank you for your response.
        Unfortunately, I do have the ca.rsa.4096.crt uploaded and still run into the same issue. I had purged everything and started over from the beginning but ended up in the same spot, with the error messages above.
        I am not sure how to to resolve this, so I am thinking about just standing up a new OPNsense device and starting from scratch. If that works, then maybe I can compare device until I find the difference which is causing this issue. Please let me know if you think of something else later on. I really do appreciate the work that you did on this, as I’m sure others do as well.
        Thanks again!

Leave a Reply

Your email address will not be published.