Compare commits

...

52 Commits

Author SHA1 Message Date
RoboMagus e956c57849
Add: Option to only generate WG config file (#171)
See #171.
2023-02-06 12:45:34 +01:00
Joel Elkins e37693326d
Add jdelkins/pia-tools to list of 3rd party repos (#167) 2022-12-09 15:54:56 +01:00
kp-dragos-neagu 203fd68b75
Merge pull request #165 from faireOwl/master
Integration of One-Line Call for DIP
2022-08-30 09:35:56 +03:00
faireOwl 4e5714ecc5 Integration of One-Line Call for DIP
Integrated one-line call support for DIP_TOKEN=none

Fixed formatting issue introduced by longer server names of new servers

Fixed spacing to normalize output in all conditions

Updated readme to provide details about new one-line call example
2022-08-26 10:21:52 -05:00
faireOwl 9b42ad934a
Add: DIP Support (#159)
* Provision of DIP Support

Added dedicated IP support, including DIP_TOKEN for one-line calls and prompts through run_setup.sh.

Adjusted package dependency response for wireguard to list the necessary package (wireguard-tools) to utilize wg-quick.

Updated README.md to clarify package dependencies and include DIP_TOKEN.
2022-08-23 11:59:02 +02:00
gheorghe c7336e9e03 on wireguard switch back to 0.0.0.0/0 from 0.0.0.0/1, 128.0.0.0/1, as this is blocking connections on some devices 2022-02-20 13:53:02 +02:00
gheorghe 9ee75c4df1 fixed merge conflict on README.md 2022-02-19 04:06:29 +02:00
a1346054 2eaa262bbe make color definitions portable 2022-02-19 04:01:13 +02:00
a1346054 7d85dae095 move variable to the right place and use it 2022-02-19 04:01:13 +02:00
a1346054 775284eacb add color, just like for openvpn 2022-02-19 04:01:13 +02:00
a1346054 a5bd8532be unify quoting style for echo 2022-02-19 04:01:13 +02:00
a1346054 a534a3cc5f fix conditionals 2022-02-19 04:01:13 +02:00
a1346054 f47b320a4a use modern shell syntax and fix various warnings
This unifies the codestyle across all shell scripts, and fixes many
warnings reported through shellcheck. Additionally, it improves
readability for everyone wishing to see what is actually going on.
2022-02-19 04:01:13 +02:00
a1346054 27ed048374 fix spelling 2022-02-19 04:01:13 +02:00
a1346054 e2b9b733af use proper check for root privileges
The root user is not guaranteed to be named 'root'
2022-02-19 04:01:13 +02:00
T. Nowah f5653e2ed9 updated AllowedIPs to fix iptables errors 2022-02-19 03:32:12 +02:00
Doug 448502d767 Added powershell variant link 2022-02-19 03:23:58 +02:00
FingerlessGloves d65feb7def Update OPNsense script Scope to include DIP
Update OPNsense script now supports DIP (Dedicated IPs), so this commit is simply to advertise that fact.
2021-12-28 06:05:34 +02:00
g00n1x b89d7e0382 use www.privateinternetaccess.com instead of privateinternetaccess.com 2021-10-11 14:41:34 +03:00
Valery Kalesnik b04be889f0 Address some shellcheck reported issues 2021-09-12 20:19:21 +03:00
gunix 6d06b31af1 fix typo on readme 2021-09-12 14:29:32 +03:00
gunix b8f4116b2d add PowerShell scripts to README in the 3rd party section 2021-09-12 14:28:46 +03:00
John Parton 1e44d65aab Replace #!/bin/bash shebang with #!/usr/bin/env bash 2021-09-12 14:21:00 +03:00
g00n1x e7d4806a9e use the new v6 serverlist 2021-08-02 16:56:41 +03:00
goonix 1898303f44
add NetworkManager-GUI-Support to the 3rd party section of the readme 2021-06-30 22:15:13 +03:00
Derek Battams 24deb12c74
Add link to piawgcli project (#115) 2021-05-18 16:52:07 +03:00
Michael Moon 804b71f01e
Append triffid/pia-wg to 3rd party repository table (#111)
* Append triffid/pia-wg to 3rd party repository table
2021-04-20 23:14:31 +03:00
Derek Battams 912d606c50
Update my 3rd party repo (#104)
Since pfSense now supports WireGuard directly, Slugger has pivoted his efforts to a pfSense specific solution for PIA + WireGuard.
2021-03-27 13:26:55 +02:00
janranz dd381a35d5 Update README.md to adjust headers / typos
Minor adjustments to capitalization (for consistency), as well as adjusted spelling.
2021-02-21 02:55:50 +02:00
faireOwl 2e29ad2d8d Added notification about PF requirements
Added notification about requirements of PF to maintain an active script, and the refresh time to be expected.
2021-01-26 23:34:42 +02:00
faireOwl b8cb2c3684 Normalize spacing
Added a few \n to echos for invalid input notifications, normalizing spacing.
2021-01-26 21:40:20 +02:00
gunix 42db36b7c1 adding faireOwl to the readme as github somehow didn't show him as contributor though he worked a lot on this repo 2021-01-22 02:06:59 +02:00
gunix 742a492eee Region Selection and Other Improvements
- separated get_region and get_token into two separate scripts, allowing for independent calls to each if desired; this also allows the implementation of other features mentioned below
- implemented use of new centralized authentication server for easier automation; the new API is  located at https://privateinternetaccess.com/gtoken/generateToken
- added server selection capabilities to run_setup.sh, as requested by multiple users
- added one-line call capabilities to run_setup.sh to allow easy automation
- changed PIA_AUTOCONNECT to VPN_PROTOCOL for clarity
- added AUTOCONNECT for one-line calls
- added PREFERRED_REGION for one-line calls
- added colored output to highlight important details
- added input validation for prompts in run_setup.sh
2021-01-22 01:12:23 +02:00
Derek Battams d2d24808b5 Add 3rd party repo: piawgmgr 2020-12-14 20:24:00 +02:00
Zachary Murray b355c4c665 Fix unescaped quotes in manual debug curl command 2020-11-24 03:21:44 +02:00
g00n1x cb51b0b79e multiple README improvements, including a list of 3rd party repos 2020-11-15 03:57:02 +02:00
Saverio Miroddi 338ca1ac42
Check if IPv6 got disabled via kernel parameter before trying to disable it 2020-11-14 23:47:22 +02:00
Saverio Miroddi 3814d4be97 Fix a typo in the README 2020-11-14 17:21:09 +02:00
Saverio Miroddi 69dd8154ce Make the OpenVPN credentials file readable only by root
It previously was world-readable (0644 permissions).
2020-11-14 17:20:33 +02:00
gertjanal f312938435 Fix typo bellow to below 2020-11-12 21:01:06 +02:00
goonix d4b04701a5
Merge pull request #34 from lofidevops/pureos
Confirmed that it works on PureOS amber with Librem One token
2020-11-02 23:14:54 +02:00
David 2e53430904 Add PureOS amber.
Signed-off-by: David <david@librem.one>
2020-11-02 20:35:06 +00:00
gunix 88b44a4b76 fixed #32 2020-11-02 01:47:31 +02:00
gunix d85aaf34df Updated the readme to better reflect the distributions that are currently supported. 2020-11-01 18:37:20 +02:00
iPherian 58f7ed3ad2
Detect interfaces on multiple distributions (fixes #25)
This modification will allow users that use specific distributions (example: Ubuntu 18.04) to use the OpenVPN scripts without getting any strange behavior on interface detection.
2020-11-01 14:14:51 +02:00
gunix 82ebed7c9c #22 fixed 2020-10-23 00:27:09 +03:00
gunix 44bab04ea1 do not stop OpenVPN script if the PIA_PF is missing; also inform the user he needs PIA_TOKEN to run OpenVPN 2020-10-17 04:09:58 +03:00
faireOwl 24c7733c14 Added a 25 second keepalive to keep the NAT active on firewalls. 2020-10-13 20:45:01 +03:00
nurupo 7a76a24a76
Small fixes (#16)
A lot of typo fixes.
2020-10-12 22:49:40 +03:00
gunix 3e2091e009 #15 fixed 2020-10-12 14:38:52 +03:00
gunix 366f132d1e added support for OpenVPN 2020-10-09 23:11:51 +03:00
bub 8d7b921c28
remove deprecated use of xargs -i for better compatibility 2020-10-03 13:39:34 +03:00
15 changed files with 1712 additions and 339 deletions

131
README.md
View File

@ -1,63 +1,118 @@
# Manual PIA VPN Connections
__This project is "Work in Progress"__
This repository contains documentation on how to create native WireGuard connections to our __NextGen network__, and also on how to enable Port Forwarding in case you require this feature. Documentation on OpenVPN will follow soon enough.
This repository contains documentation on how to create native WireGuard and OpenVPN connections, and also on how to enable Port Forwarding in case you require this feature. You will find a lot of information below. However if you prefer quick test, here is the __TL/DR__:
You will find a lot of information bellow. However if you prefer a hands-on approach, here is the __TL/DR__:
* clone this repo: `git clone https://github.com/pia-foss/manual-connections.git`
* use `get_region_and_token.sh` to get the best region and a token
* use `connect_to_wireguard_with_token.sh` to create a WireGuard connection with/without PF
Here is a oneliner example:
```
sudo PIA_AUTOCONNECT=wireguard PIA_USER=p0123456 PIA_PASS=xxxxxxxxxx ./get_region_and_token.sh
git clone https://github.com/pia-foss/manual-connections.git
cd manual-connections
sudo ./run_setup.sh
```
### Dependencies
The scripts were written so that they are easy to read and to modify. The code also has a lot of comments, so that you find all the information you might need. We hope you will enjoy forking the repo and customizing the scripts for your setup!
## Table of Contents
- [Dependencies](#dependencies)
- [Disclaimers](#disclaimers)
- [Confirmed distributions](#confirmed-distributions)
- [3rd Party Repositories](#3rd-party-repositories)
- [PIA Port Forwarding](#pia-port-forwarding)
- [Automated setup](#automated-setup)
- [Manual PF testing](#manual-pf-testing)
- [Thanks](#thanks)
- [License](#license)
## Dependencies
In order for the scripts to work (probably even if you do a manual setup), you will need the following packages:
* `curl`
* `jq`
* (only for WireGuard) `wireguard-tools` and wireguard kernel module
* (only for OpenVPN) `openvpn` (however the script is not available yet)
* (only for WireGuard) `wireguard-tools` (`wg-quick` and `wireguard` kernel module)
* (only for OpenVPN) `openvpn`
### Confirmed systems and distributions
## Disclaimers
* Port Forwarding is disabled on server-side in the United States.
* These scripts do not enforce IPv6 or DNS settings, so that you have the freedom to configure your setup the way you desire it to work. This means you should have good understanding of VPN and cybersecurity in order to properly configure your setup.
* For battle-tested security, please use the official PIA App, as it was designed to protect you in all scenarios.
* This repo is really fresh at this moment, so please take into consideration the fact that you will probably be one of the first users that use the scripts.
* Though we support research of open source technologies, we can not provide official support for all FOSS platforms, as there are simply too many platforms (which is a good thing). That is why we link 3rd Party repos in this README. We can not guarantee the quality of the code in the 3rd Party Repos, so use them only if you understand the risks.
## Confirmed Distributions
The functionality of the scripts within this repository has been tested and confirmed on the following operating systems and GNU/Linux distributions:
* Arch
* Artix
* Fedora 32
* FreeBSD 12.1
* Ubuntu 20.04
* Fedora 32, 33
* FreeBSD 12.1 (tweaks are required)
* Manjaro
* PureOS amber
* Raspberry Pi OS 2020-08-20
* Ubuntu 18.04, 20.04
### Disclaimers
## 3rd Party Repositories
* Port Forwarding is disabled on server-side in the United States.
* These scripts do not touch IPv6 or DNS, so that you have the freedom to configure your setup the way you desire it to work. This means you should have good understanding of VPN and cybersecurity in order to properly configure your setup.
* For battle-tested security, please use the official PIA App, as it was designed to protect you in all scenarios.
* This repo is really fresh at this moment, so please take into consideration the fact that you will probably be one of the first users that use the scripts.
Some users have created their own repositories for manual connections, based on the information they found within this repository. We can not guarantee the quality of the code found within these 3rd party repos, but we can create a centralized list so it's easy for you to find repos contain scripts to enable PIA services for your system.
| System | Fork | Language | Scope | Repository |
|:-:|:-:|:-:|:-:|-|
| FreeBSD | Yes | Bash | Compatibility | [glorious1/manual-connections](https://github.com/glorious1/manual-connections) |
| Linux | No | Bash | NetworkManager <br> GUI integration | [ThePowerTool/PIA-NetworkManager-GUI-Support](https://github.com/ThePowerTool/PIA-NetworkManager-GUI-Support) |
| Linux | No | Python | WireGuard, PF | [milahu/python-piavpn](https://github.com/milahu/python-piavpn) |
| Linux | No | Bash | WireGuard, PF,<br/>router and android config | [triffid/pia-wg](https://github.com/triffid/pia-wg) |
| Linux | No | Go | WireGuard via systemd-networkd, PF | [jdelkins/pia-tools](https://github.com/jdelkins/pia-tools) |
| Linux/FreeBSD/Win | No | Go | WireGuard,<br />config generation | [ddb_db/piawgcli](https://gitlab.com/ddb_db/piawgcli) |
| OPNsense | No | Python | WireGuard, PF, DIP | [FingerlessGlov3s/OPNsensePIAWireguard](https://github.com/FingerlessGlov3s/OPNsensePIAWireguard) |
| pfSense | No | Sh | OpenVPN, PF | [fm407/PIA-NextGen-PortForwarding](https://github.com/fm407/PIA-NextGen-PortForwarding) |
| pfSense | No | Java/PHP | WireGuard, PF | [ddb_db/pfpiamgr](https://gitlab.com/ddb_db/pfpiamgr) |
| Synology | Yes | Bash | Compatibility | [steff2632/manual-connections](https://github.com/steff2632/manual-connections) |
| Synology | No | Python | PF | [stmty9/synology](https://github.com/stmty9/synology) |
| TrueNAS | No | Bash | PF | [dak180/TrueNAS-Scripts](https://github.com/dak180/TrueNAS-Scripts/blob/master/pia-port-forward.sh) |
| UFW | Yes | Bash | Firewall Rules | [iPherian/manual-connections](https://github.com/iPherian/manual-connections) |
| Windows | No | PowerShell | Windows comptaibility | [ImjuzCY/pia-posh](https://github.com/ImjuzCY/pia-posh) |
| Windows | No | Powershell | OpenVPN, PF | [dougbenham/PIA-OpenVPN-Script](https://github.com/dougbenham/PIA-OpenVPN-Script) |
## PIA Port Forwarding
The PIA Port Forwarding service (a.k.a. PF) allows you run services on your own devices, and expose them to the internet by using the PIA VPN Network. The easiest way to set this up is by using a native PIA aplications. In case you require port forwarding on native clients, please follow this documentation in order to enable port forwarding for your VPN connection.
The PIA Port Forwarding service (a.k.a. PF) allows you run services on your own devices, and expose them to the internet by using the PIA VPN Network. The easiest way to set this up is by using a native PIA application. In case you require port forwarding on native clients, please follow this documentation in order to enable port forwarding for your VPN connection.
This service can be used only AFTER establishing a VPN connection.
## Automated setup of VPN and/or PF
## Automated Setup
In order to help you use VPN services and PF on any device, we have prepare a few bash scripts that should help you through the process of setting everything up. The scripts also contain a lot of comments, just in case you require detailed information regarding how the technology works.
In order to help you use VPN services and PF on any device, we have prepared a few bash scripts that should help you through the process of setting everything up. The scripts also contain a lot of comments, just in case you require detailed information regarding how the technology works. The functionality is controlled via environment variables, so that you have an easy time automating your setup.
The easiest way to trigger a fully automated connection is by running this oneliner:
```
sudo VPN_PROTOCOL=wireguard DISABLE_IPV6=yes DIP_TOKEN=no AUTOCONNECT=true PIA_PF=false PIA_DNS=true PIA_USER=p0123456 PIA_PASS=xxxxxxxx ./run_setup.sh
```
Here is a list of scripts you could find useful:
* [Get the best region and a token](get_region_and_token.sh): This script helps you to get the best region and also to get a token for VPN authentication. The script will extend it's functionality if you add extra environment variables. Adding your PIA credentials will allow the script to also get a VPN token. The script can also trigger the WireGuard script to create a connection, if you specify `PIA_AUTOCONNECT=wireguard`.
* [Connect to WireGuard](connect_to_wireguard_with_token.sh): This script allow you to connect to the VPN server via WireGuard. You can specify `PIA_PF=true` if you also wish to get Port Forwarding for your connection.
* Connect to OpenVPN: We are still working on this script.
* [Enable Port Forwarding](port_forwarding.sh): Enables you to add Port Forwarding to an existing VPN connection.
* [Prompt based connection](run_setup.sh): This script allows connections with a one-line call, or will prompt for any missing or invalid variables. Variables available for one-line calls include:
* `PIA_USER` - your PIA username
* `PIA_PASS` - your PIA password
* `DIP_TOKEN` - your PIA dedicated IP token (can be purchased in the client control panel)
* `PIA_DNS` - true/false
* `PIA_PF` - true/false
* `PIA_CONNECT` - true/false; connect to VPN after configuration has been created. Set to false to only create configuration file. Only effective for wireguard protocol. Default true.
* `PIA_CONF_PATH` - path of wireguard config file to be written. Used when only creating config file for wireguard.
* `MAX_LATENCY` - numeric value, in seconds
* `AUTOCONNECT` - true/false; this will test for and select the server with the lowest latency, it will override PREFERRED_REGION
* `PREFERRED_REGION` - the region ID for a PIA server
* `VPN_PROTOCOL` - wireguard or openvpn; openvpn will default to openvpn_udp_standard, but can also specify openvpn_tcp/udp_standad/strong
* `DISABLE_IPV6` - yes/no
* [Get region details](get_region.sh): This script will provide server details, validate `PREFERRED_REGION` input, and can determine the lowest latency location. The script can also trigger VPN connections, if you specify `VPN_PROTOCOL=wireguard` or `VPN_PROTOCOL=openvpn`; doing so requires a token. This script can reference `get_token.sh` with use of `PIA_USER` and `PIA_PASS`. If called without specifying `PREFERRED_REGION` this script writes a list of servers within lower than `MAX_LATENCY` to a `/opt/piavpn-manual/latencyList` for reference.
* [Get a token](get_token.sh): This script allows you to get an authentication token with a valid 'PIA_USER' and 'PIA_PASS'. It will write the token and its expiration date to `/opt/piavpn-manual/token` for reference.
* [Get DIP details](get_dip.sh): This script will provide necessary connection details to use a dedicated IP.
* [Connect to WireGuard](connect_to_wireguard_with_token.sh): This script allows you to connect to the VPN server via WireGuard, or create a WireGuard config file by setting environment variable `PIA_CONNECT=false`.
* [Connect to OpenVPN](connect_to_openvpn_with_token.sh): This script allows you to connect to the VPN server via OpenVPN.
* [Enable Port Forwarding](port_forwarding.sh): Enables you to add Port Forwarding to an existing VPN connection. Adding the environment variable `PIA_PF=true` to any of the previous scripts will also trigger this script.
## Manual setup of PF
## Manual PF Testing
To use port forwarding on the NextGen network, first of all establish a connection with your favorite protocol. After this, you will need to find the private IP of the gateway you are connected to. In case you are WireGuard, the gateway will be part of the JSON response you get from the server, as you can see in the [bash script](https://github.com/pia-foss/manual-connections/blob/master/wireguard_and_pf.sh#L119). In case you are using OpenVPN, you can find the gateway by checking the routing table with `ip route s t all`.
After connecting and finding out what the gateway is, get your payload and your signature by calling `getSignature` via HTTPS on port 19999. You will have to add your token as a GET var to proove you actually have an active account.
After connecting and finding out what the gateway is, get your payload and your signature by calling `getSignature` via HTTPS on port 19999. You will have to add your token as a GET var to prove you actually have an active account.
Example:
```bash
@ -71,7 +126,7 @@ bash-5.0# curl -k "https://10.4.128.1:19999/getSignature?token=$TOKEN"
The payload can be decoded with base64 to see your information:
```bash
$ echo eyJ0b2tlbiI6Inh4eHh4eHh4eCIsInBvcnQiOjQ3MDQ3LCJjcmVhdGVkX2F0IjoiMjAyMC0wNC0zMFQyMjozMzo0NC4xMTQzNjk5MDZaIn0= | base64 -d | jq
$ echo eyJ0b2tlbiI6Inh4eHh4eHh4eCIsInBvcnQiOjQ3MDQ3LCJjcmVhdGVkX2F0IjoiMjAyMC0wNC0zMFQyMjozMzo0NC4xMTQzNjk5MDZaIn0= | base64 -d | jq
{
"token": "xxxxxxxxx",
"port": 47047,
@ -87,12 +142,12 @@ bash-5.0# curl -sGk --data-urlencode "payload=${payload}" --data-urlencode "sign
"status": "OK",
"message": "port scheduled for add"
}
bash-5.0#
bash-5.0#
```
Call __/bindPort__ every 15 minutes, or the port will be deleted!
### Testing your new PF
### Testing Your New PF
To test that it works, you can tcpdump on the port you received:
@ -100,12 +155,12 @@ To test that it works, you can tcpdump on the port you received:
bash-5.0# tcpdump -ni any port 47047
```
After that, use curl on the IP of the traffic server and the port specified in the payload which in our case is `47047`:
After that, use curl __from another machine__ on the IP of the traffic server and the port specified in the payload which in our case is `47047`:
```bash
$ curl "http://178.162.208.237:47047"
```
and you should see the traffic in your tcpdump:
You should see the traffic in your tcpdump:
```
bash-5.0# tcpdump -ni any port 47047
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
@ -114,5 +169,11 @@ listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 byt
22:44:01.510895 IP 10.4.143.34.47047 > 81.180.227.170.33884: Flags [R.], seq 0, ack 906854497, win 0, length 0
```
If you run curl on the same machine (the one that is connected to the VPN), you will see the traffic in tcpdump anyway and the test won't prove anything. At the same time, the request will get firewall so you will not be able to access the port from the same machine. This can only be tested properly by running curl on another system.
## Thanks
A big special thanks to [faireOwl](https://github.com/faireOwl) for his contributions to this repo.
## License
This project is licensed under the [MIT (Expat) license](https://choosealicense.com/licenses/mit/), which can be found [here](/LICENSE).

276
connect_to_openvpn_with_token.sh Executable file
View File

@ -0,0 +1,276 @@
#!/usr/bin/env bash
# Copyright (C) 2020 Private Internet Access, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# This function allows you to check if the required tools have been installed.
check_tool() {
cmd=$1
if ! command -v "$cmd" >/dev/null; then
echo "$cmd could not be found"
echo "Please install $cmd"
exit 1
fi
}
# Now we call the function to make sure we can use openvpn, curl and jq.
check_tool openvpn
check_tool curl
check_tool jq
# Check if terminal allows output, if yes, define colors for output
if [[ -t 1 ]]; then
ncolors=$(tput colors)
if [[ -n $ncolors && $ncolors -ge 8 ]]; then
red=$(tput setaf 1) # ANSI red
green=$(tput setaf 2) # ANSI green
nc=$(tput sgr0) # No Color
else
red=''
green=''
nc='' # No Color
fi
fi
# Check if manual PIA OpenVPN connection is already initialized.
# Multi-hop is out of the scope of this repo, but you should be able to
# get multi-hop running with both OpenVPN and WireGuard.
adapter_check=$( ip a s tun06 2>&1 )
should_read="Device \"tun06\" does not exist"
pid_filepath="/opt/piavpn-manual/pia_pid"
if [[ $adapter_check != *"$should_read"* ]]; then
echo -e "${red}The tun06 adapter already exists, that interface is required"
echo -e "for this configuration.${nc}"
if [[ -f $pid_filepath ]]; then
old_pid=$( cat "$pid_filepath" )
old_pid_name=$( ps -p "$old_pid" -o comm= )
if [[ $old_pid_name == "openvpn" ]]; then
echo
echo -e "It seems likely that process ${red}$old_pid${nc} is an OpenVPN connection"
echo "that was established by using this script. Unless it is closed"
echo "you would not be able to get a new connection."
echo -ne "Do you want to run ${red}$ kill $old_pid${nc} (Y/n): "
read -r close_connection
fi
if echo "${close_connection:0:1}" | grep -iq n; then
echo -e "${red}Closing script. Resolve tun06 adapter conflict and run the script again."
exit 1
fi
echo
echo -e "${green}Killing the existing OpenVPN process and waiting 5 seconds...${nc}"
kill "$old_pid"
echo
for i in {5..1}; do
echo -n "$i..."
sleep 1
done
echo
echo
fi
fi
# PIA currently does not support IPv6. In order to be sure your VPN
# connection does not leak, it is best to disabled IPv6 altogether.
# IPv6 can also be disabled via kernel commandline param, so we must
# first check if this is the case.
if [[ -f /proc/net/if_inet6 ]] &&
[[ $(sysctl -n net.ipv6.conf.all.disable_ipv6) -ne 1 ||
$(sysctl -n net.ipv6.conf.default.disable_ipv6) -ne 1 ]]
then
echo -e "${red}You should consider disabling IPv6 by running:"
echo "sysctl -w net.ipv6.conf.all.disable_ipv6=1"
echo -e "sysctl -w net.ipv6.conf.default.disable_ipv6=1${nc}"
fi
# Check if the mandatory environment variables are set.
if [[ -z $OVPN_SERVER_IP ||
-z $OVPN_HOSTNAME ||
-z $PIA_TOKEN ||
-z $CONNECTION_SETTINGS ]]; then
echo -e "${red}This script requires 4 env vars:"
echo "PIA_TOKEN - the token used for authentication"
echo "OVPN_SERVER_IP - IP that you want to connect to"
echo "OVPN_HOSTNAME - name of the server, required for ssl"
echo "CONNECTION_SETTINGS - the protocol and encryption specification"
echo " - available options for CONNECTION_SETTINGS are:"
echo " * openvpn_udp_standard"
echo " * openvpn_udp_strong"
echo " * openvpn_tcp_standard"
echo " * openvpn_tcp_strong"
echo
echo "You can also specify optional env vars:"
echo "PIA_PF - enable port forwarding"
echo "PAYLOAD_AND_SIGNATURE - In case you already have a port."
echo
echo "An easy solution is to just run get_region_and_token.sh"
echo "as it will guide you through getting the best server and"
echo "also a token. Detailed information can be found here:"
echo -e "https://github.com/pia-foss/manual-connections${nc}"
exit 1
fi
splitToken="dedicated_ip_$DIP_TOKEN"
# Create a credentials file with the login token
echo -n "Trying to write /opt/piavpn-manual/pia.ovpn..."
mkdir -p /opt/piavpn-manual
rm -f /opt/piavpn-manual/credentials /opt/piavpn-manual/route_info
if [[ -z $DIP_TOKEN ]]; then
echo "${PIA_TOKEN:0:62}
${PIA_TOKEN:62}" > /opt/piavpn-manual/credentials || exit 1
chmod 600 /opt/piavpn-manual/credentials
else
echo "${splitToken:0:62}
${splitToken:62}" > /opt/piavpn-manual/credentials || exit 1
chmod 600 /opt/piavpn-manual/credentials
fi
echo -e "${green}OK!${nc}"
# Translate connection settings variable
IFS='_'
read -ra connection_settings <<< "$CONNECTION_SETTINGS"
IFS=' '
protocol=${connection_settings[1]}
encryption=${connection_settings[2]}
prefix_filepath="openvpn_config/standard.ovpn"
if [[ $encryption == "strong" ]]; then
prefix_filepath="openvpn_config/strong.ovpn"
fi
if [[ $protocol == "udp" ]]; then
if [[ $encryption == "standard" ]]; then
port=1198
else
port=1197
fi
else
if [[ $encryption == "standard" ]]; then
port=502
else
port=501
fi
fi
# Create the OpenVPN config based on the settings specified
cat "$prefix_filepath" > /opt/piavpn-manual/pia.ovpn || exit 1
echo "remote $OVPN_SERVER_IP $port $protocol" >> /opt/piavpn-manual/pia.ovpn
# Copy the up/down scripts to /opt/piavpn-manual/
# based upon use of PIA DNS
if [[ $PIA_DNS != "true" ]]; then
cp openvpn_config/openvpn_up.sh /opt/piavpn-manual/
cp openvpn_config/openvpn_down.sh /opt/piavpn-manual/
echo -e "${red}This configuration will not use PIA DNS.${nc}"
echo "If you want to also enable PIA DNS, please start the script"
echo "with the env var PIA_DNS=true. Example:"
echo $ OVPN_SERVER_IP=\""$OVPN_SERVER_IP"\" OVPN_HOSTNAME=\""$OVPN_HOSTNAME"\" \
PIA_TOKEN=\""$PIA_TOKEN"\" CONNECTION_SETTINGS=\""$CONNECTION_SETTINGS"\" \
PIA_PF=true PIA_DNS=true ./connect_to_openvpn_with_token.sh
else
cp openvpn_config/openvpn_up_dnsoverwrite.sh /opt/piavpn-manual/openvpn_up.sh
cp openvpn_config/openvpn_down_dnsoverwrite.sh /opt/piavpn-manual/openvpn_down.sh
fi
# Start the OpenVPN interface.
# If something failed, stop this script.
# If you get DNS errors because you miss some packages,
# just hardcode /etc/resolv.conf to "nameserver 10.0.0.242".
#rm -f /opt/piavpn-manual/debug_info
echo "
Trying to start the OpenVPN connection..."
openvpn --daemon \
--config "/opt/piavpn-manual/pia.ovpn" \
--writepid "/opt/piavpn-manual/pia_pid" \
--log "/opt/piavpn-manual/debug_info" || exit 1
echo -n "
The OpenVPN connect command was issued.
Confirming OpenVPN connection state..."
# Check if manual PIA OpenVPN connection is initialized.
# Manually adjust the connection_wait_time if needed
connection_wait_time=10
confirmation="Initialization Sequence Complete"
for (( timeout=0; timeout <= connection_wait_time; timeout++ )); do
sleep 1
if grep -q "$confirmation" /opt/piavpn-manual/debug_info; then
connected=true
break
fi
done
ovpn_pid=$( cat /opt/piavpn-manual/pia_pid )
gateway_ip=$( cat /opt/piavpn-manual/route_info )
# Report and exit if connection was not initialized within 10 seconds.
if [[ $connected != "true" ]]; then
echo -e "${red}The VPN connection was not established within 10 seconds.${nc}"
kill "$ovpn_pid"
exit 1
fi
echo -e "${green}Initialization Sequence Complete!${nc}
At this point, internet should work via VPN.
"
echo -e "OpenVPN Process ID: ${green}$ovpn_pid${nc}
VPN route IP: ${green}$gateway_ip${nc}
To disconnect the VPN, run:
--> ${green}sudo kill $ovpn_pid${nc} <--
"
# This section will stop the script if PIA_PF is not set to "true".
if [[ $PIA_PF != "true" ]]; then
echo "If you want to also enable port forwarding, you can start the script:"
echo -e "$ ${green}PIA_TOKEN=$PIA_TOKEN" \
"PF_GATEWAY=$gateway_ip" \
"PF_HOSTNAME=$OVPN_HOSTNAME" \
"./port_forwarding.sh${nc}"
echo
echo "The location used must be port forwarding enabled, or this will fail."
echo "Calling the ./get_region script with PIA_PF=true will provide a filtered list."
exit 1
fi
echo -ne "This script got started with ${green}PIA_PF=true${nc}.
Starting port forwarding in "
for i in {5..1}; do
echo -n "$i..."
sleep 1
done
echo
echo
echo -e "Starting procedure to enable port forwarding by running the following command:
$ ${green}PIA_TOKEN=$PIA_TOKEN \\
PF_GATEWAY=$gateway_ip \\
PF_HOSTNAME=$OVPN_HOSTNAME \\
./port_forwarding.sh${nc}"
PIA_TOKEN=$PIA_TOKEN \
PF_GATEWAY=$gateway_ip \
PF_HOSTNAME=$OVPN_HOSTNAME \
./port_forwarding.sh

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
# Copyright (C) 2020 Private Internet Access, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
@ -20,53 +20,77 @@
# SOFTWARE.
# This function allows you to check if the required tools have been installed.
function check_tool() {
check_tool() {
cmd=$1
package=$2
if ! command -v $cmd &>/dev/null
then
pkg=$2
if ! command -v "$cmd" >/dev/null; then
echo "$cmd could not be found"
echo "Please install $package"
echo "Please install $pkg"
exit 1
fi
}
# Now we call the function to make sure we can use wg-quick, curl and jq.
check_tool wg-quick wireguard-tools
check_tool curl curl
check_tool jq jq
# Check if terminal allows output, if yes, define colors for output
if [[ -t 1 ]]; then
ncolors=$(tput colors)
if [[ -n $ncolors && $ncolors -ge 8 ]]; then
red=$(tput setaf 1) # ANSI red
green=$(tput setaf 2) # ANSI green
nc=$(tput sgr0) # No Color
else
red=''
green=''
nc='' # No Color
fi
fi
: "${PIA_CONNECT=true}"
DEFAULT_PIA_CONF_PATH=/etc/wireguard/pia.conf
: "${PIA_CONF_PATH:=$DEFAULT_PIA_CONF_PATH}"
# PIA currently does not support IPv6. In order to be sure your VPN
# connection does not leak, it is best to disabled IPv6 altogether.
if [ $(sysctl -n net.ipv6.conf.all.disable_ipv6) -ne 1 ] ||
[ $(sysctl -n net.ipv6.conf.default.disable_ipv6) -ne 1 ]
# IPv6 can also be disabled via kernel commandline param, so we must
# first check if this is the case.
if [[ -f /proc/net/if_inet6 ]] &&
[[ $(sysctl -n net.ipv6.conf.all.disable_ipv6) -ne 1 ||
$(sysctl -n net.ipv6.conf.default.disable_ipv6) -ne 1 ]]
then
echo 'You should consider disabling IPv6 by running:'
echo 'sysctl -w net.ipv6.conf.all.disable_ipv6=1'
echo 'sysctl -w net.ipv6.conf.default.disable_ipv6=1'
echo -e "${red}You should consider disabling IPv6 by running:"
echo "sysctl -w net.ipv6.conf.all.disable_ipv6=1"
echo -e "sysctl -w net.ipv6.conf.default.disable_ipv6=1${nc}"
fi
# Check if the mandatory environment variables are set.
if [[ ! $WG_SERVER_IP || ! $WG_HOSTNAME || ! $WG_TOKEN ]]; then
echo This script requires 3 env vars:
echo WG_SERVER_IP - IP that you want to connect to
echo WG_HOSTNAME - name of the server, required for ssl
echo WG_TOKEN - your authentication token
if [[ -z $WG_SERVER_IP ||
-z $WG_HOSTNAME ||
-z $PIA_TOKEN ]]; then
echo -e "${red}This script requires 3 env vars:"
echo "WG_SERVER_IP - IP that you want to connect to"
echo "WG_HOSTNAME - name of the server, required for ssl"
echo "PIA_TOKEN - your authentication token"
echo
echo You can also specify optional env vars:
echo "You can also specify optional env vars:"
echo "PIA_PF - enable port forwarding"
echo "PAYLOAD_AND_SIGNATURE - In case you already have a port."
echo
echo An easy solution is to just run get_region_and_token.sh
echo as it will guide you through getting the best server and
echo also a token. Detailed information can be found here:
echo https://github.com/pia-foss/manual-connections
echo "An easy solution is to just run get_region_and_token.sh"
echo "as it will guide you through getting the best server and"
echo "also a token. Detailed information can be found here:"
echo -e "https://github.com/pia-foss/manual-connections${nc}"
exit 1
fi
# Create ephemeral wireguard keys, that we don't need to save to disk.
privKey="$(wg genkey)"
privKey=$(wg genkey)
export privKey
pubKey="$( echo "$privKey" | wg pubkey)"
pubKey=$( echo "$privKey" | wg pubkey)
export pubKey
# Authenticate via the PIA WireGuard RESTful API.
@ -75,76 +99,121 @@ export pubKey
# In case you didn't clone the entire repo, get the certificate from:
# https://github.com/pia-foss/manual-connections/blob/master/ca.rsa.4096.crt
# In case you want to troubleshoot the script, replace -s with -v.
echo Trying to connect to the PIA WireGuard API on $WG_SERVER_IP...
wireguard_json="$(curl -s -G \
--connect-to "$WG_HOSTNAME::$WG_SERVER_IP:" \
--cacert "ca.rsa.4096.crt" \
--data-urlencode "pt=${WG_TOKEN}" \
--data-urlencode "pubkey=$pubKey" \
"https://${WG_HOSTNAME}:1337/addKey" )"
echo "Trying to connect to the PIA WireGuard API on $WG_SERVER_IP..."
if [[ -z $DIP_TOKEN ]]; then
wireguard_json="$(curl -s -G \
--connect-to "$WG_HOSTNAME::$WG_SERVER_IP:" \
--cacert "ca.rsa.4096.crt" \
--data-urlencode "pt=${PIA_TOKEN}" \
--data-urlencode "pubkey=$pubKey" \
"https://${WG_HOSTNAME}:1337/addKey" )"
else
wireguard_json="$(curl -s -G \
--connect-to "$WG_HOSTNAME::$WG_SERVER_IP:" \
--cacert "ca.rsa.4096.crt" \
--user "dedicated_ip_$DIP_TOKEN:$WG_SERVER_IP" \
--data-urlencode "pubkey=$pubKey" \
"https://$WG_HOSTNAME:1337/addKey" )"
fi
export wireguard_json
echo "$wireguard_json"
# Check if the API returned OK and stop this script if it didn't.
if [ "$(echo "$wireguard_json" | jq -r '.status')" != "OK" ]; then
>&2 echo "Server did not return OK. Stopping now."
if [[ $(echo "$wireguard_json" | jq -r '.status') != "OK" ]]; then
>&2 echo -e "${red}Server did not return OK. Stopping now.${nc}"
exit 1
fi
if [[ $PIA_CONNECT == "true" ]]; then
# Ensure config file path is set to default used for WG connection
PIA_CONF_PATH=$DEFAULT_PIA_CONF_PATH
# Multi-hop is out of the scope of this repo, but you should be able to
# get multi-hop running with both WireGuard and OpenVPN by playing with
# these scripts. Feel free to fork the project and test it out.
echo
echo "Trying to disable a PIA WG connection in case it exists..."
wg-quick down pia && echo -e "${green}\nPIA WG connection disabled!${nc}"
echo
fi
# Create the WireGuard config based on the JSON received from the API
# The config does not contain a DNS entry, since some servers do not
# have resolvconf, which will result in the script failing.
# We will enforce the DNS after the connection gets established.
echo -n "Trying to write /etc/wireguard/pia.conf... "
mkdir -p /etc/wireguard
# In case you want this section to also add the DNS setting, please
# start the script with PIA_DNS=true.
# This uses a PersistentKeepalive of 25 seconds to keep the NAT active
# on firewalls. You can remove that line if your network does not
# require it.
if [[ $PIA_DNS == "true" ]]; then
dnsServer=$(echo "$wireguard_json" | jq -r '.dns_servers[0]')
echo "Trying to set up DNS to $dnsServer. In case you do not have resolvconf,"
echo "this operation will fail and you will not get a VPN. If you have issues,"
echo "start this script without PIA_DNS."
echo
dnsSettingForVPN="DNS = $dnsServer"
fi
echo -n "Trying to write ${PIA_CONF_PATH}..."
mkdir -p "$(dirname "$PIA_CONF_PATH")"
echo "
[Interface]
Address = $(echo "$wireguard_json" | jq -r '.peer_ip')
PrivateKey = $privKey
## If you want wg-quick to also set up your DNS, uncomment the line below.
# DNS = $(echo "$wireguard_json" | jq -r '.dns_servers[0]')
$dnsSettingForVPN
[Peer]
PersistentKeepalive = 25
PublicKey = $(echo "$wireguard_json" | jq -r '.server_key')
AllowedIPs = 0.0.0.0/0
Endpoint = ${WG_SERVER_IP}:$(echo "$wireguard_json" | jq -r '.server_port')
" > /etc/wireguard/pia.conf || exit 1
echo OK!
" > ${PIA_CONF_PATH} || exit 1
echo -e "${green}OK!${nc}"
# Start the WireGuard interface.
# If something failed, stop this script.
# If you get DNS errors because you miss some packages,
# just can hardcode /etc/resolv.conf to "nameserver 10.0.0.242".
echo
echo Trying to create the wireguard interface...
wg-quick up pia || exit 1
echo "The WireGuard interface got created.
At this point, internet should work via VPN.
--> to disconnect the VPN, run:
$ wg-quick down pia"
# This section will stop the script if PIA_PF is not set to "true".
if [ "$PIA_PF" != true ]; then
if [[ $PIA_CONNECT == "true" ]]; then
# Start the WireGuard interface.
# If something failed, stop this script.
# If you get DNS errors because you miss some packages,
# just hardcode /etc/resolv.conf to "nameserver 10.0.0.242".
echo
echo If you want to also enable port forwarding, please start the script
echo with the env var PIA_PF=true. Example:
echo $ WG_SERVER=10.0.0.3 WG_HOSTNAME=piaserver401 \
WG_TOKEN=\"\$token\" PIA_PF=true \
./sort_regions_by_latency.sh
exit
echo "Trying to create the wireguard interface..."
wg-quick up pia || exit 1
echo
echo -e "${green}The WireGuard interface got created.${nc}
At this point, internet should work via VPN.
To disconnect the VPN, run:
--> ${green}wg-quick down pia${nc} <--
"
# This section will stop the script if PIA_PF is not set to "true".
if [[ $PIA_PF != "true" ]]; then
echo "If you want to also enable port forwarding, you can start the script:"
echo -e "$ ${green}PIA_TOKEN=$PIA_TOKEN" \
"PF_GATEWAY=$WG_SERVER_IP" \
"PF_HOSTNAME=$WG_HOSTNAME" \
"./port_forwarding.sh${nc}"
echo
echo "The location used must be port forwarding enabled, or this will fail."
echo "Calling the ./get_region script with PIA_PF=true will provide a filtered list."
exit 1
fi
echo -ne "This script got started with ${green}PIA_PF=true${nc}.
Starting port forwarding in "
for i in {5..1}; do
echo -n "$i..."
sleep 1
done
echo
echo
echo -e "Starting procedure to enable port forwarding by running the following command:
$ ${green}PIA_TOKEN=$PIA_TOKEN \\
PF_GATEWAY=$WG_SERVER_IP \\
PF_HOSTNAME=$WG_HOSTNAME \\
./port_forwarding.sh${nc}"
PIA_TOKEN=$PIA_TOKEN \
PF_GATEWAY=$WG_SERVER_IP \
PF_HOSTNAME=$WG_HOSTNAME \
./port_forwarding.sh
fi
echo "
This script got started with PIA_PF=true.
Starting procedure to enable port forwarding by running the following command:
$ PIA_TOKEN=$WG_TOKEN \\
PF_GATEWAY=\"$(echo "$wireguard_json" | jq -r '.server_vip')\" \\
PF_HOSTNAME=\"$WG_HOSTNAME\" \\
./port_forwarding.sh
"
PIA_TOKEN=$WG_TOKEN \
PF_GATEWAY="$(echo "$wireguard_json" | jq -r '.server_vip')" \
PF_HOSTNAME="$WG_HOSTNAME" \
./port_forwarding.sh

109
get_dip.sh Executable file
View File

@ -0,0 +1,109 @@
#!/bin/bash
# Copyright (C) 2020 Private Internet Access, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# This function allows you to check if the required tools have been installed.
check_tool() {
cmd=$1
if ! command -v $cmd &>/dev/null; then
echo "$cmd could not be found"
echo "Please install $cmd"
exit 1
fi
}
# Now we call the function to make sure we can use curl and jq.
check_tool curl
check_tool jq
# Check if terminal allows output, if yes, define colors for output
if [[ -t 1 ]]; then
ncolors=$(tput colors)
if [[ -n $ncolors && $ncolors -ge 8 ]]; then
red=$(tput setaf 1) # ANSI red
green=$(tput setaf 2) # ANSI green
nc=$(tput sgr0) # No Color
else
red=''
green=''
nc='' # No Color
fi
fi
# Only allow script to run as root
if (( EUID != 0 )); then
echo -e "${red}This script needs to be run as root. Try again with 'sudo $0'${nc}"
exit 1
fi
mkdir -p /opt/piavpn-manual
if [[ -z $PIA_TOKEN ]]; then
echo "If you want this script to automatically retrieve dedicated IP location details"
echo "from the Meta service, please add the variables PIA_TOKEN and DIP_TOKEN. Example:"
echo "$ PIA_TOKEN DIP_TOKEN=DIP1a2b3c4d5e6f7g8h9i10j11k12l13 ./get_token.sh"
exit 1
fi
dipSavedLocation=/opt/piavpn-manual/dipAddress
echo -n "Checking DIP token..."
generateDIPResponse=$(curl -s --location --request POST \
'https://www.privateinternetaccess.com/api/client/v2/dedicated_ip' \
--header 'Content-Type: application/json' \
--header "Authorization: Token $PIA_TOKEN" \
--data-raw '{
"tokens":["'"$DIP_TOKEN"'"]
}')
if [ "$(echo "$generateDIPResponse" | jq -r '.[0].status')" != "active" ]; then
echo
echo
echo -e "${red}Could not validate the dedicated IP token provided!${nc}"
echo
exit
fi
echo -e ${green}OK!${nc}
echo
dipAddress=$(echo "$generateDIPResponse" | jq -r '.[0].ip')
dipHostname=$(echo "$generateDIPResponse" | jq -r '.[0].cn')
keyHostname=$(echo "dedicated_ip_$DIP_TOKEN")
dipExpiration=$(echo "$generateDIPResponse" | jq -r '.[0].dip_expire')
dipExpiration=$(date -d @$dipExpiration)
dipID=$(echo "$generateDIPResponse" | jq -r '.[0].id')
echo -e The hostname of your dedicated IP is ${green}$dipHostname${nc}
echo
echo -e The dedicated IP address is ${green}$dipAddress${nc}
echo
echo This dedicated IP is valid until $dipExpiration.
echo
pfCapable="true"
if [[ $dipID == us_* ]]; then
pfCapable="false"
echo This location does not have port forwarding capability.
echo
fi
echo $dipAddress > /opt/piavpn-manual/dipAddress || exit 1
echo $dipHostname >> /opt/piavpn-manual/dipAddress
echo $keyHostname >> /opt/piavpn-manual/dipAddress
echo $dipExpiration >> /opt/piavpn-manual/dipAddress
echo $pfCapable >> /opt/piavpn-manual/dipAddress

273
get_region.sh Executable file
View File

@ -0,0 +1,273 @@
#!/usr/bin/env bash
# Copyright (C) 2020 Private Internet Access, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# This function allows you to check if the required tools have been installed.
check_tool() {
cmd=$1
if ! command -v "$cmd" >/dev/null; then
echo "$cmd could not be found"
echo "Please install $cmd"
exit 1
fi
}
# Now we call the function to make sure we can use curl and jq.
check_tool curl
check_tool jq
# If the server list has less than 1000 characters, it means curl failed.
check_all_region_data() {
echo
echo -n "Getting the server list..."
if [[ ${#all_region_data} -lt 1000 ]]; then
echo -e "${red}Could not get correct region data. To debug this, run:"
echo "$ curl -v $serverlist_url"
echo -e "If it works, you will get a huge JSON as a response.${nc}"
exit 1
fi
# Notify the user that we got the server list.
echo -e "${green}OK!${nc}
"
}
# Get all data for the selected region
# Exit with code 1 if the REGION_ID provided is invalid
get_selected_region_data() {
regionData="$( echo "$all_region_data" |
jq --arg REGION_ID "$selectedRegion" -r \
'.regions[] | select(.id==$REGION_ID)')"
if [[ -z $regionData ]]; then
echo -e "${red}The REGION_ID $selectedRegion is not valid.${nc}
"
exit 1
fi
}
# Check if terminal allows output, if yes, define colors for output
if [[ -t 1 ]]; then
ncolors=$(tput colors)
if [[ -n $ncolors && $ncolors -ge 8 ]]; then
red=$(tput setaf 1) # ANSI red
green=$(tput setaf 2) # ANSI green
nc=$(tput sgr0) # No Color
else
red=''
green=''
nc='' # No Color
fi
fi
# Only allow script to run as root
if (( EUID != 0 )); then
echo -e "${red}This script needs to be run as root. Try again with 'sudo $0'${nc}"
exit 1
fi
mkdir -p /opt/piavpn-manual
# Erase old latencyList file
rm -f /opt/piavpn-manual/latencyList
touch /opt/piavpn-manual/latencyList
# This allows you to set the maximum allowed latency in seconds.
# All servers that respond slower than this will be ignored.
# You can inject this with the environment variable MAX_LATENCY.
# The default value is 50 milliseconds.
MAX_LATENCY=${MAX_LATENCY:-0.05}
export MAX_LATENCY
serverlist_url='https://serverlist.piaservers.net/vpninfo/servers/v6'
# This function checks the latency you have to a specific region.
# It will print a human-readable message to stderr,
# and it will print the variables to stdout
printServerLatency() {
serverIP=$1
regionID=$2
regionName="$(echo "${@:3}" |
sed 's/ false//' | sed 's/true/(geo)/')"
time=$(LC_NUMERIC=en_US.utf8 curl -o /dev/null -s \
--connect-timeout "$MAX_LATENCY" \
--write-out "%{time_connect}" \
"http://$serverIP:443")
if [[ $? -eq 0 ]]; then
>&2 echo "Got latency ${time}s for region: $regionName"
echo "$time $regionID $serverIP"
# Write a list of servers with acceptable latency
# to /opt/piavpn-manual/latencyList
echo -e "$time" "$regionID"'\t'"$serverIP"'\t'"$regionName" >> /opt/piavpn-manual/latencyList
fi
# Sort the latencyList, ordered by latency
sort -no /opt/piavpn-manual/latencyList /opt/piavpn-manual/latencyList
}
export -f printServerLatency
# If a server location or autoconnect isn't specified, set the variable to false/no.
if [[ -z $PREFERRED_REGION ]]; then
PREFERRED_REGION=none
fi
if [[ -z $VPN_PROTOCOL ]]; then
VPN_PROTOCOL=no
fi
# Get all region data
all_region_data=$(curl -s "$serverlist_url" | head -1)
# Set the region the user has specified
selectedRegion=$PREFERRED_REGION
# If a server isn't being specified, auto-select the server with the lowest latency
if [[ $selectedRegion == "none" ]]; then
selectedOrLowestLatency="lowest latency"
check_all_region_data
# Making sure this variable doesn't contain some strange string
if [[ $PIA_PF != "true" ]]; then
PIA_PF="false"
fi
# Test one server from each region to get the closest region.
# If port forwarding is enabled, filter out regions that don't support it.
if [[ $PIA_PF == "true" ]]; then
echo "Port Forwarding is enabled, non-PF servers excluded."
echo
summarized_region_data="$( echo "$all_region_data" |
jq -r '.regions[] | select(.port_forward==true) |
.servers.meta[0].ip+" "+.id+" "+.name+" "+(.geo|tostring)' )"
else
summarized_region_data="$( echo "$all_region_data" |
jq -r '.regions[] |
.servers.meta[0].ip+" "+.id+" "+.name+" "+(.geo|tostring)' )"
fi
echo -e Testing regions that respond \
faster than "${green}$MAX_LATENCY${nc}" seconds:
selectedRegion="$(echo "$summarized_region_data" |
xargs -I{} bash -c 'printServerLatency {}' |
sort | head -1 | awk '{ print $2 }')"
echo
if [[ -z $selectedRegion ]]; then
echo -e "${red}No region responded within ${MAX_LATENCY}s, consider using a higher timeout."
echo "For example, to wait 1 second for each region, inject MAX_LATENCY=1 like this:"
echo -e "$ MAX_LATENCY=1 ./get_region.sh${nc}"
exit 1
else
echo -e "A list of servers and connection details, ordered by latency can be
found in at : ${green}/opt/piavpn-manual/latencyList${nc}
"
fi
else
selectedOrLowestLatency="selected"
check_all_region_data
fi
get_selected_region_data
bestServer_meta_IP=$(echo "$regionData" | jq -r '.servers.meta[0].ip')
bestServer_meta_hostname=$(echo "$regionData" | jq -r '.servers.meta[0].cn')
bestServer_WG_IP=$(echo "$regionData" | jq -r '.servers.wg[0].ip')
bestServer_WG_hostname=$(echo "$regionData" | jq -r '.servers.wg[0].cn')
bestServer_OT_IP=$(echo "$regionData" | jq -r '.servers.ovpntcp[0].ip')
bestServer_OT_hostname=$(echo "$regionData" | jq -r '.servers.ovpntcp[0].cn')
bestServer_OU_IP=$(echo "$regionData" | jq -r '.servers.ovpnudp[0].ip')
bestServer_OU_hostname=$(echo "$regionData" | jq -r '.servers.ovpnudp[0].cn')
if [[ $VPN_PROTOCOL == "no" ]]; then
echo -ne "The $selectedOrLowestLatency region is ${green}$(echo "$regionData" | jq -r '.name')${nc}"
if echo "$regionData" | jq -r '.geo' | grep true > /dev/null; then
echo " (geolocated region)."
else
echo "."
fi
echo -e "
The script found the best servers from the region you selected.
When connecting to an IP (no matter which protocol), please verify
the SSL/TLS certificate actually contains the hostname so that you
are sure you are connecting to a secure server, validated by the
PIA authority. Please find below the list of best IPs and matching
hostnames for each protocol:
${green}Meta Services $bestServer_meta_IP\t- $bestServer_meta_hostname
WireGuard $bestServer_WG_IP\t- $bestServer_WG_hostname
OpenVPN TCP $bestServer_OT_IP\t- $bestServer_OT_hostname
OpenVPN UDP $bestServer_OU_IP\t- $bestServer_OU_hostname
${nc}"
fi
# The script will check for an authentication token, and use it if present
# If no token exists, the script will check for login credentials to generate one
if [[ -z $PIA_TOKEN ]]; then
if [[ -z $PIA_USER || -z $PIA_PASS ]]; then
echo -e "${red}If you want this script to automatically get an authentication"
echo "token, please add the variables PIA_USER and PIA_PASS. Example:"
echo -e "$ PIA_USER=p0123456 PIA_PASS=xxx ./get_region.sh${nc}"
exit 0
fi
./get_token.sh
PIA_TOKEN=$( awk 'NR == 1' /opt/piavpn-manual/token )
export PIA_TOKEN
rm -f /opt/piavpn-manual/token
else
echo -e "Using existing token ${green}$PIA_TOKEN${nc}."
echo
fi
# Connect with WireGuard and clear authentication token file and latencyList
if [[ $VPN_PROTOCOL == "wireguard" ]]; then
echo "The ./get_region.sh script got started with"
echo -e "${green}VPN_PROTOCOL=wireguard${nc}, so we will automatically connect to WireGuard,"
echo "by running this command:"
echo -e "$ ${green}PIA_TOKEN=$PIA_TOKEN \\"
echo "WG_SERVER_IP=$bestServer_WG_IP WG_HOSTNAME=$bestServer_WG_hostname \\"
echo -e "PIA_PF=$PIA_PF ./connect_to_wireguard_with_token.sh${nc}"
echo
PIA_PF=$PIA_PF PIA_TOKEN=$PIA_TOKEN WG_SERVER_IP=$bestServer_WG_IP \
WG_HOSTNAME=$bestServer_WG_hostname ./connect_to_wireguard_with_token.sh
rm -f /opt/piavpn-manual/latencyList
exit 0
fi
# Connect with OpenVPN and clear authentication token file and latencyList
if [[ $VPN_PROTOCOL == openvpn* ]]; then
serverIP=$bestServer_OU_IP
serverHostname=$bestServer_OU_hostname
if [[ $VPN_PROTOCOL == *tcp* ]]; then
serverIP=$bestServer_OT_IP
serverHostname=$bestServer_OT_hostname
fi
echo "The ./get_region.sh script got started with"
echo -e "${green}VPN_PROTOCOL=$VPN_PROTOCOL${nc}, so we will automatically"
echo "connect to OpenVPN, by running this command:"
echo -e "$ ${green}PIA_PF=$PIA_PF PIA_TOKEN=$PIA_TOKEN \\"
echo " OVPN_SERVER_IP=$serverIP \\"
echo " OVPN_HOSTNAME=$serverHostname \\"
echo " CONNECTION_SETTINGS=$VPN_PROTOCOL \\"
echo -e " ./connect_to_openvpn_with_token.sh${nc}"
echo
PIA_PF=$PIA_PF PIA_TOKEN=$PIA_TOKEN \
OVPN_SERVER_IP=$serverIP \
OVPN_HOSTNAME=$serverHostname \
CONNECTION_SETTINGS=$VPN_PROTOCOL \
./connect_to_openvpn_with_token.sh
rm -f /opt/piavpn-manual/latencyList
exit 0
fi

View File

@ -1,196 +0,0 @@
#!/bin/bash
# Copyright (C) 2020 Private Internet Access, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# This function allows you to check if the required tools have been installed.
function check_tool() {
cmd=$1
package=$2
if ! command -v $cmd &>/dev/null
then
echo "$cmd could not be found"
echo "Please install $package"
exit 1
fi
}
# Now we call the function to make sure we can use curl and jq.
check_tool curl curl
check_tool jq jq
# This allows you to set the maximum allowed latency in seconds.
# All servers that repond slower than this will be ignored.
# You can inject this with the environment variable MAX_LATENCY.
# The default value is 50 milliseconds.
MAX_LATENCY=${MAX_LATENCY:-0.05}
export MAX_LATENCY
serverlist_url='https://serverlist.piaservers.net/vpninfo/servers/v4'
# This function checks the latency you have to a specific region.
# It will print a human-readable message to stderr,
# and it will print the variables to stdout
printServerLatency() {
serverIP="$1"
regionID="$2"
regionName="$(echo ${@:3} |
sed 's/ false//' | sed 's/true/(geo)/')"
time=$(curl -o /dev/null -s \
--connect-timeout $MAX_LATENCY \
--write-out "%{time_connect}" \
http://$serverIP:443)
if [ $? -eq 0 ]; then
>&2 echo Got latency ${time}s for region: $regionName
echo $time $regionID $serverIP
fi
}
export -f printServerLatency
echo -n "Getting the server list... "
# Get all region data since we will need this on multiple ocasions
all_region_data=$(curl -s "$serverlist_url" | head -1)
# If the server list has less than 1000 characters, it means curl failed.
if [[ ${#all_region_data} < 1000 ]]; then
echo "Could not get correct region data. To debug this, run:"
echo "$ curl -v $serverlist_url"
echo "If it works, you will get a huge JSON as a response."
exit 1
fi
# Notify the user that we got the server list.
echo "OK!"
# Test one server from each region to get the closest region.
# If port forwarding is enabled, filter out regions that don't support it.
if [[ $PIA_PF == "true" ]]; then
echo Port Forwarding is enabled, so regions that do not support
echo port forwarding will get filtered out.
summarized_region_data="$( echo $all_region_data |
jq -r '.regions[] | select(.port_forward==true) |
.servers.meta[0].ip+" "+.id+" "+.name+" "+(.geo|tostring)' )"
else
summarized_region_data="$( echo $all_region_data |
jq -r '.regions[] |
.servers.meta[0].ip+" "+.id+" "+.name+" "+(.geo|tostring)' )"
fi
echo Testing regions that respond \
faster than $MAX_LATENCY seconds:
bestRegion="$(echo "$summarized_region_data" |
xargs -i bash -c 'printServerLatency {}' |
sort | head -1 | awk '{ print $2 }')"
if [ -z "$bestRegion" ]; then
echo ...
echo No region responded within ${MAX_LATENCY}s, consider using a higher timeout.
echo For example, to wait 1 second for each region, inject MAX_LATENCY=1 like this:
echo $ MAX_LATENCY=1 ./get_region_and_token.sh
exit 1
fi
# Get all data for the best region
regionData="$( echo $all_region_data |
jq --arg REGION_ID "$bestRegion" -r \
'.regions[] | select(.id==$REGION_ID)')"
echo -n The closest region is "$(echo $regionData | jq -r '.name')"
if echo $regionData | jq -r '.geo' | grep true > /dev/null; then
echo " (geolocated region)."
else
echo "."
fi
echo
bestServer_meta_IP="$(echo $regionData | jq -r '.servers.meta[0].ip')"
bestServer_meta_hostname="$(echo $regionData | jq -r '.servers.meta[0].cn')"
bestServer_WG_IP="$(echo $regionData | jq -r '.servers.wg[0].ip')"
bestServer_WG_hostname="$(echo $regionData | jq -r '.servers.wg[0].cn')"
bestServer_OT_IP="$(echo $regionData | jq -r '.servers.ovpntcp[0].ip')"
bestServer_OT_hostname="$(echo $regionData | jq -r '.servers.ovpntcp[0].cn')"
bestServer_OU_IP="$(echo $regionData | jq -r '.servers.ovpnudp[0].ip')"
bestServer_OU_hostname="$(echo $regionData | jq -r '.servers.ovpnudp[0].cn')"
echo "The script found the best servers from the region closest to you.
When connecting to an IP (no matter which protocol), please verify
the SSL/TLS certificate actually contains the hostname so that you
are sure you are connecting to a secure server, validated by the
PIA authority. Please find bellow the list of best IPs and matching
hostnames for each protocol:
Meta Services: $bestServer_meta_IP // $bestServer_meta_hostname
WireGuard: $bestServer_WG_IP // $bestServer_WG_hostname
OpenVPN TCP: $bestServer_OT_IP // $bestServer_OT_hostname
OpenVPN UDP: $bestServer_OU_IP // $bestServer_OU_hostname
"
if [[ ! $PIA_USER || ! $PIA_PASS ]]; then
echo If you want this script to automatically get a token from the Meta
echo service, please add the variables PIA_USER and PIA_PASS. Example:
echo $ PIA_USER=p0123456 PIA_PASS=xxx ./get_region_and_token.sh
exit 1
fi
echo "The ./get_region_and_token.sh script got started with PIA_USER and PIA_PASS,
so we will also use a meta service to get a new VPN token."
echo "Trying to get a new token by authenticating with the meta service..."
generateTokenResponse=$(curl -s -u "$PIA_USER:$PIA_PASS" \
--connect-to "$bestServer_meta_hostname::$bestServer_meta_IP:" \
--cacert "ca.rsa.4096.crt" \
"https://$bestServer_meta_hostname/authv3/generateToken")
echo "$generateTokenResponse"
if [ "$(echo "$generateTokenResponse" | jq -r '.status')" != "OK" ]; then
echo "Could not get a token. Please check your account credentials."
echo "You can also try debugging by manually running the curl command:"
echo $ curl -vs -u "$PIA_USER:$PIA_PASS" --cacert ca.rsa.4096.crt \
--connect-to "$bestServer_meta_hostname::$bestServer_meta_IP:" \
https://$bestServer_meta_hostname/authv3/generateToken
exit 1
fi
token="$(echo "$generateTokenResponse" | jq -r '.token')"
echo "This token will expire in 24 hours.
"
if [ "$PIA_AUTOCONNECT" != wireguard ]; then
echo If you wish to automatically connect to WireGuard after detecting the best
echo region, please run the script with the env var PIA_AUTOCONNECT=wireguard.
echo You can echo also specify the env var PIA_PF=true to get port forwarding.
echo Example:
echo $ PIA_USER=p0123456 PIA_PASS=xxx \
PIA_AUTOCONNECT=true PIA_PF=true ./sort_regions_by_latency.sh
echo
echo You can also connect now by running this command:
echo $ WG_TOKEN=\"$token\" WG_SERVER_IP=$bestServer_WG_IP \
WG_HOSTNAME=$bestServer_WG_hostname ./connect_to_wireguard_with_token.sh
exit
fi
if [ "$PIA_PF" != true ]; then
PIA_PF="false"
fi
echo "The ./get_region_and_token.sh script got started with
PIA_AUTOCONNECT=wireguard, so we will automatically connect to WireGuard,
by running this command:
$ WG_TOKEN=\"$token\" \\
WG_SERVER_IP=$bestServer_WG_IP WG_HOSTNAME=$bestServer_WG_hostname \\
PIA_PF=$PIA_PF ./connect_to_wireguard_with_token.sh
"
PIA_PF=$PIA_PF WG_TOKEN="$token" WG_SERVER_IP=$bestServer_WG_IP \
WG_HOSTNAME=$bestServer_WG_hostname ./connect_to_wireguard_with_token.sh

95
get_token.sh Executable file
View File

@ -0,0 +1,95 @@
#!/usr/bin/env bash
# Copyright (C) 2020 Private Internet Access, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# This function allows you to check if the required tools have been installed.
check_tool() {
cmd=$1
if ! command -v "$cmd" >/dev/null; then
echo "$cmd could not be found"
echo "Please install $cmd"
exit 1
fi
}
# Now we call the function to make sure we can use curl and jq.
check_tool curl
check_tool jq
# This function creates a timestamp, to use for setting $TOKEN_EXPIRATION
timeout_timestamp() {
date +"%c" --date='1 day' # Timestamp 24 hours
}
# Check if terminal allows output, if yes, define colors for output
if [[ -t 1 ]]; then
ncolors=$(tput colors)
if [[ -n $ncolors && $ncolors -ge 8 ]]; then
red=$(tput setaf 1) # ANSI red
green=$(tput setaf 2) # ANSI green
nc=$(tput sgr0) # No Color
else
red=''
green=''
nc='' # No Color
fi
fi
# Only allow script to run as root
if (( EUID != 0 )); then
echo -e "${red}This script needs to be run as root. Try again with 'sudo $0'${nc}"
exit 1
fi
mkdir -p /opt/piavpn-manual
if [[ -z $PIA_USER || -z $PIA_PASS ]]; then
echo "If you want this script to automatically get a token from the Meta"
echo "service, please add the variables PIA_USER and PIA_PASS. Example:"
echo "$ PIA_USER=p0123456 PIA_PASS=xxx ./get_token.sh"
exit 1
fi
echo -n "Checking login credentials..."
generateTokenResponse=$(curl -s --location --request POST \
'https://www.privateinternetaccess.com/api/client/v2/token' \
--form "username=$PIA_USER" \
--form "password=$PIA_PASS" )
if [ "$(echo "$generateTokenResponse" | jq -r '.token')" == "" ]; then
echo
echo
echo -e "${red}Could not authenticate with the login credentials provided!${nc}"
echo
exit
fi
echo -e "${green}OK!"
echo
token=$(echo "$generateTokenResponse" | jq -r '.token')
tokenExpiration=$(timeout_timestamp)
tokenLocation=/opt/piavpn-manual/token
echo -e "PIA_TOKEN=$token${nc}"
echo "$token" > "$tokenLocation" || exit 1
echo "$tokenExpiration" >> "$tokenLocation"
echo
echo "This token will expire in 24 hours, on $tokenExpiration."
echo

4
openvpn_config/openvpn_down.sh Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
# Remove process and route information when connection closes
rm -rf /opt/piavpn-manual/pia_pid /opt/pia-manual/route_info

View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
# Remove process and route information when connection closes
rm -rf /opt/piavpn-manual/pia_pid /opt/pia-manual/route_info
# Replace resolv.conf with original stored as backup
cat /opt/piavpn-manual/resolv_conf_backup > /etc/resolv.conf

4
openvpn_config/openvpn_up.sh Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
# Write gateway IP for reference
echo "$route_vpn_gateway" > /opt/piavpn-manual/route_info

View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
# Write gateway IP for reference
echo "$route_vpn_gateway" > /opt/piavpn-manual/route_info
# Back up resolv.conf and create new one with PIA DNS
cat /etc/resolv.conf > /opt/piavpn-manual/resolv_conf_backup
echo "# Generated by /connect_to_openvpn_with_token.sh
nameserver 10.0.0.241" > /etc/resolv.conf

View File

@ -0,0 +1,56 @@
client
dev tun06
resolv-retry infinite
nobind
persist-key
persist-tun
cipher aes-128-cbc
auth sha1
tls-client
remote-cert-tls server
auth-user-pass /opt/piavpn-manual/credentials
compress
verb 1
reneg-sec 0
<ca>
-----BEGIN CERTIFICATE-----
MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYD
VQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNV
BAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIElu
dGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3Mx
IDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkB
FiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1
MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
EzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQg
QWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UE
AxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50
ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVy
bmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXD
L1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzX
lH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWp
cdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/
8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB
/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RC
OfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tL
y8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZO
sqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpM
b3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4G
A1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUg
SW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2Vz
czEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5j
b22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAn
a5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xU
ryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK3
7pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyC
GohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz
1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUt
YDQ8z9v+DMO6iwyIDRiU
-----END CERTIFICATE-----
</ca>
disable-occ
script-security 2
up /opt/piavpn-manual/openvpn_up.sh
down /opt/piavpn-manual/openvpn_down.sh

View File

@ -0,0 +1,66 @@
client
dev tun06
resolv-retry infinite
nobind
persist-key
persist-tun
cipher aes-256-cbc
auth sha256
tls-client
remote-cert-tls server
auth-user-pass /opt/piavpn-manual/credentials
compress
verb 1
reneg-sec 0
<ca>
-----BEGIN CERTIFICATE-----
MIIHqzCCBZOgAwIBAgIJAJ0u+vODZJntMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYD
VQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNV
BAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIElu
dGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3Mx
IDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkB
FiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzQw
MzNaFw0zNDA0MTIxNzQwMzNaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
EzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQg
QWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UE
AxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50
ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVy
bmV0YWNjZXNzLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALVk
hjumaqBbL8aSgj6xbX1QPTfTd1qHsAZd2B97m8Vw31c/2yQgZNf5qZY0+jOIHULN
De4R9TIvyBEbvnAg/OkPw8n/+ScgYOeH876VUXzjLDBnDb8DLr/+w9oVsuDeFJ9K
V2UFM1OYX0SnkHnrYAN2QLF98ESK4NCSU01h5zkcgmQ+qKSfA9Ny0/UpsKPBFqsQ
25NvjDWFhCpeqCHKUJ4Be27CDbSl7lAkBuHMPHJs8f8xPgAbHRXZOxVCpayZ2SND
fCwsnGWpWFoMGvdMbygngCn6jA/W1VSFOlRlfLuuGe7QFfDwA0jaLCxuWt/BgZyl
p7tAzYKR8lnWmtUCPm4+BtjyVDYtDCiGBD9Z4P13RFWvJHw5aapx/5W/CuvVyI7p
Kwvc2IT+KPxCUhH1XI8ca5RN3C9NoPJJf6qpg4g0rJH3aaWkoMRrYvQ+5PXXYUzj
tRHImghRGd/ydERYoAZXuGSbPkm9Y/p2X8unLcW+F0xpJD98+ZI+tzSsI99Zs5wi
jSUGYr9/j18KHFTMQ8n+1jauc5bCCegN27dPeKXNSZ5riXFL2XX6BkY68y58UaNz
meGMiUL9BOV1iV+PMb7B7PYs7oFLjAhh0EdyvfHkrh/ZV9BEhtFa7yXp8XR0J6vz
1YV9R6DYJmLjOEbhU8N0gc3tZm4Qz39lIIG6w3FDAgMBAAGjggFUMIIBUDAdBgNV
HQ4EFgQUrsRtyWJftjpdRM0+925Y6Cl08SUwggEfBgNVHSMEggEWMIIBEoAUrsRt
yWJftjpdRM0+925Y6Cl08SWhge6kgeswgegxCzAJBgNVBAYTAlVTMQswCQYDVQQI
EwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRl
cm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAw
HgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0
ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRl
aW50ZXJuZXRhY2Nlc3MuY29tggkAnS7684Nkme0wDAYDVR0TBAUwAwEB/zANBgkq
hkiG9w0BAQ0FAAOCAgEAJsfhsPk3r8kLXLxY+v+vHzbr4ufNtqnL9/1Uuf8NrsCt
pXAoyZ0YqfbkWx3NHTZ7OE9ZRhdMP/RqHQE1p4N4Sa1nZKhTKasV6KhHDqSCt/dv
Em89xWm2MVA7nyzQxVlHa9AkcBaemcXEiyT19XdpiXOP4Vhs+J1R5m8zQOxZlV1G
tF9vsXmJqWZpOVPmZ8f35BCsYPvv4yMewnrtAC8PFEK/bOPeYcKN50bol22QYaZu
LfpkHfNiFTnfMh8sl/ablPyNY7DUNiP5DRcMdIwmfGQxR5WEQoHL3yPJ42LkB5zs
6jIm26DGNXfwura/mi105+ENH1CaROtRYwkiHb08U6qLXXJz80mWJkT90nr8Asj3
5xN2cUppg74nG3YVav/38P48T56hG1NHbYF5uOCske19F6wi9maUoto/3vEr0rnX
JUp2KODmKdvBI7co245lHBABWikk8VfejQSlCtDBXn644ZMtAdoxKNfR2WTFVEwJ
iyd1Fzx0yujuiXDROLhISLQDRjVVAvawrAtLZWYK31bY7KlezPlQnl/D9Asxe85l
8jO5+0LdJ6VyOs/Hd4w52alDW/MFySDZSfQHMTIc30hLBJ8OnCEIvluVQQ2UQvoW
+no177N9L2Y+M9TcTA62ZyMXShHQGeh20rb4kK8f+iFX8NxtdHVSkxMEFSfDDyQ=
-----END CERTIFICATE-----
</ca>
disable-occ
script-security 2
up /opt/piavpn-manual/openvpn_up.sh
down /opt/piavpn-manual/openvpn_down.sh

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
# Copyright (C) 2020 Private Internet Access, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
@ -19,21 +19,48 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# This function allows you to check if the required tools have been installed.
check_tool() {
cmd=$1
if ! command -v "$cmd" >/dev/null; then
echo "$cmd could not be found"
echo "Please install $cmd"
exit 1
fi
}
# Now we call the function to make sure we can use curl and jq.
check_tool curl
check_tool jq
# Check if the mandatory environment variables are set.
if [[ ! $PF_GATEWAY || ! $PIA_TOKEN ]]; then
echo This script requires 3 env vars:
echo PF_GATEWAY - the IP of your gateway
echo PF_HOSTNAME - name of the host used for SSL/TLS certificate verification
echo PIA_TOKEN - the token you use to connect to the vpn services
if [[ -z $PF_GATEWAY || -z $PIA_TOKEN || -z $PF_HOSTNAME ]]; then
echo "This script requires 3 env vars:"
echo "PF_GATEWAY - the IP of your gateway"
echo "PF_HOSTNAME - name of the host used for SSL/TLS certificate verification"
echo "PIA_TOKEN - the token you use to connect to the vpn services"
echo
echo An easy solution is to just run get_region_and_token.sh
echo as it will guide you through getting the best server and
echo also a token. Detailed information can be found here:
echo https://github.com/pia-foss/manual-connections
echo "An easy solution is to just run get_region_and_token.sh"
echo "as it will guide you through getting the best server and"
echo "also a token. Detailed information can be found here:"
echo "https://github.com/pia-foss/manual-connections"
exit 1
fi
# Check if terminal allows output, if yes, define colors for output
if [[ -t 1 ]]; then
ncolors=$(tput colors)
if [[ -n $ncolors && $ncolors -ge 8 ]]; then
red=$(tput setaf 1) # ANSI red
green=$(tput setaf 2) # ANSI green
nc=$(tput sgr0) # No Color
else
red=''
green=''
nc='' # No Color
fi
fi
# The port forwarding system has required two variables:
# PAYLOAD: contains the token, the port and the expiration date
# SIGNATURE: certifies the payload originates from the PIA network.
@ -54,48 +81,50 @@ fi
# If you already have a signature, and you would like to re-use that port,
# save the payload_and_signature received from your previous request
# in the env var PAYLOAD_AND_SIGNATURE, and that will be used instead.
if [[ ! $PAYLOAD_AND_SIGNATURE ]]; then
echo "Getting new signature..."
if [[ -z $PAYLOAD_AND_SIGNATURE ]]; then
echo
echo -n "Getting new signature... "
payload_and_signature="$(curl -s -m 5 \
--connect-to "$PF_HOSTNAME::$PF_GATEWAY:" \
--cacert "ca.rsa.4096.crt" \
-G --data-urlencode "token=${PIA_TOKEN}" \
"https://${PF_HOSTNAME}:19999/getSignature")"
else
payload_and_signature="$PAYLOAD_AND_SIGNATURE"
echo "Using the following payload_and_signature from the env var:"
payload_and_signature=$PAYLOAD_AND_SIGNATURE
echo -n "Checking the payload_and_signature from the env var... "
fi
echo "$payload_and_signature"
export payload_and_signature
# Check if the payload and the signature are OK.
# If they are not OK, just stop the script.
if [ "$(echo "$payload_and_signature" | jq -r '.status')" != "OK" ]; then
echo "The payload_and_signature variable does not contain an OK status."
if [[ $(echo "$payload_and_signature" | jq -r '.status') != "OK" ]]; then
echo -e "${red}The payload_and_signature variable does not contain an OK status.${nc}"
exit 1
fi
echo -e "${green}OK!${nc}"
# We need to get the signature out of the previous response.
# The signature will allow the us to bind the port on the server.
signature="$(echo "$payload_and_signature" | jq -r '.signature')"
signature=$(echo "$payload_and_signature" | jq -r '.signature')
# The payload has a base64 format. We need to extract it from the
# previous reponse and also get the following information out:
# previous response and also get the following information out:
# - port: This is the port you got access to
# - expires_at: this is the date+time when the port expires
payload="$(echo "$payload_and_signature" | jq -r '.payload')"
port="$(echo "$payload" | base64 -d | jq -r '.port')"
payload=$(echo "$payload_and_signature" | jq -r '.payload')
port=$(echo "$payload" | base64 -d | jq -r '.port')
# The port normally expires after 2 months. If you consider
# 2 months is not enough for your setup, please open a ticket.
expires_at="$(echo "$payload" | base64 -d | jq -r '.expires_at')"
expires_at=$(echo "$payload" | base64 -d | jq -r '.expires_at')
# Display some information on the screen for the user.
echo "The signature is OK.
echo -ne "
Signature ${green}$signature${nc}
Payload ${green}$payload${nc}
--> The port is $port and it will expire on $expires_at. <--
--> The port is ${green}$port${nc} and it will expire on ${red}$expires_at${nc}. <--
Trying to bind the port..."
Trying to bind the port... "
# Now we have all required data to create a request to bind the port.
# We will repeat this request every 15 minutes, in order to keep the port
@ -108,17 +137,19 @@ while true; do
--data-urlencode "payload=${payload}" \
--data-urlencode "signature=${signature}" \
"https://${PF_HOSTNAME}:19999/bindPort")"
echo "$bind_port_response"
echo -e "${green}OK!${nc}"
# If port did not bind, just exit the script.
# This script will exit in 2 months, since the port will expire.
export bind_port_response
if [ "$(echo "$bind_port_response" | jq -r '.status')" != "OK" ]; then
echo "The API did not return OK when trying to bind port. Exiting."
if [[ $(echo "$bind_port_response" | jq -r '.status') != "OK" ]]; then
echo -e "${red}The API did not return OK when trying to bind port... Exiting.${nc}"
exit 1
fi
echo Port $port refreshed on $(date). \
This port will expire on $(date --date="$expires_at")
echo -e Forwarded port'\t'"${green}$port${nc}"
echo -e Refreshed on'\t'"${green}$(date)${nc}"
echo -e Expires on'\t'"${red}$(date --date="$expires_at")${nc}"
echo -e "\n${green}This script will need to remain active to use port forwarding, and will refresh every 15 minutes.${nc}\n"
# sleep 15 minutes
sleep 900

509
run_setup.sh Executable file
View File

@ -0,0 +1,509 @@
#!/usr/bin/env bash
# Copyright (C) 2020 Private Internet Access, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Check if terminal allows output, if yes, define colors for output
if [[ -t 1 ]]; then
ncolors=$(tput colors)
if [[ -n $ncolors && $ncolors -ge 8 ]]; then
red=$(tput setaf 1) # ANSI red
green=$(tput setaf 2) # ANSI green
nc=$(tput sgr0) # No Color
else
red=''
green=''
nc='' # No Color
fi
fi
# Variables to use for validating input
intCheck='^[0-9]+$'
floatCheck='^[0-9]+([.][0-9]+)?$'
# Only allow script to run as root
if (( EUID != 0 )); then
echo -e "${red}This script needs to be run as root. Try again with 'sudo $0'${nc}"
exit 1
fi
# Erase previous authentication token if present
rm -f /opt/piavpn-manual/token /opt/piavpn-manual/latencyList
# Retry login if no token is generated
while :; do
while :; do
# Check for in-line definition of $PIA_USER
if [[ -z $PIA_USER ]]; then
echo
read -r -p "PIA username (p#######): " PIA_USER
fi
# Confirm format of PIA_USER input
unPrefix=${PIA_USER:0:1}
unSuffix=${PIA_USER:1}
if [[ -z $PIA_USER ]]; then
echo -e "\n${red}You must provide input.${nc}"
elif [[ ${#PIA_USER} != 8 ]]; then
echo -e "\n${red}A PIA username is always 8 characters long.${nc}"
elif [[ $unPrefix != "P" ]] && [[ $unPrefix != "p" ]]; then
echo -e "\n${red}A PIA username must start with \"p\".${nc}"
elif ! [[ $unSuffix =~ $intCheck ]]; then
echo -e "\n${red}Username formatting is always p#######!${nc}"
else
echo -e "\n${green}PIA_USER=$PIA_USER${nc}"
break
fi
PIA_USER=""
done
export PIA_USER
while :; do
# Check for in-line definition of $PIA_PASS
if [[ -z $PIA_PASS ]]; then
echo
echo -n "PIA password: "
read -r -s PIA_PASS
echo
fi
# Confirm format of PIA_PASS input
if [[ -z $PIA_PASS ]]; then
echo -e "\n${red}You must provide input.${nc}"
elif [[ ${#PIA_PASS} -lt 8 ]]; then
echo -e "\n${red}A PIA password is always a minimum of 8 characters long.${nc}"
else
echo -e "\n${green}PIA_PASS input received.${nc}"
echo
break
fi
PIA_PASS=""
done
export PIA_PASS
# Confirm credentials and generate token
./get_token.sh
tokenLocation="/opt/piavpn-manual/token"
# If the script failed to generate an authentication token, the script will exit early.
if [[ ! -f $tokenLocation ]]; then
read -r -p "Do you want to try again ([N]o/[y]es): " tryAgain
if ! echo "${tryAgain:0:1}" | grep -iq y; then
exit 1
fi
PIA_USER=""
PIA_PASS=""
else
PIA_TOKEN=$( awk 'NR == 1' /opt/piavpn-manual/token )
export PIA_TOKEN
rm -f /opt/piavpn-manual/token
break
fi
done
# Check for in-line definition of $DIP_TOKEN
if [[ -z $DIP_TOKEN ]]; then
# Check for dedicated IP
echo -n "Do you want to use a dedicated IP token ([N]o/[y]es): "
read useDIP
echo
pfOption="true"
else
if echo ${DIP_TOKEN:0:1} | grep -iq n; then
useDIP="no"
echo -e "${red}Not using a dedicated IP.${nc}"
echo
DIP_TOKEN=""
else
useDIP="yes"
fi
fi
if echo ${useDIP:0:1} | grep -iq y; then
useDIP="true"
while :; do
while :; do
# Check for in-line definition of $DIP_TOKEN
if [[ -z $DIP_TOKEN ]]; then
read -p "Dedicated token (DIP#############################): " DIP_TOKEN
fi
# Confirm format of DIP_TOKEN input
dipPrefix=$( echo ${DIP_TOKEN:0:3} )
if [[ -z "$DIP_TOKEN" ]]; then
echo -e "\n${red}You must provide input.${nc}"
elif [[ ${#DIP_TOKEN} != 32 ]]; then
echo -e "\n${red}A dedicated IP token is always 32 characters long.${nc}"
elif [[ $dipPrefix != "DIP" ]]; then
echo -e "\n${red}A dedicated IP token must start with \"DIP\".${nc}"
else
break
fi
echo
DIP_TOKEN=""
done
export DIP_TOKEN
# Confirm DIP_TOKEN and retrieve connection details
./get_dip.sh
dipDetails="/opt/piavpn-manual/dipAddress"
# If the script failed to generate retrieve dedicated IP information, the script will exit early.
if [ ! -f "$dipDetails" ]; then
read -p "Do you want to try again ([N]o/[y]es): " tryAgain
echo
if ! echo ${tryAgain:0:1} | grep -iq y; then
exit 1
fi
DIP_TOKEN=""
else
dipAddress=$( awk 'NR == 1' /opt/piavpn-manual/dipAddress )
dipHostname=$( awk 'NR == 2' /opt/piavpn-manual/dipAddress)
dipKey=$( awk 'NR == 3' /opt/piavpn-manual/dipAddress )
pfOption=$( awk 'NR == 5' /opt/piavpn-manual/dipAddress )
rm -f /opt/piavpn-manual/dipAddress
break
fi
done
fi
if [[ -z $DIP_TOKEN ]]; then
echo "${green}DIP_TOKEN=none${nc}"
else
echo "${green}DIP_TOKEN=$DIP_TOKEN${nc}"
fi
echo
# Erase previous connection details if present
rm -f /opt/piavpn-manual/token /opt/piavpn-manual/latencyList
# Prompt for port forwarding if no DIP or DIP allows it
if [[ $pfOption = "false" ]]; then
PIA_PF="false"
fi
# Check for in-line definition of PIA_PF and prompt for input
if [[ -z $PIA_PF ]]; then
echo -n "Do you want a forwarding port assigned ([N]o/[y]es): "
read -r portForwarding
echo
if echo "${portForwarding:0:1}" | grep -iq y; then
PIA_PF="true"
fi
fi
if [[ $PIA_PF != "true" ]]; then
PIA_PF="false"
fi
export PIA_PF
echo -e "${green}PIA_PF=$PIA_PF${nc}"
echo
# Check for in-line definition of DISABLE_IPV6 and prompt for input
if [[ -z $DISABLE_IPV6 ]]; then
echo "Having active IPv6 connections might compromise security by allowing"
echo "split tunnel connections that run outside the VPN tunnel."
echo -n "Do you want to disable IPv6? (Y/n): "
read -r DISABLE_IPV6
echo
fi
if echo "${DISABLE_IPV6:0:1}" | grep -iq n; then
echo -e "${red}IPv6 settings have not been altered.
${nc}"
else
echo -e "The variable ${green}DISABLE_IPV6=$DISABLE_IPV6${nc}, does not start with 'n' for 'no'.
${green}Defaulting to yes.${nc}
"
sysctl -w net.ipv6.conf.all.disable_ipv6=1
sysctl -w net.ipv6.conf.default.disable_ipv6=1
echo
echo -e "${red}IPv6 has been disabled${nc}, you can ${green}enable it again with: "
echo "sysctl -w net.ipv6.conf.all.disable_ipv6=0"
echo "sysctl -w net.ipv6.conf.default.disable_ipv6=0"
echo -e "${nc}"
fi
# Only prompt for server selection if no DIP has been specified
if [[ -z $DIP_TOKEN ]]; then
# Input validation and check for conflicting declarations of AUTOCONNECT and PREFERRED_REGION
# If both variables are set, AUTOCONNECT has superiority and PREFERRED_REGION is ignored
if [[ -z $AUTOCONNECT ]]; then
echo "AUTOCONNECT was not declared."
echo
selectServer="ask"
elif echo "${AUTOCONNECT:0:1}" | grep -iq f; then
if [[ $AUTOCONNECT != "false" ]]; then
echo -e "The variable ${green}AUTOCONNECT=$AUTOCONNECT${nc}, starts with 'f' for 'false'."
AUTOCONNECT="false"
echo -e "Updated ${green}AUTOCONNECT=$AUTOCONNECT${nc}"
echo
fi
selectServer="yes"
else
if [[ $AUTOCONNECT != "true" ]]; then
echo -e "The variable ${green}AUTOCONNECT=$AUTOCONNECT${nc}, does not start with 'f' for 'false'."
AUTOCONNECT="true"
echo -e "Updated ${green}AUTOCONNECT=$AUTOCONNECT${nc}"
echo
fi
if [[ -z $PREFERRED_REGION ]]; then
echo -e "${green}AUTOCONNECT=true${nc}"
echo
else
echo
echo "AUTOCONNECT supersedes in-line definitions of PREFERRED_REGION."
echo -e "${red}PREFERRED_REGION=$PREFERRED_REGION will be ignored.${nc}
"
PREFERRED_REGION=""
fi
selectServer="no"
fi
# Prompt the user to specify a server or auto-connect to the lowest latency
while :; do
if [[ -z $PREFERRED_REGION ]]; then
# If autoconnect is not set, prompt the user to specify a server or auto-connect to the lowest latency
if [[ $selectServer == "ask" ]]; then
echo -n "Do you want to manually select a server, instead of auto-connecting to the
server with the lowest latency ([N]o/[y]es): "
read -r selectServer
echo
fi
# Call the region script with input to create an ordered list based upon latency
# When $PREFERRED_REGION is set to none, get_region.sh will generate a list of servers
# that meet the latency requirements specified by $MAX_LATENCY.
# When $VPN_PROTOCOL is set to no, get_region.sh will sort that list of servers
# to allow for numeric selection, or an easy manual review of options.
if echo "${selectServer:0:1}" | grep -iq y; then
# This sets the maximum allowed latency in seconds.
# All servers that respond slower than this will be ignored.
if [[ -z $MAX_LATENCY ]]; then
echo -n "With no input, the maximum allowed latency will be set to 0.05s (50ms).
If your connection has high latency, you may need to increase this value.
For example, you can try 0.2 for 200ms allowed latency.
"
else
latencyInput=$MAX_LATENCY
fi
# Assure that input is numeric and properly formatted.
MAX_LATENCY=0.05 # default
while :; do
if [[ -z $latencyInput ]]; then
read -r -p "Custom latency (no input required for 50ms): " latencyInput
echo
fi
customLatency=0
customLatency+=$latencyInput
if [[ -z $latencyInput ]]; then
break
elif [[ $latencyInput == 0 ]]; then
echo -e "${red}Latency input must not be zero.${nc}\n"
elif ! [[ $customLatency =~ $floatCheck ]]; then
echo -e "${red}Latency input must be numeric.${nc}\n"
elif [[ $latencyInput =~ $intCheck ]]; then
MAX_LATENCY=$latencyInput
break
else
MAX_LATENCY=$customLatency
break
fi
latencyInput=""
done
export MAX_LATENCY
echo -e "${green}MAX_LATENCY=$MAX_LATENCY${nc}"
PREFERRED_REGION="none"
export PREFERRED_REGION
VPN_PROTOCOL="no"
export VPN_PROTOCOL
VPN_PROTOCOL=no ./get_region.sh
if [[ -s /opt/piavpn-manual/latencyList ]]; then
# Output the ordered list of servers that meet the latency specification $MAX_LATENCY
echo -e "Ordered list of servers with latency less than ${green}$MAX_LATENCY${nc} seconds:"
i=0
while read -r line; do
i=$((i+1))
time=$( awk 'NR == '$i' {print $1}' /opt/piavpn-manual/latencyList )
id=$( awk 'NR == '$i' {print $2}' /opt/piavpn-manual/latencyList )
ip=$( awk 'NR == '$i' {print $3}' /opt/piavpn-manual/latencyList )
location1=$( awk 'NR == '$i' {print $4}' /opt/piavpn-manual/latencyList )
location2=$( awk 'NR == '$i' {print $5}' /opt/piavpn-manual/latencyList )
location3=$( awk 'NR == '$i' {print $6}' /opt/piavpn-manual/latencyList )
location4=$( awk 'NR == '$i' {print $7}' /opt/piavpn-manual/latencyList )
location="$location1 $location2 $location3 $location4"
printf "%3s : %-8s %-15s %23s" $i "$time" "$ip" "$id"
echo " - $location"
done < /opt/piavpn-manual/latencyList
echo
# Receive input to specify the server to connect to manually
while :; do
read -r -p "Input the number of the server you want to connect to ([1]-[$i]) : " serverSelection
if [[ -z $serverSelection ]]; then
echo -e "\n${red}You must provide input.${nc}\n"
elif ! [[ $serverSelection =~ $intCheck ]]; then
echo -e "\n${red}You must enter a number.${nc}\n"
elif [[ $serverSelection -lt 1 ]]; then
echo -e "\n${red}You must enter a number greater than 1.${nc}\n"
elif [[ $serverSelection -gt $i ]]; then
echo -e "\n${red}You must enter a number between 1 and $i.${nc}\n"
else
PREFERRED_REGION=$( awk 'NR == '"$serverSelection"' {print $2}' /opt/piavpn-manual/latencyList )
echo
echo -e "${green}PREFERRED_REGION=$PREFERRED_REGION${nc}"
break
fi
done
# Write the serverID for use when connecting, and display the serverName for user confirmation
export PREFERRED_REGION
echo
break
else
exit 1
fi
else
echo -e "${green}You will auto-connect to the server with the lowest latency.${nc}"
echo
break
fi
else
# Validate in-line declaration of PREFERRED_REGION; if invalid remove input to initiate prompts
echo "Region input is : $PREFERRED_REGION"
export PREFERRED_REGION
VPN_PROTOCOL=no ./get_region.sh
if [[ $? != 1 ]]; then
break
fi
PREFERRED_REGION=""
fi
done
fi
if [[ -z $VPN_PROTOCOL ]]; then
VPN_PROTOCOL="none"
fi
# This section asks for user connection preferences
case $VPN_PROTOCOL in
openvpn)
VPN_PROTOCOL="openvpn_udp_standard"
;;
wireguard | openvpn_udp_standard | openvpn_udp_strong | openvpn_tcp_standard | openvpn_tcp_strong)
;;
none | *)
echo -n "Connection method ([W]ireguard/[o]penvpn): "
read -r connection_method
echo
VPN_PROTOCOL="wireguard"
if echo "${connection_method:0:1}" | grep -iq o; then
echo -n "Connection method ([U]dp/[t]cp): "
read -r protocolInput
echo
protocol="udp"
if echo "${protocolInput:0:1}" | grep -iq t; then
protocol="tcp"
fi
echo "Higher levels of encryption trade performance for security. "
echo -n "Do you want to use strong encryption ([N]o/[y]es): "
read -r strongEncryption
echo
encryption="standard"
if echo "${strongEncryption:0:1}" | grep -iq y; then
encryption="strong"
fi
VPN_PROTOCOL="openvpn_${protocol}_${encryption}"
fi
;;
esac
export VPN_PROTOCOL
echo -e "${green}VPN_PROTOCOL=$VPN_PROTOCOL
${nc}"
# Check for the required presence of resolvconf for setting DNS on wireguard connections
setDNS="yes"
if ! command -v resolvconf &>/dev/null && [[ $VPN_PROTOCOL == "wireguard" ]]; then
echo -e "${red}The resolvconf package could not be found."
echo "This script can not set DNS for you and you will"
echo -e "need to invoke DNS protection some other way.${nc}"
echo
setDNS="no"
fi
# Check for in-line definition of PIA_DNS and prompt for input
if [[ $setDNS == "yes" ]]; then
if [[ -z $PIA_DNS ]]; then
echo "Using third party DNS could allow DNS monitoring."
echo -n "Do you want to force PIA DNS ([Y]es/[n]o): "
read -r setDNS
echo
PIA_DNS="true"
if echo "${setDNS:0:1}" | grep -iq n; then
PIA_DNS="false"
fi
fi
elif [[ $PIA_DNS != "true" || $setDNS == "no" ]]; then
PIA_DNS="false"
fi
export PIA_DNS
echo -e "${green}PIA_DNS=$PIA_DNS${nc}"
CONNECTION_READY="true"
export CONNECTION_READY
if [[ -z $DIP_TOKEN ]]; then
./get_region.sh
elif [[ $VPN_PROTOCOL == wireguard ]]; then
echo
echo -e "You will be connecting with ${green}WG_SERVER_IP=$dipAddress${nc} using"
echo -e "${green}VPN_PROTOCOL=wireguard${nc}, so we will automatically connect to WireGuard,"
echo "by running this command:"
echo -e "$ ${green}PIA_PF=$PIA_PF PIA_TOKEN=$PIA_TOKEN" \\
echo "DIP_TOKEN=$DIP_TOKEN" \\
echo "WG_SERVER_IP=$dipAddress WG_HOSTNAME=$dipHostname" \\
echo -e "./connect_to_wireguard_with_token.sh${nc}"
echo
PIA_PF=$PIA_PF PIA_TOKEN=$PIA_TOKEN DIP_TOKEN=$DIP_TOKEN \
WG_SERVER_IP=$dipAddress WG_HOSTNAME=$dipHostname \
./connect_to_wireguard_with_token.sh
rm -f /opt/piavpn-manual/latencyList
exit 0
elif [[ $VPN_PROTOCOL == openvpn* ]]; then
echo
echo "The dedicated IP connection will be started with"
echo -e "${green}VPN_PROTOCOL=$VPN_PROTOCOL${nc}, so we will automatically"
echo "connect to OpenVPN, by running this command:"
echo -e "$ ${green}PIA_PF=$PIA_PF PIA_TOKEN=$PIA_TOKEN" \\
echo "DIP_TOKEN=$DIP_TOKEN OVPN_SERVER_IP=$dipAddress" \\
echo "OVPN_HOSTNAME=$dipHostname" \\
echo "CONNECTION_SETTINGS=$VPN_PROTOCOL" \\
echo -e "./connect_to_openvpn_with_token.sh${nc}"
echo
PIA_PF=$PIA_PF PIA_TOKEN=$PIA_TOKEN \
DIP_TOKEN=$DIP_TOKEN OVPN_SERVER_IP=$dipAddress \
OVPN_HOSTNAME=$dipHostname \
CONNECTION_SETTINGS=$VPN_PROTOCOL \
./connect_to_openvpn_with_token.sh
rm -f /opt/piavpn-manual/latencyList
exit 0
fi