diff --git a/README.md b/README.md index c3471b46..2b88fcfd 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Mullvad, Windscribe, Surfshark Cyberghost, VyprVPN, NordVPN and PureVPN VPN servers, using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and Tinyproxy* -**ANNOUNCEMENT**: *[Video of the Git history of Gluetun](https://youtu.be/khipOYJtGJ0)* +**ANNOUNCEMENT**: *Support for newer Private Internet Access servers* @@ -23,7 +23,7 @@ iptables, DNS over TLS, ShadowSocks and Tinyproxy* ## Features - Based on Alpine 3.12 for a small Docker image of 52MB -- Supports **Private Internet Access**, **Mullvad**, **Windscribe**, **Surfshark**, **Cyberghost**, **Vyprvpn**, **NordVPN** and **PureVPN** servers +- Supports **Private Internet Access** (new and old), **Mullvad**, **Windscribe**, **Surfshark**, **Cyberghost**, **Vyprvpn**, **NordVPN** and **PureVPN** servers - Supports Openvpn only for now - DNS over TLS baked in with service provider(s) of your choice - DNS fine blocking of malicious/ads/surveillance hostnames and IP addresses, with live update every 24 hours @@ -91,7 +91,7 @@ Want more testing? ▶ [see the Wiki](https://github.com/qdm12/gluetun/wiki/Test | Variable | Default | Choices | Description | | --- | --- | --- | --- | -| 🏁 `VPNSP` | `private internet access` | `private internet access`, `mullvad`, `windscribe`, `surfshark`, `vyprvpn`, `nordvpn`, `purevpn` | VPN Service Provider | +| 🏁 `VPNSP` | `private internet access` | `private internet access`, `private internet access old`, `mullvad`, `windscribe`, `surfshark`, `vyprvpn`, `nordvpn`, `purevpn` | VPN Service Provider | | `IP_STATUS_FILE` | `/tmp/gluetun/ip` | Any filepath | Filepath to store the public IP address assigned | | `PROTOCOL` | `udp` | `udp` or `tcp` | Network protocol to use | | `OPENVPN_VERBOSITY` | `1` | `0` to `6` | Openvpn verbosity level | @@ -110,8 +110,8 @@ Want more testing? ▶ [see the Wiki](https://github.com/qdm12/gluetun/wiki/Test | 🏁 `PASSWORD` | | | Your password | | `REGION` | | One of the [PIA regions](https://www.privateinternetaccess.com/pages/network/) | VPN server region | | `PIA_ENCRYPTION` | `strong` | `normal`, `strong` | Encryption preset | - | `PORT_FORWARDING` | `off` | `on`, `off` | Enable port forwarding on the VPN server | - | `PORT_FORWARDING_STATUS_FILE` | `/tmp/gluetun/forwarded_port` | Any filepath | Filepath to store the forwarded port number | + | `PORT_FORWARDING` | `off` | `on`, `off` | Enable port forwarding on the VPN server **for old only** | + | `PORT_FORWARDING_STATUS_FILE` | `/tmp/gluetun/forwarded_port` | Any filepath | Filepath to store the forwarded port number **for old only** | - Mullvad diff --git a/cmd/gluetun/main.go b/cmd/gluetun/main.go index b5a77e29..3bc7829a 100644 --- a/cmd/gluetun/main.go +++ b/cmd/gluetun/main.go @@ -46,6 +46,8 @@ func _main(background context.Context, args []string) int { //nolint:gocognit,go err = cli.ClientKey(args[2:]) case "openvpnconfig": err = cli.OpenvpnConfig() + case "update": + err = cli.Update(args[2:]) default: err = fmt.Errorf("command %q is unknown", args[1]) } @@ -92,7 +94,8 @@ func _main(background context.Context, args []string) int { //nolint:gocognit,go // TODO run this in a loop or in openvpn to reload from file without restarting storage := storage.New(logger) - allServers, err := storage.SyncServers(constants.GetAllServers()) + const updateServerFile = true + allServers, err := storage.SyncServers(constants.GetAllServers(), updateServerFile) if err != nil { logger.Error(err) return 1 diff --git a/cmd/resolver/main.go b/cmd/resolver/main.go index b0197306..79258f99 100644 --- a/cmd/resolver/main.go +++ b/cmd/resolver/main.go @@ -28,12 +28,6 @@ func _main(ctx context.Context) int { var domain string var servers []server switch *provider { - case "pia": - domain = "privateinternetaccess.com" - servers = piaServers() - case "pia-nextgen": - domain = "privacy.network" - servers = piaNextgenServers() case "windscribe": domain = "windscribe.com" servers = windscribeServers() @@ -212,108 +206,6 @@ type server struct { city string // only for purevpn } -func piaServers() []server { - return []server{ - {subdomain: "au-melbourne", region: "AU Melbourne"}, - {subdomain: "au-perth", region: "AU Perth"}, - {subdomain: "au-sydney", region: "AU Sydney"}, - {subdomain: "austria", region: "Austria"}, - {subdomain: "belgium", region: "Belgium"}, - {subdomain: "ca-montreal", region: "CA Montreal"}, - {subdomain: "ca-toronto", region: "CA Toronto"}, - {subdomain: "ca-vancouver", region: "CA Vancouver"}, - {subdomain: "czech", region: "Czech Republic"}, - {subdomain: "de-berlin", region: "DE Berlin"}, - {subdomain: "de-frankfurt", region: "DE Frankfurt"}, - {subdomain: "denmark", region: "Denmark"}, - {subdomain: "fi", region: "Finlan"}, - {subdomain: "france", region: "France"}, - {subdomain: "hungary", region: "Hungary"}, - {subdomain: "in", region: "India"}, - {subdomain: "ireland", region: "Ireland"}, - {subdomain: "israel", region: "Israel"}, - {subdomain: "italy", region: "Italy"}, - {subdomain: "japan", region: "Japan"}, - {subdomain: "lu", region: "Luxembourg"}, - {subdomain: "mexico", region: "Mexico"}, - {subdomain: "nl", region: "Netherlands"}, - {subdomain: "nz", region: "New Zealand"}, - {subdomain: "no", region: "Norway"}, - {subdomain: "poland", region: "Poland"}, - {subdomain: "ro", region: "Romania"}, - {subdomain: "sg", region: "Singapore"}, - {subdomain: "spain", region: "Spain"}, - {subdomain: "sweden", region: "Sweden"}, - {subdomain: "swiss", region: "Switzerland"}, - {subdomain: "ae", region: "UAE"}, - {subdomain: "uk-london", region: "UK London"}, - {subdomain: "uk-manchester", region: "UK Manchester"}, - {subdomain: "uk-southampton", region: "UK Southampton"}, - {subdomain: "us-atlanta", region: "US Atlanta"}, - {subdomain: "us-california", region: "US California"}, - {subdomain: "us-chicago", region: "US Chicago"}, - {subdomain: "us-dallas", region: "US Dallas"}, - {subdomain: "us-denver", region: "US Denver"}, - {subdomain: "us-east", region: "US East"}, - {subdomain: "us-florida", region: "US Florida"}, - {subdomain: "us-houston", region: "US Houston"}, - {subdomain: "us-lasvegas", region: "US Las Vegas"}, - {subdomain: "us-newyorkcity", region: "US New York City"}, - {subdomain: "us-seattle", region: "US Seattle"}, - {subdomain: "us-siliconvalley", region: "US Silicon Valley"}, - {subdomain: "us-washingtondc", region: "US Washington DC"}, - {subdomain: "us-west", region: "US West"}, - } -} - -func piaNextgenServers() []server { - return []server{ - {subdomain: "aus-melbourne", region: "AU Melbourne"}, - {subdomain: "aus-perth", region: "AU Perth"}, - {subdomain: "au-sydney", region: "AU Sydney"}, - {subdomain: "austria", region: "Austria"}, - {subdomain: "brussels", region: "Belgium"}, - {subdomain: "ca-montreal", region: "CA Montreal"}, - {subdomain: "ca-toronto", region: "CA Toronto"}, - {subdomain: "czech", region: "Czech Republic"}, - {subdomain: "de-berlin", region: "DE Berlin"}, - {subdomain: "de-frankfurt", region: "DE Frankfurt"}, - {subdomain: "denmark", region: "Denmark"}, - {subdomain: "fi", region: "Finland"}, - {subdomain: "france", region: "France"}, - {subdomain: "hungary", region: "Hungary"}, - {subdomain: "in", region: "India"}, - {subdomain: "ireland", region: "Ireland"}, - {subdomain: "israel", region: "Israel"}, - {subdomain: "italy", region: "Italy"}, - {subdomain: "japan", region: "Japan"}, - {subdomain: "lu", region: "Luxembourg"}, - {subdomain: "mexico", region: "Mexico"}, - {subdomain: "nl-amsterdam", region: "Netherlands"}, - {subdomain: "nz", region: "New Zealand"}, - {subdomain: "no", region: "Norway"}, - {subdomain: "poland", region: "Poland"}, - {subdomain: "ro", region: "Romania"}, - {subdomain: "sg", region: "Singapore"}, - {subdomain: "spain", region: "Spain"}, - {subdomain: "sweden", region: "Sweden"}, - {subdomain: "swiss", region: "Switzerland"}, - {subdomain: "ae", region: "UAE"}, - {subdomain: "uk-london", region: "UK London"}, - {subdomain: "uk-manchester", region: "UK Manchester"}, - {subdomain: "us-atlanta", region: "US Atlanta"}, - {subdomain: "us-california", region: "US California"}, - {subdomain: "us-chicago", region: "US Chicago"}, - {subdomain: "us-denver", region: "US Denver"}, - {subdomain: "us-florida", region: "US Florida"}, - {subdomain: "us-houston", region: "US Houston"}, - {subdomain: "us-seattle", region: "US Seattle"}, - {subdomain: "us-siliconvalley", region: "US Silicon Valley"}, - {subdomain: "us-washingtondc", region: "US Washington DC"}, - {subdomain: "us3", region: "US West"}, - } -} - func windscribeServers() []server { return []server{ {subdomain: "al", region: "Albania"}, diff --git a/internal/cli/cli.go b/internal/cli/cli.go index a500f0c5..c9814c1b 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -12,6 +12,7 @@ import ( "github.com/qdm12/gluetun/internal/provider" "github.com/qdm12/gluetun/internal/settings" "github.com/qdm12/gluetun/internal/storage" + "github.com/qdm12/gluetun/internal/updater" "github.com/qdm12/golibs/files" "github.com/qdm12/golibs/logging" ) @@ -56,7 +57,7 @@ func OpenvpnConfig() error { if err != nil { return err } - allServers, err := storage.New(logger).SyncServers(constants.GetAllServers()) + allServers, err := storage.New(logger).SyncServers(constants.GetAllServers(), false) if err != nil { return err } @@ -78,3 +79,28 @@ func OpenvpnConfig() error { fmt.Println(strings.Join(lines, "\n")) return nil } + +func Update(args []string) error { + var options updater.Options + flagSet := flag.NewFlagSet("update", flag.ExitOnError) + flagSet.BoolVar(&options.File, "file", false, "Write results to /gluetun/servers.json (for end users)") + flagSet.BoolVar(&options.Stdout, "stdout", false, "Write results to console to modify the program (for maintainers)") + flagSet.BoolVar(&options.PIA, "pia", false, "Update Private Internet Access post-summer 2020 servers") + flagSet.BoolVar(&options.PIAold, "piaold", false, "Update Private Internet Access pre-summer 2020 servers") + if err := flagSet.Parse(args); err != nil { + return err + } + logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel, -1) + if err != nil { + return err + } + if !options.File && !options.Stdout { + return fmt.Errorf("at least one of -file or -stdout must be specified") + } + storage := storage.New(logger) + updater := updater.New(storage) + if err := updater.UpdateServers(options); err != nil { + return err + } + return nil +} diff --git a/internal/constants/pia.go b/internal/constants/pia.go index a0f1031c..17e176bd 100644 --- a/internal/constants/pia.go +++ b/internal/constants/pia.go @@ -26,55 +26,170 @@ func PIAGeoChoices() (choices []string) { func PIAServers() []models.PIAServer { return []models.PIAServer{ - {Region: "AU Melbourne", IPs: []net.IP{{27, 50, 82, 131}, {27, 50, 82, 133}, {43, 250, 204, 81}, {43, 250, 204, 85}, {43, 250, 204, 87}, {43, 250, 204, 89}, {43, 250, 204, 95}, {43, 250, 204, 97}, {43, 250, 204, 99}, {43, 250, 204, 107}, {43, 250, 204, 109}, {43, 250, 204, 111}, {43, 250, 204, 113}, {43, 250, 204, 115}, {43, 250, 204, 117}, {43, 250, 204, 119}, {43, 250, 204, 123}, {43, 250, 204, 125}, {118, 127, 62, 227}, {221, 121, 139, 175}}}, - {Region: "AU Perth", IPs: []net.IP{{43, 250, 205, 59}, {43, 250, 205, 91}, {43, 250, 205, 95}}}, - {Region: "AU Sydney", IPs: []net.IP{{27, 50, 70, 87}, {27, 50, 77, 247}, {27, 50, 77, 251}, {27, 50, 81, 117}, {103, 13, 102, 113}, {103, 13, 102, 119}, {103, 13, 102, 121}, {103, 13, 102, 123}, {103, 13, 102, 127}, {118, 127, 60, 51}, {118, 127, 60, 53}, {118, 127, 60, 61}, {221, 121, 145, 133}, {221, 121, 145, 143}, {221, 121, 145, 145}, {221, 121, 145, 147}, {221, 121, 145, 159}, {221, 121, 146, 203}, {221, 121, 146, 217}, {221, 121, 152, 215}}}, - {Region: "Austria", IPs: []net.IP{{89, 187, 168, 6}, {156, 146, 60, 129}}}, - {Region: "Belgium", IPs: []net.IP{{77, 243, 191, 18}, {77, 243, 191, 19}, {77, 243, 191, 20}, {77, 243, 191, 21}, {77, 243, 191, 22}, {77, 243, 191, 23}, {77, 243, 191, 26}, {77, 243, 191, 27}, {185, 104, 186, 26}, {185, 232, 21, 26}, {185, 232, 21, 27}, {185, 232, 21, 28}, {185, 232, 21, 29}}}, - {Region: "CA Montreal", IPs: []net.IP{{199, 229, 249, 167}, {199, 229, 249, 177}, {199, 229, 249, 188}, {199, 229, 249, 190}, {199, 229, 249, 194}, {199, 229, 249, 196}}}, - {Region: "CA Toronto", IPs: []net.IP{{172, 98, 67, 43}, {172, 98, 67, 44}, {172, 98, 67, 52}, {172, 98, 67, 80}, {172, 98, 67, 88}, {172, 98, 67, 91}, {172, 98, 67, 143}}}, - {Region: "CA Vancouver", IPs: []net.IP{{107, 181, 189, 72}, {107, 181, 189, 73}, {107, 181, 189, 75}, {107, 181, 189, 76}, {107, 181, 189, 83}, {107, 181, 189, 84}, {107, 181, 189, 86}, {107, 181, 189, 87}, {172, 83, 40, 18}, {172, 83, 40, 19}, {172, 83, 40, 24}, {172, 83, 40, 26}, {172, 83, 40, 99}, {172, 83, 40, 100}, {172, 83, 40, 101}, {172, 83, 40, 104}, {172, 83, 40, 105}, {172, 83, 40, 107}, {172, 83, 40, 110}, {172, 83, 40, 113}}}, - {Region: "Czech Republic", IPs: []net.IP{{212, 102, 39, 1}}}, - {Region: "DE Berlin", IPs: []net.IP{{185, 230, 127, 226}, {185, 230, 127, 227}, {185, 230, 127, 229}, {185, 230, 127, 230}, {185, 230, 127, 231}, {185, 230, 127, 235}, {185, 230, 127, 238}, {185, 230, 127, 239}, {185, 230, 127, 241}, {185, 230, 127, 242}, {193, 176, 86, 125}, {193, 176, 86, 134}, {193, 176, 86, 138}, {193, 176, 86, 142}, {193, 176, 86, 150}, {193, 176, 86, 154}, {193, 176, 86, 158}, {193, 176, 86, 170}, {193, 176, 86, 178}, {194, 36, 108, 6}}}, - {Region: "DE Frankfurt", IPs: []net.IP{{195, 181, 170, 225}, {212, 102, 57, 138}}}, - {Region: "Denmark", IPs: []net.IP{{82, 102, 20, 163}, {82, 102, 20, 166}, {82, 102, 20, 167}, {82, 102, 20, 168}, {82, 102, 20, 169}, {82, 102, 20, 172}, {82, 102, 20, 173}, {82, 102, 20, 175}, {82, 102, 20, 177}, {82, 102, 20, 179}, {82, 102, 20, 182}, {82, 102, 20, 183}, {82, 102, 20, 230}, {188, 126, 94, 34}}}, - {Region: "Finlan", IPs: []net.IP{{188, 126, 89, 4}, {196, 244, 191, 2}, {196, 244, 191, 10}, {196, 244, 191, 18}, {196, 244, 191, 26}, {196, 244, 191, 34}, {196, 244, 191, 42}, {196, 244, 191, 50}, {196, 244, 191, 58}, {196, 244, 191, 66}, {196, 244, 191, 82}, {196, 244, 191, 90}, {196, 244, 191, 98}, {196, 244, 191, 114}, {196, 244, 191, 138}, {196, 244, 191, 146}}}, - {Region: "France", IPs: []net.IP{{156, 146, 63, 1}, {156, 146, 63, 65}}}, - {Region: "Hungary", IPs: []net.IP{{185, 128, 26, 18}, {185, 128, 26, 19}, {185, 128, 26, 20}, {185, 128, 26, 21}, {185, 128, 26, 22}, {185, 128, 26, 23}, {185, 128, 26, 24}}}, - {Region: "India", IPs: []net.IP{{150, 242, 12, 155}, {150, 242, 12, 171}, {150, 242, 12, 187}}}, - {Region: "Ireland", IPs: []net.IP{{23, 92, 127, 42}}}, - {Region: "Israel", IPs: []net.IP{{31, 168, 172, 142}, {31, 168, 172, 145}, {31, 168, 172, 146}, {31, 168, 172, 147}}}, - {Region: "Italy", IPs: []net.IP{{156, 146, 41, 129}, {156, 146, 41, 193}}}, - {Region: "Japan", IPs: []net.IP{{103, 208, 220, 130}, {103, 208, 220, 131}, {103, 208, 220, 132}, {103, 208, 220, 133}, {103, 208, 220, 134}, {103, 208, 220, 135}, {103, 208, 220, 136}, {103, 208, 220, 137}, {103, 208, 220, 138}, {103, 208, 220, 139}, {103, 208, 220, 140}, {103, 208, 220, 141}, {103, 208, 220, 142}, {103, 208, 220, 143}}}, - {Region: "Luxembourg", IPs: []net.IP{{92, 223, 89, 133}, {92, 223, 89, 135}, {92, 223, 89, 136}, {92, 223, 89, 137}, {92, 223, 89, 138}, {92, 223, 89, 140}}}, - {Region: "Mexico", IPs: []net.IP{{169, 57, 0, 197}, {169, 57, 0, 200}, {169, 57, 0, 203}, {169, 57, 0, 205}, {169, 57, 0, 207}, {169, 57, 0, 210}, {169, 57, 0, 211}, {169, 57, 0, 212}, {169, 57, 0, 213}, {169, 57, 0, 217}, {169, 57, 0, 218}, {169, 57, 0, 221}, {169, 57, 0, 229}, {169, 57, 0, 230}, {169, 57, 0, 233}, {169, 57, 0, 236}, {169, 57, 0, 238}, {169, 57, 0, 243}, {169, 57, 0, 247}, {169, 57, 0, 248}}}, - {Region: "Netherlands", IPs: []net.IP{{89, 187, 174, 198}, {212, 102, 35, 101}, {212, 102, 35, 102}, {212, 102, 35, 103}, {212, 102, 35, 104}}}, - {Region: "New Zealand", IPs: []net.IP{{43, 250, 207, 1}, {43, 250, 207, 3}}}, - {Region: "Norway", IPs: []net.IP{{82, 102, 27, 50}, {82, 102, 27, 51}, {82, 102, 27, 53}, {82, 102, 27, 54}, {82, 102, 27, 55}, {82, 102, 27, 56}, {82, 102, 27, 57}, {82, 102, 27, 74}, {82, 102, 27, 75}, {82, 102, 27, 77}, {82, 102, 27, 114}, {82, 102, 27, 115}, {82, 102, 27, 116}, {82, 102, 27, 117}, {82, 102, 27, 118}, {82, 102, 27, 126}, {185, 206, 225, 222}, {185, 253, 97, 226}}}, - {Region: "Poland", IPs: []net.IP{{185, 244, 214, 195}, {185, 244, 214, 197}, {185, 244, 214, 198}, {185, 244, 214, 199}}}, - {Region: "Romania", IPs: []net.IP{{86, 105, 25, 66}, {86, 105, 25, 67}, {86, 105, 25, 68}, {86, 105, 25, 69}, {86, 105, 25, 70}, {86, 105, 25, 75}, {86, 105, 25, 76}, {86, 105, 25, 77}, {94, 176, 148, 34}, {94, 176, 148, 35}, {185, 45, 12, 126}, {185, 210, 218, 99}, {185, 210, 218, 101}, {185, 210, 218, 102}, {185, 210, 218, 103}, {185, 210, 218, 104}, {185, 210, 218, 105}}}, - {Region: "Singapore", IPs: []net.IP{{156, 146, 56, 193}, {156, 146, 57, 38}}}, - {Region: "Spain", IPs: []net.IP{{212, 102, 49, 185}}}, - {Region: "Sweden", IPs: []net.IP{{45, 12, 220, 187}, {45, 12, 220, 208}, {45, 12, 220, 216}, {45, 12, 220, 238}, {45, 12, 220, 242}, {45, 12, 220, 245}, {45, 83, 91, 27}}}, - {Region: "Switzerland", IPs: []net.IP{{156, 146, 62, 129}, {156, 146, 62, 193}, {212, 102, 36, 166}}}, - {Region: "UAE", IPs: []net.IP{{45, 9, 250, 46}, {45, 9, 250, 62}}}, - {Region: "UK London", IPs: []net.IP{{37, 235, 96, 198}, {37, 235, 97, 11}, {212, 102, 52, 1}, {212, 102, 52, 134}, {212, 102, 52, 199}, {212, 102, 53, 129}}}, - {Region: "UK Manchester", IPs: []net.IP{{89, 238, 139, 4}, {89, 238, 139, 8}, {89, 238, 139, 9}, {89, 238, 139, 54}, {89, 238, 139, 58}}}, - {Region: "UK Southampton", IPs: []net.IP{{31, 24, 226, 136}, {31, 24, 226, 145}, {31, 24, 226, 146}, {31, 24, 226, 189}, {31, 24, 226, 202}, {31, 24, 226, 203}, {31, 24, 226, 205}, {31, 24, 226, 206}, {31, 24, 226, 209}, {31, 24, 226, 222}, {31, 24, 226, 230}, {31, 24, 226, 232}, {31, 24, 226, 233}, {31, 24, 226, 235}, {31, 24, 226, 238}, {31, 24, 226, 239}, {31, 24, 226, 241}, {31, 24, 226, 243}, {31, 24, 226, 245}, {31, 24, 226, 254}}}, - {Region: "US Atlanta", IPs: []net.IP{{66, 115, 169, 197}, {66, 115, 169, 199}, {66, 115, 169, 201}, {66, 115, 169, 203}, {66, 115, 169, 204}, {66, 115, 169, 209}, {66, 115, 169, 210}, {66, 115, 169, 212}, {66, 115, 169, 213}, {156, 146, 46, 1}, {156, 146, 46, 134}, {156, 146, 46, 198}, {156, 146, 47, 11}}}, - {Region: "US California", IPs: []net.IP{{37, 235, 108, 144}, {37, 235, 108, 208}, {89, 187, 187, 129}, {89, 187, 187, 159}, {89, 187, 187, 162}}}, - {Region: "US Chicago", IPs: []net.IP{{156, 146, 50, 1}, {156, 146, 50, 65}, {156, 146, 50, 134}, {156, 146, 50, 198}, {156, 146, 51, 11}, {212, 102, 58, 113}, {212, 102, 59, 54}, {212, 102, 59, 129}}}, - {Region: "US Dallas", IPs: []net.IP{{104, 18, 4, 18}, {104, 18, 5, 18}}}, - {Region: "US Denver", IPs: []net.IP{{174, 128, 225, 106}, {174, 128, 225, 186}, {174, 128, 226, 10}, {174, 128, 227, 226}, {174, 128, 236, 106}, {174, 128, 242, 250}, {174, 128, 243, 98}, {174, 128, 243, 106}, {174, 128, 244, 74}, {174, 128, 245, 98}, {174, 128, 245, 106}, {174, 128, 246, 10}, {174, 128, 250, 18}, {199, 115, 97, 202}, {199, 115, 98, 234}, {199, 115, 99, 82}, {199, 115, 101, 186}, {199, 115, 102, 146}, {199, 115, 103, 2}, {199, 115, 103, 10}}}, - {Region: "US East", IPs: []net.IP{{156, 146, 58, 198}, {156, 146, 58, 199}, {156, 146, 58, 201}, {156, 146, 58, 202}, {156, 146, 58, 203}, {156, 146, 58, 204}, {156, 146, 58, 205}, {156, 146, 58, 206}, {156, 146, 58, 207}, {156, 146, 58, 208}, {156, 146, 58, 209}, {193, 37, 253, 24}, {193, 37, 253, 102}, {193, 37, 253, 113}, {193, 37, 253, 141}, {193, 37, 253, 254}, {194, 59, 251, 13}, {194, 59, 251, 22}, {194, 59, 251, 49}, {194, 59, 251, 57}}}, - {Region: "US Florida", IPs: []net.IP{{156, 146, 42, 1}, {156, 146, 42, 65}, {156, 146, 42, 134}, {156, 146, 43, 11}, {156, 146, 43, 75}, {156, 146, 43, 121}, {156, 146, 43, 122}, {212, 102, 61, 19}, {212, 102, 61, 83}}}, - {Region: "US Houston", IPs: []net.IP{{74, 81, 88, 18}, {74, 81, 88, 26}, {74, 81, 88, 34}, {74, 81, 88, 42}, {74, 81, 88, 58}, {74, 81, 88, 66}, {74, 81, 88, 82}, {74, 81, 88, 90}, {74, 81, 88, 114}, {74, 81, 88, 122}, {205, 251, 148, 34}, {205, 251, 148, 42}, {205, 251, 148, 74}, {205, 251, 148, 90}, {205, 251, 148, 98}, {205, 251, 148, 162}, {205, 251, 150, 186}, {205, 251, 150, 202}, {205, 251, 150, 234}, {205, 251, 151, 42}}}, - {Region: "US Las Vegas", IPs: []net.IP{{162, 251, 236, 2}, {162, 251, 236, 3}, {162, 251, 236, 4}, {162, 251, 236, 5}, {162, 251, 236, 6}, {162, 251, 236, 7}, {162, 251, 236, 8}, {162, 251, 236, 9}, {199, 127, 56, 82}, {199, 127, 56, 83}, {199, 127, 56, 84}, {199, 127, 56, 87}, {199, 127, 56, 88}, {199, 127, 56, 89}, {199, 127, 56, 90}, {199, 127, 56, 91}, {199, 127, 56, 115}, {199, 127, 56, 117}, {199, 127, 56, 118}, {199, 127, 56, 119}}}, - {Region: "US New York City", IPs: []net.IP{{107, 182, 230, 194}, {107, 182, 231, 24}, {107, 182, 231, 30}, {107, 182, 231, 34}, {107, 182, 231, 37}, {107, 182, 231, 38}, {107, 182, 231, 51}, {209, 95, 50, 12}, {209, 95, 50, 27}, {209, 95, 50, 50}, {209, 95, 50, 65}, {209, 95, 50, 66}, {209, 95, 50, 90}, {209, 95, 50, 93}, {209, 95, 50, 103}, {209, 95, 50, 104}, {209, 95, 50, 133}, {209, 95, 50, 144}, {209, 95, 50, 146}, {209, 95, 50, 162}}}, - {Region: "US Seattle", IPs: []net.IP{{104, 200, 154, 11}, {104, 200, 154, 21}, {104, 200, 154, 22}, {104, 200, 154, 44}, {104, 200, 154, 47}, {104, 200, 154, 56}, {104, 200, 154, 59}, {104, 200, 154, 62}, {104, 200, 154, 66}, {104, 200, 154, 67}, {104, 200, 154, 70}, {104, 200, 154, 81}, {104, 200, 154, 84}, {104, 200, 154, 87}, {104, 200, 154, 90}, {104, 200, 154, 91}, {104, 200, 154, 96}, {104, 200, 154, 97}, {104, 200, 154, 98}, {104, 200, 154, 99}}}, - {Region: "US Silicon Valley", IPs: []net.IP{{199, 116, 118, 143}, {199, 116, 118, 149}, {199, 116, 118, 153}, {199, 116, 118, 154}, {199, 116, 118, 156}, {199, 116, 118, 168}, {199, 116, 118, 173}, {199, 116, 118, 174}, {199, 116, 118, 176}, {199, 116, 118, 181}, {199, 116, 118, 187}, {199, 116, 118, 209}, {199, 116, 118, 212}, {199, 116, 118, 215}, {199, 116, 118, 218}, {199, 116, 118, 221}, {199, 116, 118, 222}, {199, 116, 118, 239}, {199, 116, 118, 244}, {199, 116, 118, 250}}}, - {Region: "US Washington DC", IPs: []net.IP{{70, 32, 0, 46}, {70, 32, 0, 50}, {70, 32, 0, 51}, {70, 32, 0, 52}, {70, 32, 0, 53}, {70, 32, 0, 57}, {70, 32, 0, 64}, {70, 32, 0, 65}, {70, 32, 0, 77}, {70, 32, 0, 101}, {70, 32, 0, 104}, {70, 32, 0, 114}, {70, 32, 0, 116}, {70, 32, 0, 118}, {70, 32, 0, 120}, {70, 32, 0, 130}, {70, 32, 0, 139}, {70, 32, 0, 167}, {70, 32, 0, 172}, {70, 32, 0, 173}}}, - {Region: "US West", IPs: []net.IP{{104, 200, 151, 4}, {104, 200, 151, 11}, {104, 200, 151, 12}, {104, 200, 151, 13}, {104, 200, 151, 16}, {104, 200, 151, 20}, {104, 200, 151, 21}, {104, 200, 151, 31}, {104, 200, 151, 38}, {104, 200, 151, 39}, {104, 200, 151, 42}, {104, 200, 151, 52}, {104, 200, 151, 55}, {104, 200, 151, 61}, {104, 200, 151, 72}, {104, 200, 151, 73}, {104, 200, 151, 74}, {104, 200, 151, 78}, {104, 200, 151, 79}, {104, 200, 151, 83}}}, + {Region: "AU Melbourne", IPs: []net.IP{{27, 50, 74, 184}}}, + {Region: "AU Perth", IPs: []net.IP{{43, 250, 205, 170}}}, + {Region: "AU Sydney", IPs: []net.IP{{103, 2, 196, 167}}}, + {Region: "Algeria", IPs: []net.IP{{45, 133, 91, 210}}}, + {Region: "Andorra", IPs: []net.IP{{45, 139, 49, 241}}}, + {Region: "Argentina", IPs: []net.IP{{190, 106, 134, 82}}}, + {Region: "Armenia", IPs: []net.IP{{45, 139, 50, 232}}}, + {Region: "Austria", IPs: []net.IP{{156, 146, 60, 14}}}, + {Region: "Bahamas", IPs: []net.IP{{45, 132, 143, 206}}}, + {Region: "Bangladesh", IPs: []net.IP{{45, 132, 142, 210}}}, + {Region: "Belgium", IPs: []net.IP{{5, 253, 205, 147}}}, + {Region: "Bulgaria", IPs: []net.IP{{217, 138, 221, 130}}}, + {Region: "CA Montreal", IPs: []net.IP{{172, 98, 71, 13}}}, + {Region: "CA Toronto", IPs: []net.IP{{66, 115, 142, 81}}}, + {Region: "Cambodia", IPs: []net.IP{{188, 215, 235, 103}}}, + {Region: "China", IPs: []net.IP{{45, 132, 193, 234}}}, + {Region: "Cyprus", IPs: []net.IP{{45, 132, 137, 235}}}, + {Region: "Czech Republic", IPs: []net.IP{{212, 102, 39, 194}}}, + {Region: "DE Berlin", IPs: []net.IP{{89, 36, 76, 69}}}, + {Region: "DE Frankfurt", IPs: []net.IP{{185, 216, 33, 164}}}, + {Region: "Denmark", IPs: []net.IP{{188, 126, 94, 124}}}, + {Region: "Egypt", IPs: []net.IP{{188, 214, 122, 119}}}, + {Region: "Finland", IPs: []net.IP{{188, 126, 89, 10}}}, + {Region: "France", IPs: []net.IP{{156, 146, 63, 210}}}, + {Region: "Georgia", IPs: []net.IP{{45, 132, 138, 236}}}, + {Region: "Greenland", IPs: []net.IP{{45, 131, 209, 233}}}, + {Region: "Hungary", IPs: []net.IP{{217, 138, 192, 222}}}, + {Region: "Iceland", IPs: []net.IP{{45, 133, 193, 85}}}, + {Region: "India", IPs: []net.IP{{103, 26, 205, 251}}}, + {Region: "Iran", IPs: []net.IP{{45, 131, 4, 208}}}, + {Region: "Ireland", IPs: []net.IP{{5, 157, 13, 41}}}, + {Region: "Isle of Man", IPs: []net.IP{{45, 132, 140, 213}}}, + {Region: "Israel", IPs: []net.IP{{185, 77, 248, 10}}}, + {Region: "Italy", IPs: []net.IP{{156, 146, 41, 77}}}, + {Region: "Japan", IPs: []net.IP{{156, 146, 34, 164}}}, + {Region: "Kazakhstan", IPs: []net.IP{{45, 133, 88, 231}}}, + {Region: "Liechtenstein", IPs: []net.IP{{45, 139, 48, 236}}}, + {Region: "Luxembourg", IPs: []net.IP{{92, 223, 89, 80}}}, + {Region: "Macao", IPs: []net.IP{{45, 137, 197, 207}}}, + {Region: "Malta", IPs: []net.IP{{45, 137, 198, 235}}}, + {Region: "Mexico", IPs: []net.IP{{77, 81, 142, 5}}}, + {Region: "Moldova", IPs: []net.IP{{178, 175, 129, 40}}}, + {Region: "Monaco", IPs: []net.IP{{45, 137, 199, 237}}}, + {Region: "Mongolia", IPs: []net.IP{{45, 139, 51, 211}}}, + {Region: "Montenegro", IPs: []net.IP{{45, 131, 208, 206}}}, + {Region: "Morocco", IPs: []net.IP{{45, 131, 211, 234}}}, + {Region: "Netherlands", IPs: []net.IP{{37, 235, 101, 73}}}, + {Region: "New Zealand", IPs: []net.IP{{43, 250, 207, 70}}}, + {Region: "Nigeria", IPs: []net.IP{{45, 137, 196, 208}}}, + {Region: "Norway", IPs: []net.IP{{46, 246, 122, 82}}}, + {Region: "Panama", IPs: []net.IP{{45, 131, 210, 206}}}, + {Region: "Philippines", IPs: []net.IP{{188, 214, 125, 138}}}, + {Region: "Poland", IPs: []net.IP{{217, 138, 209, 243}}}, + {Region: "Qatar", IPs: []net.IP{{45, 131, 7, 209}}}, + {Region: "Romania", IPs: []net.IP{{185, 45, 15, 22}}}, + {Region: "Saudi Arabia", IPs: []net.IP{{45, 131, 6, 208}}}, + {Region: "Serbia", IPs: []net.IP{{37, 120, 193, 248}}}, + {Region: "Singapore", IPs: []net.IP{{156, 146, 57, 123}}}, + {Region: "South Africa", IPs: []net.IP{{154, 16, 93, 35}}}, + {Region: "Spain", IPs: []net.IP{{195, 181, 167, 42}}}, + {Region: "Sri Lanka", IPs: []net.IP{{45, 132, 136, 232}}}, + {Region: "Sweden", IPs: []net.IP{{46, 246, 3, 150}}}, + {Region: "Switzerland", IPs: []net.IP{{212, 102, 37, 77}}}, + {Region: "Taiwan", IPs: []net.IP{{188, 214, 106, 70}}}, + {Region: "Turkey", IPs: []net.IP{{188, 213, 34, 87}}}, + {Region: "UK London", IPs: []net.IP{{37, 235, 96, 26}}}, + {Region: "UK Manchester", IPs: []net.IP{{193, 239, 84, 60}}}, + {Region: "US Atlanta", IPs: []net.IP{{195, 181, 171, 76}}}, + {Region: "US California", IPs: []net.IP{{37, 235, 108, 19}}}, + {Region: "US Chicago", IPs: []net.IP{{154, 21, 28, 111}}}, + {Region: "US Denver", IPs: []net.IP{{70, 39, 126, 143}}}, + {Region: "US Florida", IPs: []net.IP{{37, 235, 98, 18}}}, + {Region: "US Houston", IPs: []net.IP{{74, 81, 92, 147}}}, + {Region: "US New Jersey", IPs: []net.IP{{37, 235, 103, 75}}}, + {Region: "US New York", IPs: []net.IP{{156, 146, 55, 213}}}, + {Region: "US Seattle", IPs: []net.IP{{156, 146, 48, 14}}}, + {Region: "US Silicon Valley", IPs: []net.IP{{154, 21, 212, 228}}}, + {Region: "US Texas", IPs: []net.IP{{154, 29, 131, 17}}}, + {Region: "US Washington DC", IPs: []net.IP{{70, 32, 5, 172}}}, + {Region: "US West", IPs: []net.IP{{193, 37, 254, 239}}}, + {Region: "Ukraine", IPs: []net.IP{{62, 149, 20, 51}}}, + {Region: "United Arab Emirates", IPs: []net.IP{{45, 131, 5, 233}}}, + {Region: "Venezuela", IPs: []net.IP{{45, 133, 89, 212}}}, + {Region: "Vietnam", IPs: []net.IP{{188, 214, 152, 67}}}, + } +} + +func PIAOldGeoChoices() (choices []string) { + servers := PIAOldServers() + choices = make([]string, len(servers)) + for i := range servers { + choices[i] = servers[i].Region + } + return choices +} + +func PIAOldServers() []models.PIAServer { + return []models.PIAServer{ + {Region: "AU Melbourne", IPs: []net.IP{{43, 250, 204, 97}}}, + {Region: "AU Perth", IPs: []net.IP{{43, 250, 205, 59}}}, + {Region: "AU Sydney", IPs: []net.IP{{221, 121, 146, 203}}}, + {Region: "Albania", IPs: []net.IP{{31, 171, 154, 130}}}, + {Region: "Argentina", IPs: []net.IP{{190, 106, 134, 80}}}, + {Region: "Austria", IPs: []net.IP{{185, 216, 34, 229}}}, + {Region: "Belgium", IPs: []net.IP{{185, 232, 21, 29}}}, + {Region: "Bosnia and Herzegovina", IPs: []net.IP{{185, 164, 35, 55}}}, + {Region: "Bulgaria", IPs: []net.IP{{217, 138, 221, 82}}}, + {Region: "CA Montreal", IPs: []net.IP{{199, 229, 249, 159}}}, + {Region: "CA Ontario", IPs: []net.IP{{184, 75, 213, 218}}}, + {Region: "CA Toronto", IPs: []net.IP{{172, 98, 67, 85}}}, + {Region: "CA Vancouver", IPs: []net.IP{{172, 83, 40, 25}}}, + {Region: "Czech Republic", IPs: []net.IP{{185, 242, 6, 27}}}, + {Region: "DE Berlin", IPs: []net.IP{{193, 176, 86, 123}}}, + {Region: "DE Frankfurt", IPs: []net.IP{{185, 220, 70, 147}}}, + {Region: "Denmark", IPs: []net.IP{{82, 102, 20, 181}}}, + {Region: "Estonia", IPs: []net.IP{{77, 247, 111, 98}}}, + {Region: "Finland", IPs: []net.IP{{196, 244, 191, 146}}}, + {Region: "France", IPs: []net.IP{{194, 187, 249, 47}}}, + {Region: "Greece", IPs: []net.IP{{154, 57, 3, 91}}}, + {Region: "Hungary", IPs: []net.IP{{185, 128, 26, 19}}}, + {Region: "Iceland", IPs: []net.IP{{213, 167, 139, 66}}}, + {Region: "India", IPs: []net.IP{{150, 242, 12, 155}}}, + {Region: "Ireland", IPs: []net.IP{{23, 92, 127, 34}}}, + {Region: "Israel", IPs: []net.IP{{31, 168, 172, 145}}}, + {Region: "Italy", IPs: []net.IP{{82, 102, 21, 217}}}, + {Region: "Japan", IPs: []net.IP{{156, 146, 34, 65}}}, + {Region: "Latvia", IPs: []net.IP{{109, 248, 149, 2}}}, + {Region: "Lithuania", IPs: []net.IP{{85, 206, 165, 160}}}, + {Region: "Luxembourg", IPs: []net.IP{{92, 223, 89, 137}}}, + {Region: "Moldova", IPs: []net.IP{{178, 17, 172, 242}}}, + {Region: "Netherlands", IPs: []net.IP{{46, 166, 190, 227}}}, + {Region: "New Zealand", IPs: []net.IP{{43, 250, 207, 3}}}, + {Region: "North Macedonia", IPs: []net.IP{{185, 225, 28, 130}}}, + {Region: "Norway", IPs: []net.IP{{82, 102, 27, 52}}}, + {Region: "Poland", IPs: []net.IP{{185, 244, 214, 198}}}, + {Region: "Portugal", IPs: []net.IP{{89, 26, 241, 102}}}, + {Region: "Romania", IPs: []net.IP{{185, 210, 218, 98}}}, + {Region: "Serbia", IPs: []net.IP{{37, 120, 193, 242}}}, + {Region: "Singapore", IPs: []net.IP{{37, 120, 208, 82}}}, + {Region: "Slovakia", IPs: []net.IP{{37, 120, 221, 82}}}, + {Region: "South Africa", IPs: []net.IP{{102, 165, 20, 133}}}, + {Region: "Spain", IPs: []net.IP{{185, 230, 124, 52}}}, + {Region: "Sweden", IPs: []net.IP{{45, 12, 220, 170}}}, + {Region: "Switzerland", IPs: []net.IP{{91, 132, 136, 45}}}, + {Region: "Turkey", IPs: []net.IP{{185, 195, 79, 82}}}, + {Region: "UAE", IPs: []net.IP{{45, 9, 250, 46}}}, + {Region: "UK London", IPs: []net.IP{{89, 238, 154, 229}}}, + {Region: "UK Manchester", IPs: []net.IP{{89, 238, 139, 9}}}, + {Region: "UK Southampton", IPs: []net.IP{{31, 24, 226, 234}}}, + {Region: "US Atlanta", IPs: []net.IP{{156, 146, 47, 11}}}, + {Region: "US California", IPs: []net.IP{{91, 207, 175, 169}}}, + {Region: "US Chicago", IPs: []net.IP{{212, 102, 58, 113}}}, + {Region: "US Dallas", IPs: []net.IP{{156, 146, 52, 70}}}, + {Region: "US Denver", IPs: []net.IP{{174, 128, 242, 250}}}, + {Region: "US East", IPs: []net.IP{{193, 37, 253, 120}}}, + {Region: "US Florida", IPs: []net.IP{{193, 37, 252, 126}}}, + {Region: "US Houston", IPs: []net.IP{{205, 251, 150, 194}}}, + {Region: "US Las Vegas", IPs: []net.IP{{199, 127, 56, 119}}}, + {Region: "US New York City", IPs: []net.IP{{156, 146, 54, 53}}}, + {Region: "US Seattle", IPs: []net.IP{{156, 146, 48, 65}}}, + {Region: "US Silicon Valley", IPs: []net.IP{{199, 116, 118, 181}}}, + {Region: "US Washington DC", IPs: []net.IP{{70, 32, 0, 75}}}, + {Region: "US West", IPs: []net.IP{{104, 200, 151, 44}}}, + {Region: "Ukraine", IPs: []net.IP{{62, 149, 20, 50}}}, } } diff --git a/internal/constants/servers.go b/internal/constants/servers.go index cdcfacc7..9c74c4f1 100644 --- a/internal/constants/servers.go +++ b/internal/constants/servers.go @@ -22,9 +22,14 @@ func GetAllServers() (allServers models.AllServers) { }, Pia: models.PiaServers{ Version: 1, - Timestamp: 1598236838, + Timestamp: 1598485988, Servers: PIAServers(), }, + PiaOld: models.PiaServers{ + Version: 1, + Timestamp: 1598485988, + Servers: PIAOldServers(), + }, Purevpn: models.PurevpnServers{ Version: 1, Timestamp: 1598236838, diff --git a/internal/constants/servers_test.go b/internal/constants/servers_test.go index 504310e9..1834d132 100644 --- a/internal/constants/servers_test.go +++ b/internal/constants/servers_test.go @@ -50,7 +50,8 @@ func Test_timestamps(t *testing.T) { assert.Equal(t, "lZa+3P5DGuo9VXlsXsW5Jw", digestServersTimestamp(t, allServers.Cyberghost.Servers, allServers.Cyberghost.Timestamp)) assert.Equal(t, "cK5eeY2KU+doigSAonCfVQ", digestServersTimestamp(t, allServers.Mullvad.Servers, allServers.Mullvad.Timestamp)) assert.Equal(t, "ZfMT6wXJJBAT0fOqx3TuOA", digestServersTimestamp(t, allServers.Nordvpn.Servers, allServers.Nordvpn.Timestamp)) - assert.Equal(t, "JGzrjRLM5MlWUjAkjpqKWw", digestServersTimestamp(t, allServers.Pia.Servers, allServers.Pia.Timestamp)) + assert.Equal(t, "vNjr3aOwoql8lBAKDx8Ygw", digestServersTimestamp(t, allServers.Pia.Servers, allServers.Pia.Timestamp)) + assert.Equal(t, "l3vaGSaIT4YOVGn3IaQkBg", digestServersTimestamp(t, allServers.PiaOld.Servers, allServers.PiaOld.Timestamp)) assert.Equal(t, "IW1gWNvYTSRDxpAv4kwmzg", digestServersTimestamp(t, allServers.Purevpn.Servers, allServers.Purevpn.Timestamp)) assert.Equal(t, "f934tXGfEVeNGT3TUdnpxw", digestServersTimestamp(t, allServers.Surfshark.Servers, allServers.Surfshark.Timestamp)) assert.Equal(t, "wwkmrCGEW06x7ze8+FO2hg", digestServersTimestamp(t, allServers.Vyprvpn.Servers, allServers.Vyprvpn.Timestamp)) diff --git a/internal/constants/vpn.go b/internal/constants/vpn.go index 1168290b..241c4c0c 100644 --- a/internal/constants/vpn.go +++ b/internal/constants/vpn.go @@ -7,6 +7,8 @@ import ( const ( // PrivateInternetAccess is a VPN provider PrivateInternetAccess models.VPNProvider = "private internet access" + // PrivateInternetAccessOld is the pre summer 2020 PIA provider + PrivateInternetAccessOld models.VPNProvider = "private internet access old" // Mullvad is a VPN provider Mullvad models.VPNProvider = "mullvad" // Windscribe is a VPN provider diff --git a/internal/models/selection.go b/internal/models/selection.go index b7732b65..b4443dd5 100644 --- a/internal/models/selection.go +++ b/internal/models/selection.go @@ -75,12 +75,17 @@ func (p *ProviderSettings) String() string { number = fmt.Sprintf("%d", p.ServerSelection.Number) } switch strings.ToLower(string(p.Name)) { - case "private internet access": + case "private internet access old": settingsList = append(settingsList, "Region: "+p.ServerSelection.Region, "Encryption preset: "+p.ExtraConfigOptions.EncryptionPreset, "Port forwarding: "+p.PortForwarding.String(), ) + case "private internet access": + settingsList = append(settingsList, + "Region: "+p.ServerSelection.Region, + "Encryption preset: "+p.ExtraConfigOptions.EncryptionPreset, + ) case "mullvad": settingsList = append(settingsList, "Country: "+p.ServerSelection.Country, diff --git a/internal/models/server.go b/internal/models/server.go index 494393da..b077df6e 100644 --- a/internal/models/server.go +++ b/internal/models/server.go @@ -1,12 +1,28 @@ package models -import "net" +import ( + "fmt" + "net" + "strings" +) + +func stringifyIPs(ips []net.IP) string { + ipStrings := make([]string, len(ips)) + for i := range ips { + ipStrings[i] = fmt.Sprintf("{%s}", strings.ReplaceAll(ips[i].String(), ".", ", ")) + } + return strings.Join(ipStrings, ", ") +} type PIAServer struct { IPs []net.IP `json:"ips"` Region string `json:"region"` } +func (p *PIAServer) String() string { + return fmt.Sprintf("{Region: %q, IPs: []net.IP{%s}}", p.Region, stringifyIPs(p.IPs)) +} + type MullvadServer struct { IPs []net.IP `json:"ips"` Country string `json:"country"` diff --git a/internal/models/servers.go b/internal/models/servers.go index f8a32590..e1fbd68b 100644 --- a/internal/models/servers.go +++ b/internal/models/servers.go @@ -5,6 +5,7 @@ type AllServers struct { Cyberghost CyberghostServers `json:"cyberghost"` Mullvad MullvadServers `json:"mullvad"` Nordvpn NordvpnServers `json:"nordvpn"` + PiaOld PiaServers `json:"piaOld"` Pia PiaServers `json:"pia"` Purevpn PurevpnServers `json:"purevpn"` Surfshark SurfsharkServers `json:"surfshark"` diff --git a/internal/params/params.go b/internal/params/params.go index bb6c1d6f..8c6f43ce 100644 --- a/internal/params/params.go +++ b/internal/params/params.go @@ -60,6 +60,7 @@ type Reader interface { GetPortForwardingStatusFilepath() (filepath models.Filepath, err error) GetPIAEncryptionPreset() (preset string, err error) GetPIARegion() (region string, err error) + GetPIAOldRegion() (region string, err error) // Mullvad getters GetMullvadCountry() (country string, err error) @@ -136,7 +137,7 @@ func NewReader(logger logging.Logger, fileManager files.FileManager) Reader { // GetVPNSP obtains the VPN service provider to use from the environment variable VPNSP func (r *reader) GetVPNSP() (vpnServiceProvider models.VPNProvider, err error) { - s, err := r.envParams.GetValueIfInside("VPNSP", []string{"pia", "private internet access", "mullvad", "windscribe", "surfshark", "cyberghost", "vyprvpn", "nordvpn", "purevpn"}) + s, err := r.envParams.GetValueIfInside("VPNSP", []string{"pia", "private internet access", "private internet access old", "mullvad", "windscribe", "surfshark", "cyberghost", "vyprvpn", "nordvpn", "purevpn"}) if s == "pia" { s = "private internet access" } diff --git a/internal/params/pia.go b/internal/params/pia.go index 55c251ad..105409e5 100644 --- a/internal/params/pia.go +++ b/internal/params/pia.go @@ -10,6 +10,7 @@ import ( // GetPortForwarding obtains if port forwarding on the VPN provider server // side is enabled or not from the environment variable PORT_FORWARDING +// Only valid for older PIA servers for now func (r *reader) GetPortForwarding() (activated bool, err error) { s, err := r.envParams.GetEnv("PORT_FORWARDING", libparams.Default("off")) if err != nil { @@ -61,3 +62,10 @@ func (r *reader) GetPIARegion() (region string, err error) { choices := append(constants.PIAGeoChoices(), "") return r.envParams.GetValueIfInside("REGION", choices) } + +// GetPIAOldRegion obtains the region for the PIA server from the +// environment variable REGION +func (r *reader) GetPIAOldRegion() (region string, err error) { + choices := append(constants.PIAOldGeoChoices(), "") + return r.envParams.GetValueIfInside("REGION", choices) +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 7d94938b..1ce8fe1b 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -17,6 +17,8 @@ func New(provider models.VPNProvider, allServers models.AllServers) Provider { switch provider { case constants.PrivateInternetAccess: return newPrivateInternetAccess(allServers.Pia.Servers) + case constants.PrivateInternetAccessOld: + return newPrivateInternetAccess(allServers.PiaOld.Servers) case constants.Mullvad: return newMullvad(allServers.Mullvad.Servers) case constants.Windscribe: diff --git a/internal/settings/openvpn.go b/internal/settings/openvpn.go index 3192e3ce..a148afe0 100644 --- a/internal/settings/openvpn.go +++ b/internal/settings/openvpn.go @@ -54,6 +54,8 @@ func GetOpenVPNSettings(paramsReader params.Reader, vpnProvider models.VPNProvid switch vpnProvider { case constants.PrivateInternetAccess: settings.Provider, err = GetPIASettings(paramsReader) + case constants.PrivateInternetAccessOld: + settings.Provider, err = GetPIAOldSettings(paramsReader) case constants.Mullvad: settings.Provider, err = GetMullvadSettings(paramsReader) case constants.Windscribe: diff --git a/internal/settings/providers.go b/internal/settings/providers.go index a8df31d8..0aa95668 100644 --- a/internal/settings/providers.go +++ b/internal/settings/providers.go @@ -29,6 +29,30 @@ func GetPIASettings(paramsReader params.Reader) (settings models.ProviderSetting if err != nil { return settings, err } + return settings, nil +} + +// GetPIAOldSettings obtains PIA settings for the older PIA servers (pre summer 2020) from environment variables using the params package. +func GetPIAOldSettings(paramsReader params.Reader) (settings models.ProviderSettings, err error) { + settings.Name = constants.PrivateInternetAccessOld + settings.ServerSelection.Protocol, err = paramsReader.GetNetworkProtocol() + if err != nil { + return settings, err + } + settings.ServerSelection.TargetIP, err = paramsReader.GetTargetIP() + if err != nil { + return settings, err + } + encryptionPreset, err := paramsReader.GetPIAEncryptionPreset() + if err != nil { + return settings, err + } + settings.ServerSelection.EncryptionPreset = encryptionPreset + settings.ExtraConfigOptions.EncryptionPreset = encryptionPreset + settings.ServerSelection.Region, err = paramsReader.GetPIAOldRegion() + if err != nil { + return settings, err + } settings.PortForwarding.Enabled, err = paramsReader.GetPortForwarding() if err != nil { return settings, err diff --git a/internal/storage/merge.go b/internal/storage/merge.go index e93d8127..464e2b90 100644 --- a/internal/storage/merge.go +++ b/internal/storage/merge.go @@ -40,6 +40,12 @@ func (s *storage) mergeServers(hardcoded, persistent models.AllServers) (merged getUnixTimeDifference(persistent.Pia.Timestamp, hardcoded.Pia.Timestamp)) merged.Pia = persistent.Pia } + merged.PiaOld = hardcoded.PiaOld + if persistent.PiaOld.Timestamp > hardcoded.PiaOld.Timestamp { + s.logger.Info("Using Private Internet Access older servers from file (%s more recent)", + getUnixTimeDifference(persistent.PiaOld.Timestamp, hardcoded.PiaOld.Timestamp)) + merged.PiaOld = persistent.PiaOld + } merged.Purevpn = hardcoded.Purevpn if persistent.Purevpn.Timestamp > hardcoded.Purevpn.Timestamp { s.logger.Info("Using Purevpn servers from file (%s more recent)", diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 5ba52e59..719085cb 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -9,7 +9,8 @@ import ( ) type Storage interface { - SyncServers(hardcodedServers models.AllServers) (allServers models.AllServers, err error) + SyncServers(hardcodedServers models.AllServers, write bool) (allServers models.AllServers, err error) + FlushToFile(servers models.AllServers) error } type storage struct { diff --git a/internal/storage/sync.go b/internal/storage/sync.go index 2a76032c..64965173 100644 --- a/internal/storage/sync.go +++ b/internal/storage/sync.go @@ -18,13 +18,14 @@ func countServers(allServers models.AllServers) int { len(allServers.Mullvad.Servers) + len(allServers.Nordvpn.Servers) + len(allServers.Pia.Servers) + + len(allServers.PiaOld.Servers) + len(allServers.Purevpn.Servers) + len(allServers.Surfshark.Servers) + len(allServers.Vyprvpn.Servers) + len(allServers.Windscribe.Servers) } -func (s *storage) SyncServers(hardcodedServers models.AllServers) (allServers models.AllServers, err error) { +func (s *storage) SyncServers(hardcodedServers models.AllServers, write bool) (allServers models.AllServers, err error) { // Eventually read file var serversOnFile models.AllServers _, err = s.osStat(jsonFilepath) @@ -43,10 +44,10 @@ func (s *storage) SyncServers(hardcodedServers models.AllServers) (allServers mo allServers = s.mergeServers(hardcodedServers, serversOnFile) // Eventually write file - if reflect.DeepEqual(serversOnFile, allServers) { + if !write || reflect.DeepEqual(serversOnFile, allServers) { return allServers, nil } - return allServers, s.flushToFile(allServers) + return allServers, s.FlushToFile(allServers) } func (s *storage) readFromFile() (servers models.AllServers, err error) { @@ -60,7 +61,7 @@ func (s *storage) readFromFile() (servers models.AllServers, err error) { return servers, nil } -func (s *storage) flushToFile(servers models.AllServers) error { +func (s *storage) FlushToFile(servers models.AllServers) error { bytes, err := json.MarshalIndent(servers, "", " ") if err != nil { return fmt.Errorf("cannot write to file: %w", err) diff --git a/internal/updater/openvpn.go b/internal/updater/openvpn.go new file mode 100644 index 00000000..5e08d67d --- /dev/null +++ b/internal/updater/openvpn.go @@ -0,0 +1,28 @@ +package updater + +import ( + "net" + "strings" +) + +func extractRemoteLinesFromOpenvpn(content []byte) (remoteLines []string) { + lines := strings.Split(string(content), "\n") + for _, line := range lines { + if strings.HasPrefix(line, "remote ") { + remoteLines = append(remoteLines, line) + } + } + return remoteLines +} + +func extractIPsFromRemoteLines(remoteLines []string) (ips []net.IP) { + for _, remoteLine := range remoteLines { + fields := strings.Fields(remoteLine) + ip := net.ParseIP(fields[1]) + if ip == nil { // not an IP address + continue + } + ips = append(ips, ip) + } + return ips +} diff --git a/internal/updater/options.go b/internal/updater/options.go new file mode 100644 index 00000000..0c8ee92a --- /dev/null +++ b/internal/updater/options.go @@ -0,0 +1,8 @@ +package updater + +type Options struct { + PIA bool + PIAold bool + File bool // update JSON file (user side) + Stdout bool // update constants file (maintainer side) +} diff --git a/internal/updater/pia.go b/internal/updater/pia.go new file mode 100644 index 00000000..c1f67b37 --- /dev/null +++ b/internal/updater/pia.go @@ -0,0 +1,66 @@ +package updater + +import ( + "fmt" + "sort" + "strings" + + "github.com/qdm12/gluetun/internal/models" +) + +func findPIAServers(new bool) (servers []models.PIAServer, err error) { + zipURL := "https://www.privateinternetaccess.com/openvpn/openvpn-ip.zip" + if new { + zipURL = "https://www.privateinternetaccess.com/openvpn/openvpn-ip-nextgen.zip" + } + return findPIAServersFromURL(zipURL) +} + +func findPIAServersFromURL(zipURL string) (servers []models.PIAServer, err error) { + contents, err := fetchAndExtractFiles(zipURL) + if err != nil { + return nil, err + } + for fileName, content := range contents { + remoteLines := extractRemoteLinesFromOpenvpn(content) + if len(remoteLines) == 0 { + return nil, fmt.Errorf("cannot find any remote lines in %s", fileName) + } + IPs := extractIPsFromRemoteLines(remoteLines) + if len(IPs) == 0 { + return nil, fmt.Errorf("cannot find any IP addresses in %s", fileName) + } + region := strings.TrimSuffix(fileName, ".ovpn") + server := models.PIAServer{ + Region: region, + IPs: IPs, + } + servers = append(servers, server) + } + sort.Slice(servers, func(i, j int) bool { + return servers[i].Region < servers[j].Region + }) + return servers, nil +} + +func stringifyPIAServers(servers []models.PIAServer) (s string) { + s = "func PIAServers() []models.PIAServer {\n" + s += " return []models.PIAServer{\n" + for _, server := range servers { + s += " " + server.String() + ",\n" + } + s += " }\n" + s += "}" + return s +} + +func stringifyPIAOldServers(servers []models.PIAServer) (s string) { + s = "func PIAOldServers() []models.PIAServer {\n" + s += " return []models.PIAServer{\n" + for _, server := range servers { + s += " " + server.String() + ",\n" + } + s += " }\n" + s += "}" + return s +} diff --git a/internal/updater/updater.go b/internal/updater/updater.go new file mode 100644 index 00000000..bc078daa --- /dev/null +++ b/internal/updater/updater.go @@ -0,0 +1,69 @@ +package updater + +import ( + "fmt" + "time" + + "github.com/qdm12/gluetun/internal/constants" + "github.com/qdm12/gluetun/internal/storage" +) + +type Updater interface { + UpdateServers(options Options) error +} + +type updater struct { + storage storage.Storage + timeNow func() time.Time + println func(s string) +} + +func New(storage storage.Storage) Updater { + return &updater{ + storage: storage, + timeNow: time.Now, + println: func(s string) { fmt.Println(s) }, + } +} + +func (u *updater) UpdateServers(options Options) error { + const writeSync = false + allServers, err := u.storage.SyncServers(constants.GetAllServers(), writeSync) + if err != nil { + return fmt.Errorf("cannot update servers: %w", err) + } + + if options.PIA { + const newServers = true + servers, err := findPIAServers(newServers) + if err != nil { + return fmt.Errorf("cannot update PIA servers: %w", err) + } + if options.Stdout { + u.println(stringifyPIAServers(servers)) + } + allServers.Pia.Timestamp = u.timeNow().Unix() + allServers.Pia.Servers = servers + } + + if options.PIAold { + const newServers = false + servers, err := findPIAServers(newServers) + if err != nil { + return fmt.Errorf("cannot update PIA old servers: %w", err) + } + if options.Stdout { + u.println(stringifyPIAOldServers(servers)) + } + allServers.PiaOld.Timestamp = u.timeNow().Unix() + allServers.PiaOld.Servers = servers + } + + if options.File { + if err := u.storage.FlushToFile(allServers); err != nil { + return fmt.Errorf("cannot update servers: %w", err) + } + } + + return nil +} diff --git a/internal/updater/zip.go b/internal/updater/zip.go new file mode 100644 index 00000000..67d7845c --- /dev/null +++ b/internal/updater/zip.go @@ -0,0 +1,62 @@ +package updater + +import ( + "archive/zip" + "bytes" + "fmt" + "io/ioutil" + "net/http" + "path/filepath" + "strings" + "time" + + "github.com/qdm12/golibs/network" +) + +func fetchAndExtractFiles(urls ...string) (contents map[string][]byte, err error) { + client := network.NewClient(10 * time.Second) + contents = make(map[string][]byte) + for _, url := range urls { + zipBytes, status, err := client.GetContent(url) + if err != nil { + return nil, err + } else if status != http.StatusOK { + return nil, fmt.Errorf("Getting %s results in HTTP status code %d", url, status) + } + newContents, err := zipExtractAll(zipBytes) + if err != nil { + return nil, err + } + for fileName, content := range newContents { + contents[fileName] = content + } + } + return contents, nil +} + +func zipExtractAll(zipBytes []byte) (contents map[string][]byte, err error) { + r, err := zip.NewReader(bytes.NewReader(zipBytes), int64(len(zipBytes))) + if err != nil { + return nil, err + } + contents = map[string][]byte{} + for _, zf := range r.File { + fileName := filepath.Base(zf.Name) + if !strings.HasSuffix(fileName, ".ovpn") { + continue + } + f, err := zf.Open() + if err != nil { + return nil, err + } + defer f.Close() + contents[fileName], err = ioutil.ReadAll(f) + if err != nil { + return nil, err + } + if err := f.Close(); err != nil { + return nil, err + } + } + return contents, nil +}