-
Notifications
You must be signed in to change notification settings - Fork 3
/
pia.go
193 lines (176 loc) · 6.12 KB
/
pia.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
package pia
import (
"crypto/tls"
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"net/http"
"os"
)
const path_cache = "/var/cache/pia"
type Server struct {
Ip string `json:"ip"`
Cn string `json:"cn"`
}
type Tunnel struct {
Region string
MetaServer Server
WgServer Server
Status string `json:"status"`
ServerPubkey string `json:"server_key"`
ServerPort int `json:"server_port"`
ServerIp string `json:"server_ip"`
ServerVip string `json:"server_vip"`
PeerIp string `json:"peer_ip"`
PrivateKey string `json:"peer_privkey"`
PublicKey string `json:"peer_pubkey"`
DnsServers []string `json:"dns_servers"`
Token Token `json:"token"`
Message string `json:"message"`
Interface string `json:"interface"`
PFSig PortForwardSig `json:",omitempty"`
}
var _pia_certpool *x509.CertPool = nil
func get_pia_certpool() *x509.CertPool {
if _pia_certpool == nil {
p, _ := pem.Decode([]byte(`
-----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, _ := x509.ParseCertificate(p.Bytes)
_pia_certpool = x509.NewCertPool()
_pia_certpool.AddCert(ca)
}
return _pia_certpool
}
func do_request(req *http.Request, server_name string) (*http.Response, error) {
c := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
ServerName: server_name,
RootCAs: get_pia_certpool(),
},
},
}
resp, err := c.Do(req)
if err != nil {
return nil, err
}
return resp, nil
}
func GetServers(region string) (*Tunnel, error) {
const pia_url_servers = "https://serverlist.piaservers.net/vpninfo/servers/v4"
resp, err := http.Get(pia_url_servers)
if err != nil {
return nil, err
}
defer resp.Body.Close()
tun := Tunnel{Region: region}
var res struct {
Regions []struct {
Id string `json:"id"`
Servers map[string][]Server `json:"servers"`
} `json:"regions"`
}
if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
return nil, err
}
for r := range res.Regions {
if res.Regions[r].Id == region {
tun.MetaServer = res.Regions[r].Servers["meta"][0]
tun.WgServer = res.Regions[r].Servers["wg"][0]
return &tun, nil
}
}
return nil, fmt.Errorf("get_servers: Region %s not found", region)
}
func (tun *Tunnel) Activate() error {
url := fmt.Sprintf("https://%s:1337/addKey", tun.WgServer.Ip)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
}
q := req.URL.Query()
q.Add("pt", tun.Token.Token)
q.Add("pubkey", tun.PublicKey)
req.URL.RawQuery = q.Encode()
resp, err := do_request(req, tun.WgServer.Cn)
if err != nil {
return err
}
defer resp.Body.Close()
if err := json.NewDecoder(resp.Body).Decode(tun); err != nil {
return err
}
if tun.Status != "OK" {
return fmt.Errorf("PIA returned the following error: %s: %s", tun.Status, tun.Message)
}
return nil
}
func (tun *Tunnel) SaveCache() error {
path := fmt.Sprintf("%s/%s.json", path_cache, tun.Interface)
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o660)
if err != nil {
return err
}
defer file.Close()
if err := json.NewEncoder(file).Encode(tun); err != nil {
return err
}
return nil
}
func ReadCache(ifname string) (*Tunnel, error) {
path := fmt.Sprintf("%s/%s.json", path_cache, ifname)
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
var tun Tunnel
if err := json.NewDecoder(file).Decode(&tun); err != nil {
return nil, err
}
return &tun, err
}