refactoring and readme improvements

This commit is contained in:
gunix 2020-09-19 00:08:43 +03:00
parent 09dee21d40
commit b88e135b89
4 changed files with 165 additions and 101 deletions

View File

@ -6,14 +6,28 @@ This repository contains documentation on how to create native WireGuard connect
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 `wireguard_and_pf.sh` to create a WireGuard connection with/without PF
* 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
```
### Dependencies
In order for the scripts to work (probably even if you do a manual setup), you will need the following packages:
* `curl`
* `jq`
* `wireguard-tools` (which give you the `wg-quick` utility)
* (only for WireGuard) `wireguard-tools` and wireguard kernel module
* (only for OpenVPN) `openvpn`
### Confirmed distributions
The functionality of the scripts within this repository has been tested and confirmed on the following distributions:
* Arch
* Artix
* Fedora 32
* Ubuntu 20.04
## PIA Port Forwarding
@ -26,9 +40,10 @@ This service can be used only AFTER establishing a VPN connection.
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.
Here is a list of scripts you could find useful:
* [region and token script](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 `WG_AUTOCONNECT=true`.
* [wireguard and pf script](wireguard_and_pf.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.
* OpenVPN automation is not ready yet, however will be available soon enough.
* [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 `WG_AUTOCONNECT=true`.
* [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.
## Manual setup of PF
@ -90,3 +105,6 @@ listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 byt
22:44:01.510804 IP 81.180.227.170.33884 > 10.4.143.34.47047: Flags [S], seq 906854496, win 64860, options [mss 1380,sackOK,TS val 2608022390 ecr 0,nop,wscale 7], length 0
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
```
## License
This project is licensed under the [MIT (Expat) license](https://choosealicense.com/licenses/mit/), which can be found [here](/LICENSE).

View File

@ -127,93 +127,14 @@ fi
echo "
This script got started with PIA_PF=true.
Starting procedure to enable port forwarding."
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
"
# 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.
# Basically PAYLOAD+SIGNATURE=PORT. You can use the same PORT on all servers.
# The system has been designed to be completely decentralized, so that your
# privacy is protected even if you want to host services on your systems.
# You can get your PAYLOAD+SIGNATURE with a simple curl request to any VPN
# gateway, no matter what protocol you are using.
# Since this is the script for wireguard, you can just get the gateway
# from the JSON response you got at the previous step from the Wireguard API.
gateway="$(echo "$wireguard_json" | jq -r '.server_vip')"
# Get the payload and the signature from the PF API. This will grant you
# access to a random port, which you can activate on any server you connect to.
# 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..."
payload_and_signature="$(curl -s -m 5 \
--connect-to "$WG_HOSTNAME::$gateway:" \
--cacert "ca.rsa.4096.crt" \
-G --data-urlencode "token=${WG_TOKEN}" \
"https://${WG_HOSTNAME}:19999/getSignature")"
else
payload_and_signature="$PAYLOAD_AND_SIGNATURE"
echo "Using the following 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."
exit 1
fi
# 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')"
# The payload has a base64 format. We need to extract it from the
# previous reponse 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')"
# 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')"
# Display some information on the screen for the user.
echo "The signature is OK.
--> The port is $port and it will expire on $expires_at. <--
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
# alive. The servers have no mechanism to track your activity, so they
# will just delete the port forwarding if you don't send keepalives.
while true; do
bind_port_response="$(curl -Gs -m 5 \
--connect-to "$WG_HOSTNAME::$gateway:" \
--cacert "ca.rsa.4096.crt" \
--data-urlencode "payload=${payload}" \
--data-urlencode "signature=${signature}" \
"https://${WG_HOSTNAME}:19999/bindPort")"
echo "$bind_port_response"
# 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."
exit 1
fi
echo Port $port refreshed on $(date). \
This port will expire on $(date --date="$expires_at")
# sleep 15 minutes
sleep 900
done
PIA_TOKEN=$WG_TOKEN \
PF_GATEWAY="$(echo "$wireguard_json" | jq -r '.server_vip')" \
PF_HOSTNAME="$WG_HOSTNAME" \
./port_forwarding.sh

View File

@ -136,16 +136,16 @@ token="$(echo "$generateTokenResponse" | jq -r '.token')"
echo "This token will expire in 24 hours.
"
if [ "$WG_AUTOCONNECT" != true ]; then
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 WG_AUTOCONNECT=true. You can
echo region, please run the script with the env var PIA_AUTOCONNECT=wireguard. You can
echo also specify the env var PIA_PF=true to get port forwarding. Example:
echo $ PIA_USER=p0123456 PIA_PASS=xxx \
WG_AUTOCONNECT=true PIA_PF=true ./sort_regions_by_latency.sh
PIA_AUTOCONNECT=true PIA_PF=true ./sort_regions_by_latency.sh
echo
echo You can connect by running:
echo You can also connect manually by running:
echo WG_TOKEN=\"$token\" WG_SERVER_IP=$bestServer_WG_IP \
WG_HOSTNAME=$bestServer_WG_hostname ./wireguard_and_pf.sh
WG_HOSTNAME=$bestServer_WG_hostname ./connect_to_wireguard_with_token.sh
exit
fi
@ -153,7 +153,7 @@ if [ "$PIA_PF" != true ]; then
PIA_PF="false"
fi
echo "The ./get_region_and_token.sh script got started with WG_AUTOCONNECT=true,
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 \\
@ -161,4 +161,4 @@ $ WG_TOKEN=\"$token\" \\
"
PIA_PF=$PIA_PF WG_TOKEN="$token" WG_SERVER_IP=$bestServer_WG_IP \
WG_HOSTNAME=$bestServer_WG_hostname ./wireguard_and_pf.sh
WG_HOSTNAME=$bestServer_WG_hostname ./connect_to_wireguard_with_token.sh

125
port_forwarding.sh Executable file
View File

@ -0,0 +1,125 @@
#!/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.
# Check if the mandatory environment variables are set.
if [[ ! $PF_GATEWAY || ! $PIA_TOKEN ]]; then
echo This script requires 2 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
exit 1
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.
# Basically PAYLOAD+SIGNATURE=PORT. You can use the same PORT on all servers.
# The system has been designed to be completely decentralized, so that your
# privacy is protected even if you want to host services on your systems.
# You can get your PAYLOAD+SIGNATURE with a simple curl request to any VPN
# gateway, no matter what protocol you are using. Considering WireGuard has
# already been automated in this repo, here is a command to help you get
# your gateway if you have an active OpenVPN connection:
# $ ip route | head -1 | grep tun | awk '{ print $3 }'
# This section will get updated as soon as we created the OpenVPN script.
# Get the payload and the signature from the PF API. This will grant you
# access to a random port, which you can activate on any server you connect to.
# 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..."
payload_and_signature="$(curl -s -m 5 \
--connect-to "$PF_HOSTNAME::$PF_GATEWAY:" \
--cacert "ca.rsa.4096.crt" \
-G --data-urlencode "token=${WG_TOKEN}" \
"https://${PF_HOSTNAME}:19999/getSignature")"
else
payload_and_signature="$PAYLOAD_AND_SIGNATURE"
echo "Using the following 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."
exit 1
fi
# 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')"
# The payload has a base64 format. We need to extract it from the
# previous reponse 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')"
# 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')"
# Display some information on the screen for the user.
echo "The signature is OK.
--> The port is $port and it will expire on $expires_at. <--
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
# alive. The servers have no mechanism to track your activity, so they
# will just delete the port forwarding if you don't send keepalives.
while true; do
bind_port_response="$(curl -Gs -m 5 \
--connect-to "$PF_HOSTNAME::$PF_GATEWAY:" \
--cacert "ca.rsa.4096.crt" \
--data-urlencode "payload=${payload}" \
--data-urlencode "signature=${signature}" \
"https://${PF_HOSTNAME}:19999/bindPort")"
echo "$bind_port_response"
# 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."
exit 1
fi
echo Port $port refreshed on $(date). \
This port will expire on $(date --date="$expires_at")
# sleep 15 minutes
sleep 900
done