commit
f37db1caf7
@ -0,0 +1,43 @@
|
||||
-----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-----
|
||||
@ -0,0 +1,57 @@
|
||||
from piawg import piawg
|
||||
from pick import pick
|
||||
import os
|
||||
from getpass import getpass
|
||||
from datetime import datetime
|
||||
|
||||
pia = piawg()
|
||||
|
||||
# Generate public and private key pair
|
||||
while True:
|
||||
if os.path.exists('privatekey') or os.path.exists('publickey'):
|
||||
value = input("Key files already exist. If you want to overwrite them type 'YES': ")
|
||||
if value == 'YES':
|
||||
pia.generate_keys()
|
||||
break
|
||||
else:
|
||||
pia.generate_keys()
|
||||
break
|
||||
|
||||
# Select region
|
||||
title = 'Please choose a region: '
|
||||
options = sorted(list(pia.server_list.keys()))
|
||||
option, index = pick(options, title)
|
||||
pia.set_region(option)
|
||||
|
||||
# Get token
|
||||
while True:
|
||||
username = input("\nEnter PIA username: ")
|
||||
password = getpass()
|
||||
if pia.get_token(username, password):
|
||||
print("Login successful!")
|
||||
break
|
||||
else:
|
||||
print("Error logging in, please try again...")
|
||||
|
||||
# Add key
|
||||
status, response = pia.addkey()
|
||||
if status:
|
||||
print("Added key to server!")
|
||||
else:
|
||||
print("Error adding key to server")
|
||||
print(response)
|
||||
|
||||
# Build config
|
||||
timestamp = int(datetime.now().timestamp())
|
||||
location = pia.region.replace(' ', '-')
|
||||
config_file = 'PIA-{}-{}.conf'.format(location, timestamp)
|
||||
print("Saving configuration file {}".format(config_file))
|
||||
with open(config_file, 'w') as file:
|
||||
file.write('[Interface]\n')
|
||||
file.write('Address = {}\n'.format(pia.connection['peer_ip']))
|
||||
file.write('PrivateKey = {}\n'.format(pia.privatekey))
|
||||
file.write('DNS = {},{}\n\n'.format(pia.connection['dns_servers'][0], pia.connection['dns_servers'][1]))
|
||||
file.write('[Peer]\n')
|
||||
file.write('PublicKey = {}\n'.format(pia.connection['server_key']))
|
||||
file.write('Endpoint = {}:1337\n'.format(pia.connection['server_ip']))
|
||||
file.write('AllowedIPs = 0.0.0.0/0\n')
|
||||
@ -0,0 +1,79 @@
|
||||
import requests
|
||||
import json
|
||||
from requests_toolbelt.adapters import host_header_ssl
|
||||
import urllib3
|
||||
import os
|
||||
import urllib.parse
|
||||
|
||||
# PIA uses the CN attribute for certificates they issue themselves.
|
||||
# This will be deprecated by urllib3 at some point in the future, and generates a warning (that we ignore).
|
||||
urllib3.disable_warnings(urllib3.exceptions.SubjectAltNameWarning)
|
||||
|
||||
|
||||
class piawg:
|
||||
def __init__(self):
|
||||
self.server_list = {}
|
||||
self.get_server_list()
|
||||
self.region = None
|
||||
self.token = None
|
||||
self.publickey = None
|
||||
self.privatekey = None
|
||||
self.connection = None
|
||||
|
||||
def get_server_list(self):
|
||||
r = requests.get('https://serverlist.piaservers.net/vpninfo/servers/v4')
|
||||
# Only process first line of response, there's some base64 data at the end we're ignoring
|
||||
data = json.loads(r.text.splitlines()[0])
|
||||
for server in data['regions']:
|
||||
self.server_list[server['name']] = server
|
||||
|
||||
def set_region(self, region_name):
|
||||
self.region = region_name
|
||||
|
||||
def get_token(self, username, password):
|
||||
# Get common name and IP address for metadata endpoint in region
|
||||
meta_cn = self.server_list[self.region]['servers']['meta'][0]['cn']
|
||||
meta_ip = self.server_list[self.region]['servers']['meta'][0]['ip']
|
||||
|
||||
# Some tricks to verify PIA certificate, even though we're sending requests to an IP and not a proper domain
|
||||
# https://toolbelt.readthedocs.io/en/latest/adapters.html#requests_toolbelt.adapters.host_header_ssl.HostHeaderSSLAdapter
|
||||
s = requests.Session()
|
||||
s.mount('https://', host_header_ssl.HostHeaderSSLAdapter())
|
||||
s.verify = 'ca.rsa.4096.crt'
|
||||
|
||||
r = s.get("https://{}/authv3/generateToken".format(meta_ip), headers={"Host": meta_cn},
|
||||
auth=(username, password))
|
||||
data = r.json()
|
||||
if r.status_code == 200 and data['status'] == 'OK':
|
||||
self.token = data['token']
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def generate_keys(self):
|
||||
os.system('wg genkey > privatekey')
|
||||
os.system('wg pubkey < privatekey > publickey')
|
||||
|
||||
# Read newly created keys
|
||||
with open('publickey', 'r') as file:
|
||||
self.publickey = file.read().splitlines()[0]
|
||||
|
||||
with open('privatekey', 'r') as file:
|
||||
self.privatekey = file.read().splitlines()[0]
|
||||
|
||||
def addkey(self):
|
||||
# Get common name and IP address for wireguard endpoint in region
|
||||
cn = self.server_list[self.region]['servers']['wg'][0]['cn']
|
||||
ip = self.server_list[self.region]['servers']['wg'][0]['ip']
|
||||
|
||||
s = requests.Session()
|
||||
s.mount('https://', host_header_ssl.HostHeaderSSLAdapter())
|
||||
s.verify = 'ca.rsa.4096.crt'
|
||||
|
||||
r = s.get("https://{}:1337/addKey?pt={}&pubkey={}".format(ip, urllib.parse.quote(self.token),
|
||||
urllib.parse.quote(self.publickey)), headers={"Host": cn})
|
||||
if r.status_code == 200 and r.json()['status'] == 'OK':
|
||||
self.connection = r.json()
|
||||
return True, r.content
|
||||
else:
|
||||
return False, r.content
|
||||
@ -0,0 +1,4 @@
|
||||
pick==1.0.0
|
||||
requests==2.24.0
|
||||
requests-toolbelt==0.9.1
|
||||
urllib3==1.25.11
|
||||
Loading…
Reference in new issue