Compare commits

...

10 Commits

Author SHA1 Message Date
Quentin McGaw
f48392064e Update issue templates 2020-11-10 01:29:47 +00:00
Quentin McGaw
994bdd0ca7 Update Gituhb labels 2020-11-10 01:16:12 +00:00
Quentin McGaw
40ed070f21 Filter Privado servers by hostnames only 2020-11-09 23:17:22 +00:00
Quentin McGaw
f1e4b9937b Privado support, fix #285 (#288) 2020-11-08 20:56:49 -05:00
Quentin McGaw
0423388b52 Fix build information setting at build time 2020-11-07 22:31:20 +00:00
Quentin McGaw
096a9c5fc0 Fix #289 2020-11-06 02:54:27 +00:00
Quentin McGaw
7518f74729 Refactor HTTP control server code 2020-11-05 22:26:53 +00:00
Quentin McGaw
854401a150 PureVPN servers json tag fix 2020-11-05 02:22:33 +00:00
Quentin McGaw
a7a7efe9c3 Remove PIA v3 servers support 2020-11-05 02:10:34 +00:00
Quentin McGaw
31883f9adb Windscribe API and more servers filter options, fixes #197 (#282)
- Use Windscribe API to fetch servers information
- More data on servers about region, city and hostname
- Add optional server filters with `REGION`, `CITY` and `HOSTNAME` csv environment variables
2020-11-04 20:38:35 -05:00
46 changed files with 1183 additions and 842 deletions

View File

@@ -7,49 +7,31 @@ assignees: qdm12
---
**TLDR**: *Describe your issue in a one liner here*
**Host OS** (approximate answer is fine too): Ubuntu 18
1. Is this urgent?
**Is this urgent?**: No
- [ ] Yes
- [x] No
**What VPN provider are you using**:
2. What VPN service provider are you using?
**What are you using to run your container?**: Docker Compose
- [x] PIA
- [ ] Mullvad
- [ ] Windscribe
- [ ] Surfshark
- [ ] Cyberghost
**What is the version of the program** (See the line at the top of your logs)
3. What's the version of the program?
```
Running version latest built on 2020-03-13T01:30:06Z (commit d0f678c)
```
**See the line at the top of your logs**
**What's the problem** 🤔
`Running version latest built on 2020-03-13T01:30:06Z (commit d0f678c)`
That feature doesn't work
4. What are you using to run the container?
**Share your logs...**
- [ ] Docker run
- [x] Docker Compose
- [ ] Kubernetes
- [ ] Docker stack
- [ ] Docker swarm
- [ ] Podman
- [ ] Other:
5. Extra information
Logs:
...*careful to remove i.e. token information with PIA port forwarding*
```log
```
Configuration file:
```yml
PASTE YOUR LOGS
IN THERE
```
Host OS:

View File

@@ -1,14 +1,17 @@
---
name: Feature request
about: Suggest a feature to add to this project
title: 'Feature request: ...'
title: 'Feature request: FILL THIS TEXT!'
labels: ":bulb: feature request"
assignees: qdm12
---
1. What's the feature?
**What's the feature?** 🧐
2. Why do you need this feature?
- Support this new feature because that and that
3. Extra information?
**Optional extra information** 🚀
- I tried `docker run something` and it doesn't work
- That [url](https://github.com/qdm12/gluetun) is interesting

View File

@@ -7,49 +7,47 @@ assignees:
---
**TLDR**: *Describe your issue in a one liner here*
**Host OS** (approximate answer is fine too): Ubuntu 18
1. Is this urgent?
**Is this urgent?**: No
- [ ] Yes
- [x] No
**What VPN provider are you using**:
2. What VPN service provider are you using?
**What is the version of the program** (See the line at the top of your logs)
- [x] PIA
- [ ] Mullvad
- [ ] Windscribe
- [ ] Surfshark
- [ ] Cyberghost
```
Running version latest built on 2020-03-13T01:30:06Z (commit d0f678c)
```
3. What's the version of the program?
**What's the problem** 🤔
**See the line at the top of your logs**
That feature doesn't work
`Running version latest built on 2020-03-13T01:30:06Z (commit d0f678c)`
**Share your logs...**
4. What are you using to run the container?
- [ ] Docker run
- [x] Docker Compose
- [ ] Kubernetes
- [ ] Docker stack
- [ ] Docker swarm
- [ ] Podman
- [ ] Other:
5. Extra information
Logs:
...*careful to remove i.e. token information with PIA port forwarding*
```log
PASTE YOUR LOGS
IN THERE
```
Configuration file:
**What are you using to run your container?**: Docker Compose
Please also share your configuration file:
```yml
your .yml
content
in here
```
Host OS:
or
```sh
# your docker
# run command
# in here
```

96
.github/labels.yml vendored
View File

@@ -1,51 +1,67 @@
- name: ":robot: bot"
color: "69cde9"
description: ""
- name: ":bug: bug"
- name: "Bug :bug:"
color: "b60205"
description: ""
- name: ":game_die: dependencies"
color: "0366d6"
description: ""
- name: ":memo: documentation"
color: "c5def5"
description: ""
- name: ":busts_in_silhouette: duplicate"
color: "cccccc"
description: ""
- name: ":sparkles: enhancement"
color: "0054ca"
description: ""
- name: ":bulb: feature request"
- name: "Feature request :bulb:"
color: "0e8a16"
description: ""
- name: ":mega: feedback"
color: "03a9f4"
description: ""
- name: ":rocket: future maybe"
color: "fef2c0"
description: ""
- name: ":hatching_chick: good first issue"
color: "7057ff"
description: ""
- name: ":pray: help wanted"
- name: "Help wanted :pray:"
color: "4caf50"
description: ""
- name: ":hand: hold"
color: "24292f"
- name: "Documentation :memo:"
color: "c5def5"
description: ""
- name: ":no_entry_sign: invalid"
color: "e6e6e6"
description: ""
- name: ":interrobang: maybe bug"
color: "ff5722"
description: ""
- name: ":thinking: needs more info"
- name: "Needs more info :thinking:"
color: "795548"
description: ""
- name: ":question: question"
color: "3f51b5"
# VPN providers
- name: ":cloud: Cyberghost"
color: "cfe8d4"
description: ""
- name: ":coffin: wontfix"
color: "ffffff"
- name: ":cloud: Mullvad"
color: "cfe8d4"
description: ""
- name: ":cloud: NordVPN"
color: "cfe8d4"
description: ""
- name: ":cloud: PIA"
color: "cfe8d4"
description: ""
- name: ":cloud: Privado"
color: "cfe8d4"
description: ""
- name: ":cloud: PureVPN"
color: "cfe8d4"
description: ""
- name: ":cloud: Surfshark"
color: "cfe8d4"
description: ""
- name: ":cloud: Vyprvpn"
color: "cfe8d4"
description: ""
- name: ":cloud: Windscribe"
color: "cfe8d4"
description: ""
# Problem category
- name: "Openvpn"
color: "ffc7ea"
description: ""
- name: "Unbound (DNS over TLS)"
color: "ffc7ea"
description: ""
- name: "Firewall"
color: "ffc7ea"
description: ""
- name: "HTTP proxy"
color: "ffc7ea"
description: ""
- name: "Shadowsocks"
color: "ffc7ea"
description: ""
- name: "Healthcheck server"
color: "ffc7ea"
description: ""
- name: "Control server"
color: "ffc7ea"
description: ""

View File

@@ -58,7 +58,10 @@ ENV VPNSP=pia \
PORT_FORWARDING_STATUS_FILE="/tmp/gluetun/forwarded_port" \
# Mullvad and PureVPN only
COUNTRY= \
# Mullvad, PureVPN, Windscribe only
CITY= \
# Windscribe only
HOSTNAME= \
# Mullvad only
ISP= \
OWNED=no \

View File

@@ -1,7 +1,7 @@
# Gluetun VPN client
*Lightweight swiss-knife-like VPN client to tunnel to Private Internet Access,
Mullvad, Windscribe, Surfshark Cyberghost, VyprVPN, NordVPN and PureVPN VPN servers, using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and an HTTP proxy*
Mullvad, Windscribe, Surfshark Cyberghost, VyprVPN, NordVPN, PureVPN and Privado VPN servers, using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and an HTTP proxy*
**ANNOUNCEMENT**: *Github Wiki reworked*
@@ -28,7 +28,7 @@ Mullvad, Windscribe, Surfshark Cyberghost, VyprVPN, NordVPN and PureVPN VPN serv
## Features
- Based on Alpine 3.12 for a small Docker image of 52MB
- Supports **Private Internet Access** (new and old), **Mullvad**, **Windscribe**, **Surfshark**, **Cyberghost**, **Vyprvpn**, **NordVPN** and **PureVPN** servers
- Supports **Private Internet Access**, **Mullvad**, **Windscribe**, **Surfshark**, **Cyberghost**, **Vyprvpn**, **NordVPN**, **PureVPN** and **Privado** 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
@@ -96,7 +96,7 @@ docker run --rm --network=container:gluetun alpine:3.12 wget -qO- https://ipinfo
| Variable | Default | Choices | Description |
| --- | --- | --- | --- |
| 🏁 `VPNSP` | `private internet access` | `private internet access`, `private internet access old`, `mullvad`, `windscribe`, `surfshark`, `vyprvpn`, `nordvpn`, `purevpn` | VPN Service Provider |
| 🏁 `VPNSP` | `private internet access` | `private internet access`, `mullvad`, `windscribe`, `surfshark`, `vyprvpn`, `nordvpn`, `purevpn`, `privado` | 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 |
@@ -134,13 +134,15 @@ docker run --rm --network=container:gluetun alpine:3.12 wget -qO- https://ipinfo
For **port forwarding**, obtain a port from [here](https://mullvad.net/en/account/#/ports) and add it to `FIREWALL_VPN_INPUT_PORTS`
- Windscribe
- Windscribe (see [this](https://github.com/qdm12/gluetun/blob/master/internal/constants/windscribe.go#L43) for the choices of regions, cities and hostnames)
| Variable | Default | Choices | Description |
| --- | --- | --- | --- |
| 🏁 `USER` | | | Your username |
| 🏁 `PASSWORD` | | | Your password |
| `REGION` | | One of the [Windscribe regions](https://windscribe.com/status) | VPN server region |
| `REGION` | | | Comma separated list of regions to choose the VPN server |
| `CITY` | | | Comma separated list of cities to choose the VPN server |
| `HOSTNAME` | | | Comma separated list of hostnames to choose the VPN server |
| `PORT` | | One from the [this list of ports](https://windscribe.com/getconfig/openvpn) | Custom VPN port to use |
- Surfshark
@@ -200,6 +202,14 @@ docker run --rm --network=container:gluetun alpine:3.12 wget -qO- https://ipinfo
| `COUNTRY` | | One of the [PureVPN countries](https://support.purevpn.com/vpn-servers) | VPN server country |
| `CITY` | | One of the [PureVPN cities](https://support.purevpn.com/vpn-servers) | VPN server city |
- Privado
| Variable | Default | Choices | Description |
| --- | --- | --- | --- |
| 🏁 `USER` | | | Your username |
| 🏁 `PASSWORD` | | | Your password |
| `HOSTNAME` | | [One of the Privado hostname](internal/constants/privado.go#L26), i.e. `ams-001.vpn.privado.io` | VPN server hostname |
### DNS over TLS
None of the following values are required.

View File

@@ -38,13 +38,17 @@ import (
)
//nolint:gochecknoglobals
var buildInfo = models.BuildInformation{
Version: "unknown",
Commit: "unknown",
BuildDate: "an unknown date",
}
var (
buildInfo models.BuildInformation
version = "unknown"
commit = "unknown"
buildDate = "an unknown date"
)
func main() {
buildInfo.Version = version
buildInfo.Commit = commit
buildInfo.BuildDate = buildDate
ctx := context.Background()
os.Exit(_main(ctx, os.Args))
}
@@ -411,24 +415,13 @@ func routeReadyEvents(ctx context.Context, wg *sync.WaitGroup, tunnelReadyCh, dn
logger.Info("VPN routing IP address: %s", vpnDestination)
}
if portForwardingEnabled {
// TODO make instantaneous once v3 go out of service
const waitDuration = 5 * time.Second
timer := time.NewTimer(waitDuration)
select {
case <-ctx.Done():
if !timer.Stop() {
<-timer.C
}
continue
case <-timer.C:
// vpnGateway required only for PIA v4
vpnGateway, err := routing.VPNLocalGatewayIP()
if err != nil {
logger.Error(err)
}
logger.Info("VPN gateway IP address: %s", vpnGateway)
startPortForward(vpnGateway)
// vpnGateway required only for PIA v4
vpnGateway, err := routing.VPNLocalGatewayIP()
if err != nil {
logger.Error(err)
}
logger.Info("VPN gateway IP address: %s", vpnGateway)
startPortForward(vpnGateway)
}
case <-dnsReadyCh:
publicIPLooper.Restart() // TODO do not restart if disabled

View File

@@ -93,7 +93,7 @@ func Update(args []string) error {
flagSet.BoolVar(&options.Mullvad, "mullvad", false, "Update Mullvad servers")
flagSet.BoolVar(&options.Nordvpn, "nordvpn", false, "Update Nordvpn servers")
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")
flagSet.BoolVar(&options.Privado, "privado", false, "Update Privado servers")
flagSet.BoolVar(&options.Purevpn, "purevpn", false, "Update Purevpn servers")
flagSet.BoolVar(&options.Surfshark, "surfshark", false, "Update Surfshark servers")
flagSet.BoolVar(&options.Vyprvpn, "vyprvpn", false, "Update Vyprvpn servers")

View File

@@ -125,88 +125,3 @@ func PIAServers() []models.PIAServer {
{Region: "Vietnam", PortForward: true, OpenvpnUDP: models.PIAServerOpenvpn{CN: "vietnam401", IPs: []net.IP{{188, 214, 152, 76}}}, OpenvpnTCP: models.PIAServerOpenvpn{CN: "vietnam401", IPs: []net.IP{{188, 214, 152, 70}}}},
}
}
func PIAOldGeoChoices() (choices []string) {
servers := PIAOldServers()
choices = make([]string, len(servers))
for i := range servers {
choices[i] = servers[i].Region
}
return choices
}
//nolint:lll
func PIAOldServers() []models.PIAOldServer {
return []models.PIAOldServer{
{Region: "AU Melbourne", IPs: []net.IP{{27, 50, 82, 131}, {43, 250, 204, 105}, {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}}},
{Region: "AU Perth", IPs: []net.IP{{43, 250, 205, 59}, {43, 250, 205, 91}, {43, 250, 205, 93}, {43, 250, 205, 95}}},
{Region: "AU Sydney", IPs: []net.IP{{27, 50, 68, 23}, {27, 50, 70, 87}, {27, 50, 77, 251}, {27, 50, 81, 117}, {103, 13, 102, 123}, {103, 13, 102, 127}, {118, 127, 60, 51}, {221, 121, 145, 135}, {221, 121, 145, 137}, {221, 121, 145, 145}, {221, 121, 145, 147}, {221, 121, 145, 159}, {221, 121, 146, 203}, {221, 121, 148, 221}, {221, 121, 152, 215}}},
{Region: "Albania", IPs: []net.IP{{31, 171, 154, 114}}},
{Region: "Argentina", IPs: []net.IP{{190, 106, 134, 100}}},
{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}, {185, 232, 21, 26}}},
{Region: "Bosnia and Herzegovina", IPs: []net.IP{{185, 164, 35, 54}}},
{Region: "Bulgaria", IPs: []net.IP{{217, 138, 221, 66}}},
{Region: "CA Montreal", IPs: []net.IP{{172, 98, 71, 194}, {199, 36, 223, 130}, {199, 36, 223, 194}}},
{Region: "CA Ontario", IPs: []net.IP{{162, 219, 176, 26}, {162, 219, 176, 42}, {184, 75, 208, 2}, {184, 75, 208, 90}, {184, 75, 208, 114}, {184, 75, 208, 122}, {184, 75, 208, 130}, {184, 75, 208, 146}, {184, 75, 208, 170}, {184, 75, 208, 202}, {184, 75, 210, 18}, {184, 75, 210, 98}, {184, 75, 210, 106}, {184, 75, 213, 186}, {184, 75, 213, 218}, {184, 75, 214, 18}, {184, 75, 215, 18}, {184, 75, 215, 26}, {184, 75, 215, 66}, {184, 75, 215, 74}}},
{Region: "CA Toronto", IPs: []net.IP{{66, 115, 142, 130}, {66, 115, 145, 199}, {172, 98, 92, 66}, {172, 98, 92, 130}, {172, 98, 92, 194}}},
{Region: "CA Vancouver", IPs: []net.IP{{162, 216, 47, 66}, {162, 216, 47, 194}, {172, 98, 89, 130}, {172, 98, 89, 194}}},
{Region: "Czech Republic", IPs: []net.IP{{212, 102, 39, 1}}},
{Region: "DE Berlin", IPs: []net.IP{{185, 230, 127, 238}, {193, 176, 86, 122}, {193, 176, 86, 123}, {193, 176, 86, 134}, {193, 176, 86, 178}, {194, 36, 108, 6}}},
{Region: "DE Frankfurt", IPs: []net.IP{{195, 181, 170, 239}, {195, 181, 170, 240}, {195, 181, 170, 241}, {195, 181, 170, 242}, {195, 181, 170, 243}, {195, 181, 170, 244}, {212, 102, 57, 138}}},
{Region: "Denmark", IPs: []net.IP{{188, 126, 94, 34}}},
{Region: "Estonia", IPs: []net.IP{{77, 247, 111, 82}, {77, 247, 111, 98}, {77, 247, 111, 114}, {77, 247, 111, 130}}},
{Region: "Finland", IPs: []net.IP{{188, 126, 89, 4}, {188, 126, 89, 194}}},
{Region: "France", IPs: []net.IP{{156, 146, 63, 1}, {156, 146, 63, 65}}},
{Region: "Greece", IPs: []net.IP{{154, 57, 3, 91}, {154, 57, 3, 106}, {154, 57, 3, 145}}},
{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}, {185, 189, 114, 98}}},
{Region: "Iceland", IPs: []net.IP{{45, 133, 193, 50}}},
{Region: "India", IPs: []net.IP{{45, 120, 139, 108}, {45, 120, 139, 109}, {150, 242, 12, 155}, {150, 242, 12, 171}, {150, 242, 12, 187}}},
{Region: "Ireland", IPs: []net.IP{{193, 56, 252, 210}, {193, 56, 252, 226}, {193, 56, 252, 242}, {193, 56, 252, 250}, {193, 56, 252, 251}, {193, 56, 252, 252}}},
{Region: "Israel", IPs: []net.IP{{31, 168, 172, 142}, {31, 168, 172, 143}, {31, 168, 172, 145}, {31, 168, 172, 146}}},
{Region: "Italy", IPs: []net.IP{{156, 146, 41, 129}, {156, 146, 41, 193}}},
{Region: "Japan", IPs: []net.IP{{156, 146, 34, 1}, {156, 146, 34, 65}}},
{Region: "Latvia", IPs: []net.IP{{46, 183, 217, 34}, {46, 183, 218, 130}, {46, 183, 218, 146}}},
{Region: "Lithuania", IPs: []net.IP{{85, 206, 165, 96}, {85, 206, 165, 112}, {85, 206, 165, 128}}},
{Region: "Luxembourg", IPs: []net.IP{{92, 223, 89, 133}, {92, 223, 89, 134}, {92, 223, 89, 135}, {92, 223, 89, 136}, {92, 223, 89, 137}, {92, 223, 89, 138}, {92, 223, 89, 140}, {92, 223, 89, 142}}},
{Region: "Moldova", IPs: []net.IP{{178, 17, 172, 242}, {178, 17, 173, 194}, {178, 175, 128, 34}}},
{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: "North Macedonia", IPs: []net.IP{{185, 225, 28, 130}}},
{Region: "Norway", IPs: []net.IP{{46, 246, 122, 34}, {46, 246, 122, 162}}},
{Region: "Poland", IPs: []net.IP{{185, 244, 214, 195}, {185, 244, 214, 196}, {185, 244, 214, 197}, {185, 244, 214, 198}, {185, 244, 214, 199}, {185, 244, 214, 200}}},
{Region: "Portugal", IPs: []net.IP{{89, 26, 241, 86}, {89, 26, 241, 102}, {89, 26, 241, 130}}},
{Region: "Romania", IPs: []net.IP{{86, 105, 25, 69}, {86, 105, 25, 70}, {86, 105, 25, 74}, {86, 105, 25, 75}, {86, 105, 25, 76}, {86, 105, 25, 77}, {86, 105, 25, 78}, {89, 33, 8, 38}, {89, 33, 8, 42}, {93, 115, 7, 70}, {94, 176, 148, 35}, {143, 244, 54, 1}, {185, 45, 12, 126}, {185, 210, 218, 98}, {185, 210, 218, 99}, {185, 210, 218, 100}, {185, 210, 218, 101}, {185, 210, 218, 102}, {185, 210, 218, 105}, {188, 240, 220, 26}}},
{Region: "Serbia", IPs: []net.IP{{37, 120, 193, 226}}},
{Region: "Singapore", IPs: []net.IP{{156, 146, 56, 193}, {156, 146, 57, 38}, {156, 146, 57, 235}, {156, 146, 57, 244}}},
{Region: "Slovakia", IPs: []net.IP{{37, 120, 221, 82}, {37, 120, 221, 98}}},
{Region: "South Africa", IPs: []net.IP{{102, 165, 20, 133}}},
{Region: "Spain", IPs: []net.IP{{212, 102, 49, 185}, {212, 102, 49, 251}}},
{Region: "Sweden", IPs: []net.IP{{46, 246, 3, 254}}},
{Region: "Switzerland", IPs: []net.IP{{156, 146, 62, 193}, {212, 102, 36, 1}, {212, 102, 36, 166}, {212, 102, 37, 240}, {212, 102, 37, 241}, {212, 102, 37, 242}, {212, 102, 37, 243}}},
{Region: "Turkey", IPs: []net.IP{{185, 195, 79, 34}, {185, 195, 79, 82}}},
{Region: "UAE", IPs: []net.IP{{45, 9, 250, 46}}},
{Region: "UK London", IPs: []net.IP{{212, 102, 52, 1}}},
{Region: "UK Manchester", IPs: []net.IP{{89, 238, 137, 36}, {89, 238, 137, 37}, {89, 238, 137, 38}, {89, 238, 137, 39}, {89, 238, 139, 52}, {89, 238, 139, 53}, {89, 238, 139, 54}, {89, 238, 139, 55}, {89, 238, 139, 56}, {89, 238, 139, 57}, {89, 238, 139, 58}, {89, 249, 67, 220}}},
{Region: "UK Southampton", IPs: []net.IP{{143, 244, 36, 58}, {143, 244, 37, 1}, {143, 244, 38, 1}, {143, 244, 38, 60}, {143, 244, 38, 119}}},
{Region: "US Atlanta", IPs: []net.IP{{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, 208}, {89, 187, 187, 129}, {89, 187, 187, 162}, {91, 207, 175, 194}, {91, 207, 175, 195}, {91, 207, 175, 197}, {91, 207, 175, 198}, {91, 207, 175, 199}, {91, 207, 175, 200}, {91, 207, 175, 205}, {91, 207, 175, 206}, {91, 207, 175, 207}, {91, 207, 175, 209}, {91, 207, 175, 210}, {91, 207, 175, 212}}},
{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{{156, 146, 38, 65}, {156, 146, 38, 161}, {156, 146, 39, 1}, {156, 146, 39, 6}, {156, 146, 52, 6}, {156, 146, 52, 70}, {156, 146, 52, 139}, {156, 146, 52, 203}}},
{Region: "US Denver", IPs: []net.IP{{70, 39, 77, 130}, {70, 39, 92, 2}, {70, 39, 113, 194}, {174, 128, 225, 2}, {174, 128, 226, 10}, {174, 128, 226, 18}, {174, 128, 227, 2}, {174, 128, 227, 226}, {174, 128, 236, 98}, {174, 128, 242, 234}, {174, 128, 242, 250}, {174, 128, 243, 98}, {174, 128, 244, 74}, {174, 128, 245, 122}, {174, 128, 246, 10}, {199, 115, 98, 146}, {199, 115, 98, 234}, {199, 115, 101, 178}, {199, 115, 101, 186}, {199, 115, 102, 146}}},
{Region: "US East", IPs: []net.IP{{156, 146, 58, 202}, {156, 146, 58, 203}, {156, 146, 58, 204}, {156, 146, 58, 205}, {156, 146, 58, 207}, {156, 146, 58, 208}, {156, 146, 58, 209}, {193, 37, 253, 115}, {193, 37, 253, 134}, {194, 59, 251, 8}, {194, 59, 251, 11}, {194, 59, 251, 22}, {194, 59, 251, 28}, {194, 59, 251, 56}, {194, 59, 251, 62}, {194, 59, 251, 69}, {194, 59, 251, 82}, {194, 59, 251, 84}, {194, 59, 251, 91}, {194, 59, 251, 112}}},
{Region: "US Florida", IPs: []net.IP{{193, 37, 252, 6}, {193, 37, 252, 7}, {193, 37, 252, 8}, {193, 37, 252, 9}, {193, 37, 252, 10}, {193, 37, 252, 11}, {193, 37, 252, 12}, {193, 37, 252, 14}, {193, 37, 252, 15}, {193, 37, 252, 16}, {193, 37, 252, 17}, {193, 37, 252, 18}, {193, 37, 252, 19}, {193, 37, 252, 20}, {193, 37, 252, 21}, {193, 37, 252, 23}, {193, 37, 252, 24}, {193, 37, 252, 25}, {193, 37, 252, 26}, {193, 37, 252, 27}}},
{Region: "US Houston", IPs: []net.IP{{74, 81, 88, 26}, {74, 81, 88, 42}, {74, 81, 88, 66}, {74, 81, 88, 74}, {205, 251, 148, 66}, {205, 251, 148, 90}, {205, 251, 148, 98}, {205, 251, 148, 122}, {205, 251, 148, 130}, {205, 251, 148, 138}, {205, 251, 148, 186}, {205, 251, 150, 146}, {205, 251, 150, 170}}},
{Region: "US Las Vegas", IPs: []net.IP{{79, 110, 53, 50}, {79, 110, 53, 66}, {79, 110, 53, 98}, {79, 110, 53, 114}, {79, 110, 53, 130}, {79, 110, 53, 146}, {79, 110, 53, 162}, {79, 110, 53, 178}, {79, 110, 53, 194}, {79, 110, 53, 210}, {162, 251, 236, 7}, {199, 127, 56, 83}, {199, 127, 56, 84}, {199, 127, 56, 87}, {199, 127, 56, 89}, {199, 127, 56, 90}}},
{Region: "US New York City", IPs: []net.IP{{156, 146, 36, 225}, {156, 146, 37, 129}, {156, 146, 58, 1}, {156, 146, 58, 134}}},
{Region: "US Seattle", IPs: []net.IP{{156, 146, 48, 65}, {156, 146, 48, 135}, {156, 146, 48, 200}, {156, 146, 49, 13}, {212, 102, 46, 129}, {212, 102, 46, 193}, {212, 102, 47, 134}}},
{Region: "US Silicon Valley", IPs: []net.IP{{199, 116, 118, 130}, {199, 116, 118, 132}, {199, 116, 118, 134}, {199, 116, 118, 136}, {199, 116, 118, 145}, {199, 116, 118, 148}, {199, 116, 118, 149}, {199, 116, 118, 157}, {199, 116, 118, 166}, {199, 116, 118, 169}, {199, 116, 118, 172}}},
{Region: "US Washington DC", IPs: []net.IP{{70, 32, 0, 46}, {70, 32, 0, 51}, {70, 32, 0, 53}, {70, 32, 0, 62}, {70, 32, 0, 64}, {70, 32, 0, 68}, {70, 32, 0, 69}, {70, 32, 0, 72}, {70, 32, 0, 76}, {70, 32, 0, 77}, {70, 32, 0, 106}, {70, 32, 0, 107}, {70, 32, 0, 114}, {70, 32, 0, 116}, {70, 32, 0, 120}, {70, 32, 0, 167}, {70, 32, 0, 168}, {70, 32, 0, 170}, {70, 32, 0, 172}, {70, 32, 0, 173}}},
{Region: "US West", IPs: []net.IP{{184, 170, 241, 130}, {184, 170, 241, 194}, {184, 170, 242, 135}, {184, 170, 242, 199}}},
{Region: "Ukraine", IPs: []net.IP{{62, 149, 20, 10}, {62, 149, 20, 40}}},
}
}
const (
PIAPortForwardURL models.URL = "http://209.222.18.222:2000"
)

View File

@@ -0,0 +1,206 @@
package constants
import (
"net"
"github.com/qdm12/gluetun/internal/models"
)
//nolint:lll
const (
PrivadoCertificate = "MIIFKDCCAxCgAwIBAgIJAMtrmqZxIV/OMA0GCSqGSIb3DQEBDQUAMBIxEDAOBgNVBAMMB1ByaXZhZG8wHhcNMjAwMTA4MjEyODQ1WhcNMzUwMTA5MjEyODQ1WjASMRAwDgYDVQQDDAdQcml2YWRvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxPwOgiwNJzZTnKIXwAB0TSu/Lu2qt2U2I8obtQjwhi/7OrfmbmYykSdro70al2XPhnwAGGdCxW6LDnp0UN/IOhD11mgBPo14f5CLkBQjSJ6VN5miPbvK746LsNZl9H8rQGvDuPo4CG9BfPZMiDRGlsMxij/jztzgT1gmuxQ7WHfFRcNzBas1dHa9hV/d3TU6/t47x4SE/ljdcCtJiu7Zn6ODKQoys3mB7Luz2ngqUJWvkqsg+E4+3eJ0M8Hlbn5TPaRJBID7DAdYo6Vs6xGCYr981ThFcmoIQ10js10yANrrfGAzd03b3TnLAgko0uQMHjliMZL6L8sWOPHxyxJI0us88SFh4UgcFyRHKHPKux7w24SxAlZUYoUcTHp9VjG5XvDKYxzgV2RdM4ulBGbQRQ3y3/CyddsyQYMvA55Ets0LfPaBvDIcct70iXijGsdvlX1du3ArGpG7Vaje/RU4nbbGT6HYRdt5YyZfof288ukMOSj20nVcmS+c/4tqsxSerRb1aq5LOi1IemSkTMeC5gCbexk+L1vl7NT/58sxjGmu5bXwnvev/lIItfi2AlITrfUSEv19iDMKkeshwn/+sFJBMWYyluP+yJ56yR+MWoXvLlSWphLDTqq19yx3BZn0P1tgbXoR0g8PTdJFcz8z3RIb7myVLYulV1oGG/3rka0CAwEAAaOBgDB+MB0GA1UdDgQWBBTFtJkZCVDuDAD6k5bJzefjJdO3DTBCBgNVHSMEOzA5gBTFtJkZCVDuDAD6k5bJzefjJdO3DaEWpBQwEjEQMA4GA1UEAwwHUHJpdmFkb4IJAMtrmqZxIV/OMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBDQUAA4ICAQB7MUSXMeBb9wlSv4sUaT1JHEwE26nlBw+TKmezfuPU5pBlY0LYr6qQZY95DHqsRJ7ByUzGUrGo17dNGXlcuNc6TAaQQEDRPo6y+LVh2TWMk15TUMI+MkqryJtCret7xGvDigKYMJgBy58HN3RAVr1B7cL9youwzLgc2Y/NcFKvnQJKeiIYAJ7g0CcnJiQvgZTS7xdwkEBXfsngmUCIG320DLPEL+Ze0HiUrxwWljMRya6i40AeH3Zu2i532xX1wV5+cjA4RJWIKg6ri/Q54iFGtZrA9/nc6y9uoQHkmz8cGyVUmJxFzMrrIICVqUtVRxLhkTMe4UzwRWTBeGgtW4tS0yq1QonAKfOyjgRw/CeY55D2UGvnAFZdTadtYXS4Alu2P9zdwoEk3fzHiVmDjqfJVr5wz9383aABUFrPI3nz6ed/Z6LZflKh1k+DUDEp8NxU4klUULWsSOKoa5zGX51G8cdHxwQLImXvtGuN5eSR8jCTgxFZhdps/xes4KkyfIz9FMYG748M+uOTgKITf4zdJ9BAyiQaOufVQZ8WjhWzWk9YHec9VqPkzpWNGkVjiRI5ewuXwZzZ164tMv2hikBXSuUCnFz37/ZNwGlDi0oBdDszCk2GxccdFHHaCSmpjU5MrdJ+5IhtTKGeTx+US2hTIVHQFIO99DmacxSYvLNcSQ=="
)
func PrivadoHostnameChoices() (choices []string) {
servers := PrivadoServers()
choices = make([]string, len(servers))
for i := range servers {
choices[i] = servers[i].Hostname
}
return choices
}
//nolint:gomnd
func PrivadoServers() []models.PrivadoServer {
return []models.PrivadoServer{
{Hostname: "akl-001.vpn.privado.io", IP: net.IP{23, 254, 104, 114}},
{Hostname: "akl-002.vpn.privado.io", IP: net.IP{23, 254, 104, 120}},
{Hostname: "akl-003.vpn.privado.io", IP: net.IP{23, 254, 104, 51}},
{Hostname: "ams-001.vpn.privado.io", IP: net.IP{91, 148, 224, 10}},
{Hostname: "ams-002.vpn.privado.io", IP: net.IP{91, 148, 224, 20}},
{Hostname: "ams-003.vpn.privado.io", IP: net.IP{91, 148, 224, 30}},
{Hostname: "ams-004.vpn.privado.io", IP: net.IP{91, 148, 224, 40}},
{Hostname: "ams-005.vpn.privado.io", IP: net.IP{91, 148, 224, 50}},
{Hostname: "ams-006.vpn.privado.io", IP: net.IP{91, 148, 224, 60}},
{Hostname: "ams-007.vpn.privado.io", IP: net.IP{91, 148, 224, 70}},
{Hostname: "ams-008.vpn.privado.io", IP: net.IP{91, 148, 224, 80}},
{Hostname: "ams-009.vpn.privado.io", IP: net.IP{91, 148, 228, 10}},
{Hostname: "ams-010.vpn.privado.io", IP: net.IP{91, 148, 228, 20}},
{Hostname: "ams-011.vpn.privado.io", IP: net.IP{91, 148, 228, 30}},
{Hostname: "ams-012.vpn.privado.io", IP: net.IP{91, 148, 228, 40}},
{Hostname: "ams-013.vpn.privado.io", IP: net.IP{91, 148, 228, 50}},
{Hostname: "ams-014.vpn.privado.io", IP: net.IP{91, 148, 228, 60}},
{Hostname: "ams-015.vpn.privado.io", IP: net.IP{91, 148, 228, 70}},
{Hostname: "ams-016.vpn.privado.io", IP: net.IP{91, 148, 228, 80}},
{Hostname: "arn-001.vpn.privado.io", IP: net.IP{86, 106, 103, 67}},
{Hostname: "arn-002.vpn.privado.io", IP: net.IP{86, 106, 103, 74}},
{Hostname: "arn-003.vpn.privado.io", IP: net.IP{86, 106, 103, 81}},
{Hostname: "ath-001.vpn.privado.io", IP: net.IP{188, 123, 126, 61}},
{Hostname: "ath-002.vpn.privado.io", IP: net.IP{188, 123, 126, 64}},
{Hostname: "ath-003.vpn.privado.io", IP: net.IP{188, 123, 126, 68}},
{Hostname: "ath-004.vpn.privado.io", IP: net.IP{188, 123, 126, 72}},
{Hostname: "beg-001.vpn.privado.io", IP: net.IP{89, 38, 224, 19}},
{Hostname: "beg-002.vpn.privado.io", IP: net.IP{89, 38, 224, 25}},
{Hostname: "bkk-001.vpn.privado.io", IP: net.IP{119, 59, 111, 3}},
{Hostname: "bkk-002.vpn.privado.io", IP: net.IP{119, 59, 111, 11}},
{Hostname: "bom-001.vpn.privado.io", IP: net.IP{103, 26, 204, 61}},
{Hostname: "bom-002.vpn.privado.io", IP: net.IP{103, 26, 204, 70}},
{Hostname: "bru-001.vpn.privado.io", IP: net.IP{217, 138, 211, 163}},
{Hostname: "bru-002.vpn.privado.io", IP: net.IP{217, 138, 211, 170}},
{Hostname: "bru-003.vpn.privado.io", IP: net.IP{217, 138, 211, 177}},
{Hostname: "bru-004.vpn.privado.io", IP: net.IP{217, 138, 211, 184}},
{Hostname: "bts-001.vpn.privado.io", IP: net.IP{37, 120, 221, 227}},
{Hostname: "bts-002.vpn.privado.io", IP: net.IP{37, 120, 221, 233}},
{Hostname: "bud-001.vpn.privado.io", IP: net.IP{185, 128, 26, 194}},
{Hostname: "bud-002.vpn.privado.io", IP: net.IP{185, 128, 26, 200}},
{Hostname: "cdg-001.vpn.privado.io", IP: net.IP{89, 40, 183, 99}},
{Hostname: "cdg-002.vpn.privado.io", IP: net.IP{89, 40, 183, 106}},
{Hostname: "cdg-003.vpn.privado.io", IP: net.IP{89, 40, 183, 113}},
{Hostname: "cdg-004.vpn.privado.io", IP: net.IP{89, 40, 183, 120}},
{Hostname: "cph-001.vpn.privado.io", IP: net.IP{2, 58, 46, 35}},
{Hostname: "cph-002.vpn.privado.io", IP: net.IP{2, 58, 46, 42}},
{Hostname: "cph-003.vpn.privado.io", IP: net.IP{2, 58, 46, 49}},
{Hostname: "cph-004.vpn.privado.io", IP: net.IP{2, 58, 46, 56}},
{Hostname: "dca-001.vpn.privado.io", IP: net.IP{85, 12, 61, 10}},
{Hostname: "dca-002.vpn.privado.io", IP: net.IP{85, 12, 61, 20}},
{Hostname: "dca-003.vpn.privado.io", IP: net.IP{85, 12, 61, 30}},
{Hostname: "dca-004.vpn.privado.io", IP: net.IP{85, 12, 61, 40}},
{Hostname: "dca-005.vpn.privado.io", IP: net.IP{85, 12, 61, 50}},
{Hostname: "dca-006.vpn.privado.io", IP: net.IP{85, 12, 61, 60}},
{Hostname: "dca-007.vpn.privado.io", IP: net.IP{85, 12, 61, 70}},
{Hostname: "dca-008.vpn.privado.io", IP: net.IP{85, 12, 61, 80}},
{Hostname: "dca-013.vpn.privado.io", IP: net.IP{185, 247, 68, 3}},
{Hostname: "dca-014.vpn.privado.io", IP: net.IP{185, 247, 68, 10}},
{Hostname: "dca-015.vpn.privado.io", IP: net.IP{185, 247, 68, 17}},
{Hostname: "dca-016.vpn.privado.io", IP: net.IP{185, 247, 68, 24}},
{Hostname: "dfw-001.vpn.privado.io", IP: net.IP{23, 105, 32, 243}},
{Hostname: "dfw-002.vpn.privado.io", IP: net.IP{23, 105, 32, 244}},
{Hostname: "dub-001.vpn.privado.io", IP: net.IP{84, 247, 48, 227}},
{Hostname: "dub-002.vpn.privado.io", IP: net.IP{84, 247, 48, 234}},
{Hostname: "dub-003.vpn.privado.io", IP: net.IP{84, 247, 48, 241}},
{Hostname: "dub-004.vpn.privado.io", IP: net.IP{84, 247, 48, 248}},
{Hostname: "eze-001.vpn.privado.io", IP: net.IP{168, 205, 93, 211}},
{Hostname: "eze-002.vpn.privado.io", IP: net.IP{168, 205, 93, 217}},
{Hostname: "fra-001.vpn.privado.io", IP: net.IP{91, 148, 232, 10}},
{Hostname: "fra-002.vpn.privado.io", IP: net.IP{91, 148, 232, 20}},
{Hostname: "fra-003.vpn.privado.io", IP: net.IP{91, 148, 232, 30}},
{Hostname: "fra-004.vpn.privado.io", IP: net.IP{91, 148, 232, 40}},
{Hostname: "fra-005.vpn.privado.io", IP: net.IP{91, 148, 233, 7}},
{Hostname: "fra-006.vpn.privado.io", IP: net.IP{91, 148, 233, 8}},
{Hostname: "fra-007.vpn.privado.io", IP: net.IP{91, 148, 233, 9}},
{Hostname: "fra-008.vpn.privado.io", IP: net.IP{91, 148, 233, 10}},
{Hostname: "gru-001.vpn.privado.io", IP: net.IP{177, 54, 145, 193}},
{Hostname: "gru-002.vpn.privado.io", IP: net.IP{177, 54, 145, 197}},
{Hostname: "hel-001.vpn.privado.io", IP: net.IP{194, 34, 134, 219}},
{Hostname: "hel-002.vpn.privado.io", IP: net.IP{194, 34, 134, 227}},
{Hostname: "hkg-001.vpn.privado.io", IP: net.IP{209, 58, 185, 88}},
{Hostname: "hkg-002.vpn.privado.io", IP: net.IP{209, 58, 185, 97}},
{Hostname: "hkg-003.vpn.privado.io", IP: net.IP{209, 58, 185, 108}},
{Hostname: "hkg-004.vpn.privado.io", IP: net.IP{209, 58, 185, 120}},
{Hostname: "icn-001.vpn.privado.io", IP: net.IP{169, 56, 73, 146}},
{Hostname: "icn-002.vpn.privado.io", IP: net.IP{169, 56, 73, 153}},
{Hostname: "iev-001.vpn.privado.io", IP: net.IP{176, 103, 52, 40}},
{Hostname: "iev-002.vpn.privado.io", IP: net.IP{176, 103, 53, 40}},
{Hostname: "ist-001.vpn.privado.io", IP: net.IP{185, 84, 183, 3}},
{Hostname: "ist-002.vpn.privado.io", IP: net.IP{185, 84, 183, 4}},
{Hostname: "jfk-001.vpn.privado.io", IP: net.IP{217, 138, 208, 99}},
{Hostname: "jfk-002.vpn.privado.io", IP: net.IP{217, 138, 208, 106}},
{Hostname: "jfk-003.vpn.privado.io", IP: net.IP{217, 138, 208, 113}},
{Hostname: "jfk-004.vpn.privado.io", IP: net.IP{217, 138, 208, 120}},
{Hostname: "jnb-001.vpn.privado.io", IP: net.IP{172, 107, 93, 131}},
{Hostname: "jnb-002.vpn.privado.io", IP: net.IP{172, 107, 93, 137}},
{Hostname: "lax-009.vpn.privado.io", IP: net.IP{45, 152, 182, 227}},
{Hostname: "lax-010.vpn.privado.io", IP: net.IP{45, 152, 182, 234}},
{Hostname: "lax-011.vpn.privado.io", IP: net.IP{45, 152, 182, 241}},
{Hostname: "lax-012.vpn.privado.io", IP: net.IP{45, 152, 182, 248}},
{Hostname: "lis-001.vpn.privado.io", IP: net.IP{89, 26, 243, 153}},
{Hostname: "lis-002.vpn.privado.io", IP: net.IP{89, 26, 243, 154}},
{Hostname: "lon-001.vpn.privado.io", IP: net.IP{217, 138, 195, 163}},
{Hostname: "lon-002.vpn.privado.io", IP: net.IP{217, 138, 195, 170}},
{Hostname: "lon-003.vpn.privado.io", IP: net.IP{217, 138, 195, 177}},
{Hostname: "lon-004.vpn.privado.io", IP: net.IP{217, 138, 195, 184}},
{Hostname: "mad-001.vpn.privado.io", IP: net.IP{217, 138, 218, 131}},
{Hostname: "man-001.vpn.privado.io", IP: net.IP{217, 138, 196, 131}},
{Hostname: "man-002.vpn.privado.io", IP: net.IP{217, 138, 196, 138}},
{Hostname: "man-003.vpn.privado.io", IP: net.IP{217, 138, 196, 145}},
{Hostname: "man-004.vpn.privado.io", IP: net.IP{217, 138, 196, 152}},
{Hostname: "mex-001.vpn.privado.io", IP: net.IP{169, 57, 96, 52}},
{Hostname: "mex-002.vpn.privado.io", IP: net.IP{169, 57, 96, 57}},
{Hostname: "mia-001.vpn.privado.io", IP: net.IP{86, 106, 87, 131}},
{Hostname: "mia-002.vpn.privado.io", IP: net.IP{86, 106, 87, 138}},
{Hostname: "mia-003.vpn.privado.io", IP: net.IP{86, 106, 87, 145}},
{Hostname: "mia-004.vpn.privado.io", IP: net.IP{86, 106, 87, 152}},
{Hostname: "mxp-001.vpn.privado.io", IP: net.IP{89, 40, 182, 195}},
{Hostname: "mxp-002.vpn.privado.io", IP: net.IP{89, 40, 182, 201}},
{Hostname: "nrt-001.vpn.privado.io", IP: net.IP{217, 138, 252, 3}},
{Hostname: "nrt-002.vpn.privado.io", IP: net.IP{217, 138, 252, 10}},
{Hostname: "nrt-003.vpn.privado.io", IP: net.IP{217, 138, 252, 17}},
{Hostname: "nrt-004.vpn.privado.io", IP: net.IP{217, 138, 252, 24}},
{Hostname: "ord-001.vpn.privado.io", IP: net.IP{23, 108, 95, 129}},
{Hostname: "ord-002.vpn.privado.io", IP: net.IP{23, 108, 95, 167}},
{Hostname: "osl-001.vpn.privado.io", IP: net.IP{84, 247, 50, 115}},
{Hostname: "osl-002.vpn.privado.io", IP: net.IP{84, 247, 50, 119}},
{Hostname: "osl-003.vpn.privado.io", IP: net.IP{84, 247, 50, 123}},
{Hostname: "otp-001.vpn.privado.io", IP: net.IP{89, 46, 102, 179}},
{Hostname: "otp-002.vpn.privado.io", IP: net.IP{89, 46, 102, 185}},
{Hostname: "phx-001.vpn.privado.io", IP: net.IP{91, 148, 236, 10}},
{Hostname: "phx-002.vpn.privado.io", IP: net.IP{91, 148, 236, 20}},
{Hostname: "phx-003.vpn.privado.io", IP: net.IP{91, 148, 236, 30}},
{Hostname: "phx-004.vpn.privado.io", IP: net.IP{91, 148, 236, 40}},
{Hostname: "phx-005.vpn.privado.io", IP: net.IP{91, 148, 236, 50}},
{Hostname: "phx-006.vpn.privado.io", IP: net.IP{91, 148, 236, 60}},
{Hostname: "phx-007.vpn.privado.io", IP: net.IP{91, 148, 236, 70}},
{Hostname: "phx-008.vpn.privado.io", IP: net.IP{91, 148, 236, 80}},
{Hostname: "prg-001.vpn.privado.io", IP: net.IP{185, 216, 35, 99}},
{Hostname: "prg-002.vpn.privado.io", IP: net.IP{185, 216, 35, 105}},
{Hostname: "rix-001.vpn.privado.io", IP: net.IP{109, 248, 149, 35}},
{Hostname: "rix-002.vpn.privado.io", IP: net.IP{109, 248, 149, 40}},
{Hostname: "rkv-001.vpn.privado.io", IP: net.IP{82, 221, 131, 78}},
{Hostname: "rkv-002.vpn.privado.io", IP: net.IP{82, 221, 131, 127}},
{Hostname: "sea-001.vpn.privado.io", IP: net.IP{23, 81, 208, 96}},
{Hostname: "sea-002.vpn.privado.io", IP: net.IP{23, 81, 208, 104}},
{Hostname: "sin-001.vpn.privado.io", IP: net.IP{92, 119, 178, 131}},
{Hostname: "sin-002.vpn.privado.io", IP: net.IP{92, 119, 178, 138}},
{Hostname: "sin-003.vpn.privado.io", IP: net.IP{92, 119, 178, 145}},
{Hostname: "sin-004.vpn.privado.io", IP: net.IP{92, 119, 178, 152}},
{Hostname: "sof-001.vpn.privado.io", IP: net.IP{217, 138, 221, 163}},
{Hostname: "sof-002.vpn.privado.io", IP: net.IP{217, 138, 221, 169}},
{Hostname: "stl-001.vpn.privado.io", IP: net.IP{148, 72, 170, 145}},
{Hostname: "stl-002.vpn.privado.io", IP: net.IP{148, 72, 172, 82}},
{Hostname: "syd-001.vpn.privado.io", IP: net.IP{93, 115, 35, 35}},
{Hostname: "syd-002.vpn.privado.io", IP: net.IP{93, 115, 35, 42}},
{Hostname: "syd-003.vpn.privado.io", IP: net.IP{93, 115, 35, 49}},
{Hostname: "syd-004.vpn.privado.io", IP: net.IP{93, 115, 35, 56}},
{Hostname: "vie-001.vpn.privado.io", IP: net.IP{5, 253, 207, 227}},
{Hostname: "vie-002.vpn.privado.io", IP: net.IP{5, 253, 207, 234}},
{Hostname: "vie-003.vpn.privado.io", IP: net.IP{5, 253, 207, 241}},
{Hostname: "vie-004.vpn.privado.io", IP: net.IP{5, 253, 207, 248}},
{Hostname: "vno-001.vpn.privado.io", IP: net.IP{185, 64, 104, 176}},
{Hostname: "vno-002.vpn.privado.io", IP: net.IP{185, 64, 104, 180}},
{Hostname: "waw-001.vpn.privado.io", IP: net.IP{217, 138, 209, 163}},
{Hostname: "waw-002.vpn.privado.io", IP: net.IP{217, 138, 209, 164}},
{Hostname: "waw-003.vpn.privado.io", IP: net.IP{217, 138, 209, 165}},
{Hostname: "waw-004.vpn.privado.io", IP: net.IP{217, 138, 209, 166}},
{Hostname: "yul-001.vpn.privado.io", IP: net.IP{217, 138, 213, 67}},
{Hostname: "yul-002.vpn.privado.io", IP: net.IP{217, 138, 213, 74}},
{Hostname: "yul-003.vpn.privado.io", IP: net.IP{217, 138, 213, 81}},
{Hostname: "yul-004.vpn.privado.io", IP: net.IP{217, 138, 213, 88}},
{Hostname: "yvr-001.vpn.privado.io", IP: net.IP{71, 19, 248, 57}},
{Hostname: "yvr-002.vpn.privado.io", IP: net.IP{71, 19, 248, 113}},
{Hostname: "yyz-003.vpn.privado.io", IP: net.IP{199, 189, 27, 19}},
{Hostname: "zrh-001.vpn.privado.io", IP: net.IP{185, 156, 175, 195}},
{Hostname: "zrh-002.vpn.privado.io", IP: net.IP{185, 156, 175, 202}},
{Hostname: "zrh-003.vpn.privado.io", IP: net.IP{185, 156, 175, 209}},
{Hostname: "zrh-004.vpn.privado.io", IP: net.IP{185, 156, 175, 216}},
}
}

View File

@@ -26,16 +26,16 @@ func GetAllServers() (allServers models.AllServers) {
Timestamp: 1602531173,
Servers: PIAServers(),
},
PiaOld: models.PiaOldServers{
Version: 1,
Timestamp: 1602523433,
Servers: PIAOldServers(),
},
Purevpn: models.PurevpnServers{
Version: 1,
Timestamp: 1599323261,
Servers: PurevpnServers(),
},
Privado: models.PrivadoServers{
Version: 2,
Timestamp: 1604963273,
Servers: PrivadoServers(),
},
Surfshark: models.SurfsharkServers{
Version: 1,
Timestamp: 1599957644,
@@ -47,8 +47,8 @@ func GetAllServers() (allServers models.AllServers) {
Servers: VyprvpnServers(),
},
Windscribe: models.WindscribeServers{
Version: 1,
Timestamp: 1599323261,
Version: 2,
Timestamp: 1604019438,
Servers: WindscribeServers(),
},
}

View File

@@ -54,10 +54,10 @@ func Test_versions(t *testing.T) {
version: allServers.Pia.Version,
digest: "f1e01afe",
},
"Private Internet Access Old": {
model: models.PIAOldServer{},
version: allServers.PiaOld.Version,
digest: "4e25ce4a",
"Privado": {
model: models.PrivadoServer{},
version: allServers.Privado.Version,
digest: "1d5aeb23",
},
"Purevpn": {
model: models.PurevpnServer{},
@@ -77,7 +77,7 @@ func Test_versions(t *testing.T) {
"Windscribe": {
model: models.WindscribeServer{},
version: allServers.Windscribe.Version,
digest: "042bef64",
digest: "6e3ca639",
},
}
for name, testCase := range testCases {
@@ -135,16 +135,16 @@ func Test_timestamps(t *testing.T) {
timestamp: allServers.Pia.Timestamp,
digest: "1571e777",
},
"Private Internet Access Old": {
servers: allServers.PiaOld.Servers,
timestamp: allServers.PiaOld.Timestamp,
digest: "3566a800",
},
"Purevpn": {
servers: allServers.Purevpn.Servers,
timestamp: allServers.Purevpn.Timestamp,
digest: "cdf9b708",
},
"Privado": {
servers: allServers.Privado.Servers,
timestamp: allServers.Privado.Timestamp,
digest: "df2a046d",
},
"Surfshark": {
servers: allServers.Surfshark.Servers,
timestamp: allServers.Surfshark.Timestamp,
@@ -158,7 +158,7 @@ func Test_timestamps(t *testing.T) {
"Windscribe": {
servers: allServers.Windscribe.Servers,
timestamp: allServers.Windscribe.Timestamp,
digest: "eacad593",
digest: "fd87502e",
},
}
for name, testCase := range testCases {

View File

@@ -2,9 +2,9 @@ package constants
const (
// Announcement is a message announcement.
Announcement = "Port forwarding is working for PIA v4 servers"
Announcement = "Support for Privado"
// AnnouncementExpiration is the expiration date of the announcement in format yyyy-mm-dd.
AnnouncementExpiration = "2020-11-15"
AnnouncementExpiration = "2020-11-25"
)
const (

View File

@@ -7,8 +7,6 @@ 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.
@@ -23,6 +21,8 @@ const (
Nordvpn models.VPNProvider = "nordvpn"
// PureVPN is a VPN provider.
Purevpn models.VPNProvider = "purevpn"
// Privado is a VPN provider.
Privado models.VPNProvider = "privado"
)
const (

View File

@@ -21,79 +21,319 @@ func WindscribeRegionChoices() (choices []string) {
return choices
}
func WindscribeCityChoices() (choices []string) {
servers := WindscribeServers()
choices = make([]string, len(servers))
for i := range servers {
choices[i] = servers[i].City
}
return choices
}
func WindscribeHostnameChoices() (choices []string) {
servers := WindscribeServers()
choices = make([]string, len(servers))
for i := range servers {
choices[i] = servers[i].Hostname
}
return choices
}
//nolint:lll
func WindscribeServers() []models.WindscribeServer {
return []models.WindscribeServer{
{Region: "Albania", IPs: []net.IP{{31, 171, 152, 179}}},
{Region: "Argentina", IPs: []net.IP{{167, 250, 6, 121}, {190, 105, 236, 19}, {190, 105, 236, 32}, {190, 105, 236, 50}}},
{Region: "Australia", IPs: []net.IP{{45, 121, 208, 160}, {45, 121, 209, 160}, {45, 121, 210, 208}, {103, 62, 50, 208}, {103, 77, 233, 67}, {103, 77, 234, 211}, {116, 90, 72, 243}, {116, 206, 228, 67}}},
{Region: "Austria", IPs: []net.IP{{89, 187, 168, 66}, {217, 64, 127, 11}}},
{Region: "Azerbaijan", IPs: []net.IP{{85, 132, 61, 123}}},
{Region: "Belgium", IPs: []net.IP{{185, 232, 21, 131}, {194, 187, 251, 147}}},
{Region: "Bosnia", IPs: []net.IP{{185, 99, 3, 24}}},
{Region: "Brazil", IPs: []net.IP{{177, 54, 144, 68}, {177, 67, 80, 59}, {189, 1, 172, 12}}},
{Region: "Bulgaria", IPs: []net.IP{{185, 94, 192, 35}}},
{Region: "Canada East", IPs: []net.IP{{23, 154, 160, 177}, {66, 70, 148, 80}, {104, 227, 235, 129}, {104, 254, 92, 11}, {104, 254, 92, 91}, {144, 168, 163, 160}, {144, 168, 163, 193}, {184, 75, 212, 91}, {192, 190, 19, 65}, {192, 190, 19, 97}, {198, 8, 85, 195}, {198, 8, 85, 210}, {199, 204, 208, 158}}},
{Region: "Canada West", IPs: []net.IP{{104, 218, 61, 1}, {104, 218, 61, 33}, {162, 221, 207, 95}, {208, 78, 41, 1}, {208, 78, 41, 131}, {208, 78, 41, 163}}},
{Region: "Colombia", IPs: []net.IP{{138, 121, 203, 203}, {138, 186, 141, 155}}},
{Region: "Croatia", IPs: []net.IP{{85, 10, 56, 252}}},
{Region: "Cyprus", IPs: []net.IP{{157, 97, 132, 43}}},
{Region: "Czech republic", IPs: []net.IP{{185, 156, 174, 11}, {185, 246, 210, 2}}},
{Region: "Denmark", IPs: []net.IP{{134, 90, 149, 147}, {185, 206, 224, 195}}},
{Region: "Estonia", IPs: []net.IP{{46, 22, 211, 251}, {196, 196, 216, 131}}},
{Region: "Fake antarctica", IPs: []net.IP{{23, 154, 160, 212}, {23, 154, 160, 222}}},
{Region: "Finland", IPs: []net.IP{{185, 112, 82, 227}, {194, 34, 133, 82}}},
{Region: "France", IPs: []net.IP{{45, 89, 174, 35}, {82, 102, 18, 35}, {84, 17, 42, 2}, {84, 17, 42, 34}, {185, 156, 173, 187}}},
{Region: "Germany", IPs: []net.IP{{45, 87, 212, 51}, {89, 249, 65, 19}, {185, 130, 184, 195}, {195, 181, 170, 66}, {195, 181, 175, 98}, {217, 138, 194, 115}}},
{Region: "Greece", IPs: []net.IP{{78, 108, 38, 155}, {185, 226, 64, 111}, {188, 123, 126, 146}}},
{Region: "Guinea-Bissau", IPs: []net.IP{{149, 56, 10, 82}}},
{Region: "Hong kong", IPs: []net.IP{{84, 17, 57, 114}, {103, 10, 197, 99}}},
{Region: "Hungary", IPs: []net.IP{{185, 104, 187, 43}}},
{Region: "Iceland", IPs: []net.IP{{82, 221, 139, 38}, {185, 165, 170, 2}}},
{Region: "India", IPs: []net.IP{{103, 205, 140, 227}, {169, 38, 68, 188}, {169, 38, 72, 12}, {169, 38, 72, 14}}},
{Region: "Indonesia", IPs: []net.IP{{45, 127, 134, 91}}},
{Region: "Ireland", IPs: []net.IP{{185, 24, 232, 146}, {185, 104, 219, 2}}},
{Region: "Israel", IPs: []net.IP{{160, 116, 0, 27}, {185, 191, 205, 139}}},
{Region: "Italy", IPs: []net.IP{{37, 120, 135, 83}, {37, 120, 207, 19}, {84, 17, 59, 66}, {87, 101, 94, 195}, {89, 40, 182, 3}}},
{Region: "Japan", IPs: []net.IP{{89, 187, 161, 114}, {193, 148, 16, 243}}},
{Region: "Latvia", IPs: []net.IP{{85, 254, 72, 23}, {89, 111, 33, 220}}},
{Region: "Lithuania", IPs: []net.IP{{85, 206, 163, 225}}},
{Region: "Macedonia", IPs: []net.IP{{185, 225, 28, 51}}},
{Region: "Madagascar", IPs: []net.IP{{104, 20, 26, 217}, {104, 20, 27, 217}, {172, 67, 17, 175}}},
{Region: "Malaysia", IPs: []net.IP{{103, 106, 250, 31}, {103, 212, 69, 232}}},
{Region: "Mexico", IPs: []net.IP{{143, 255, 57, 67}, {190, 103, 179, 211}, {190, 103, 179, 217}, {201, 131, 125, 107}}},
{Region: "Moldova", IPs: []net.IP{{178, 175, 144, 123}}},
{Region: "Netherlands", IPs: []net.IP{{37, 120, 192, 19}, {46, 166, 143, 98}, {72, 11, 157, 35}, {72, 11, 157, 67}, {84, 17, 46, 2}, {185, 212, 171, 131}, {185, 253, 96, 3}}},
{Region: "New zealand", IPs: []net.IP{{103, 62, 49, 113}}},
{Region: "Norway", IPs: []net.IP{{37, 120, 203, 67}, {185, 206, 225, 131}}},
{Region: "Panama", IPs: []net.IP{{138, 186, 142, 203}}},
{Region: "Peru", IPs: []net.IP{{190, 120, 229, 139}}},
{Region: "Philippines", IPs: []net.IP{{103, 103, 0, 118}, {141, 98, 215, 211}}},
{Region: "Poland", IPs: []net.IP{{5, 133, 11, 116}, {84, 17, 55, 98}, {185, 244, 214, 35}}},
{Region: "Portugal", IPs: []net.IP{{94, 46, 13, 215}, {185, 15, 21, 66}}},
{Region: "Romania", IPs: []net.IP{{89, 46, 103, 147}, {91, 207, 102, 147}}},
{Region: "Russia", IPs: []net.IP{{94, 242, 62, 19}, {94, 242, 62, 67}, {95, 213, 193, 195}, {95, 213, 193, 227}, {185, 22, 175, 132}, {188, 124, 42, 99}, {188, 124, 42, 115}}},
{Region: "Serbia", IPs: []net.IP{{141, 98, 103, 19}}},
{Region: "Singapore", IPs: []net.IP{{82, 102, 25, 131}, {103, 62, 48, 224}, {156, 146, 56, 98}, {156, 146, 56, 111}, {185, 200, 117, 163}}},
{Region: "Slovakia", IPs: []net.IP{{185, 245, 85, 3}}},
{Region: "South Africa", IPs: []net.IP{{129, 232, 167, 211}, {165, 73, 248, 91}, {197, 242, 157, 235}}},
{Region: "South Korea", IPs: []net.IP{{27, 255, 92, 52}, {103, 212, 223, 3}, {218, 232, 76, 179}}},
{Region: "Spain", IPs: []net.IP{{37, 120, 142, 227}, {89, 238, 178, 43}, {185, 253, 99, 131}, {217, 138, 218, 99}}},
{Region: "Sweden", IPs: []net.IP{{31, 13, 191, 67}, {79, 142, 76, 198}, {195, 181, 166, 129}}},
{Region: "Switzerland", IPs: []net.IP{{31, 7, 57, 242}, {37, 120, 213, 163}, {84, 17, 53, 2}, {89, 187, 165, 98}, {185, 156, 175, 179}}},
{Region: "Taiwan", IPs: []net.IP{{103, 4, 29, 77}, {185, 189, 160, 12}, {185, 189, 160, 27}, {185, 189, 160, 32}}},
{Region: "Thailand", IPs: []net.IP{{27, 254, 130, 221}, {202, 129, 16, 147}, {202, 129, 16, 155}}},
{Region: "Tunisia", IPs: []net.IP{{41, 231, 5, 23}}},
{Region: "Turkey", IPs: []net.IP{{45, 123, 118, 156}, {45, 123, 119, 11}, {79, 98, 131, 43}, {176, 53, 113, 163}, {185, 125, 33, 227}}},
{Region: "US Central", IPs: []net.IP{{67, 212, 238, 196}, {69, 12, 94, 67}, {104, 129, 18, 3}, {104, 129, 18, 131}, {104, 223, 92, 163}, {107, 150, 31, 3}, {107, 150, 31, 67}, {107, 150, 31, 131}, {107, 161, 86, 131}, {107, 182, 234, 240}, {161, 129, 70, 195}, {162, 222, 198, 67}, {172, 241, 26, 78}, {172, 241, 131, 129}, {198, 12, 76, 211}, {198, 54, 128, 116}, {198, 55, 125, 195}, {199, 115, 96, 83}, {204, 44, 112, 67}, {204, 44, 112, 131}, {206, 217, 139, 19}, {206, 217, 139, 195}, {206, 217, 143, 131}}},
{Region: "US West", IPs: []net.IP{{23, 83, 130, 166}, {23, 83, 131, 187}, {23, 94, 74, 99}, {37, 120, 147, 163}, {64, 120, 2, 174}, {66, 115, 176, 3}, {82, 102, 30, 67}, {89, 187, 185, 34}, {89, 187, 187, 98}, {104, 129, 3, 67}, {104, 129, 3, 163}, {104, 129, 56, 67}, {104, 129, 56, 131}, {104, 152, 222, 33}, {167, 88, 60, 227}, {167, 88, 60, 243}, {172, 241, 214, 202}, {172, 241, 250, 131}, {172, 255, 125, 141}, {185, 236, 200, 35}, {192, 3, 20, 51}, {198, 12, 116, 195}, {198, 23, 242, 147}, {209, 58, 129, 121}, {212, 103, 49, 67}, {216, 45, 53, 131}, {217, 138, 217, 51}, {217, 138, 217, 211}}},
{Region: "Ukraine", IPs: []net.IP{{45, 141, 156, 11}, {45, 141, 156, 50}}},
{Region: "United Arab Emirates", IPs: []net.IP{{45, 9, 249, 43}}},
{Region: "United Kingdom", IPs: []net.IP{{2, 58, 29, 17}, {2, 58, 29, 145}, {81, 92, 207, 69}, {84, 17, 50, 130}, {89, 44, 201, 99}, {89, 238, 135, 133}, {89, 238, 150, 229}, {185, 212, 168, 133}, {212, 102, 63, 32}, {212, 102, 63, 62}, {217, 138, 254, 51}}},
{Region: "Vietnam", IPs: []net.IP{{103, 9, 76, 197}, {103, 9, 79, 186}, {103, 9, 79, 219}}},
{Region: "Windflix CA", IPs: []net.IP{{104, 218, 60, 111}, {104, 254, 92, 99}}},
{Region: "Windflix JP", IPs: []net.IP{{5, 181, 235, 67}}},
{Region: "Windflix UK", IPs: []net.IP{{45, 9, 248, 3}, {81, 92, 200, 85}, {89, 47, 62, 83}}},
{Region: "Windflix US", IPs: []net.IP{{38, 132, 101, 211}, {38, 132, 122, 131}, {38, 132, 122, 195}, {77, 81, 136, 99}, {185, 232, 22, 131}, {217, 138, 206, 211}}},
{Region: "Albania", City: "Tirana", Hostname: "al-002.whiskergalaxy.com", IP: net.IP{31, 171, 152, 179}},
{Region: "Argentina", City: "Buenos Aires", Hostname: "ar-001.whiskergalaxy.com", IP: net.IP{200, 85, 152, 110}},
{Region: "Argentina", City: "Buenos Aires", Hostname: "ar-003.whiskergalaxy.com", IP: net.IP{167, 250, 6, 121}},
{Region: "Argentina", City: "Buenos Aires", Hostname: "ar-004.whiskergalaxy.com", IP: net.IP{190, 105, 236, 50}},
{Region: "Argentina", City: "Buenos Aires", Hostname: "ar-005.whiskergalaxy.com", IP: net.IP{190, 105, 236, 32}},
{Region: "Argentina", City: "Buenos Aires", Hostname: "ar-006.whiskergalaxy.com", IP: net.IP{190, 105, 236, 19}},
{Region: "Australia", City: "Adelaide ", Hostname: "au-011.whiskergalaxy.com", IP: net.IP{103, 108, 92, 83}},
{Region: "Australia", City: "Adelaide", Hostname: "au-008.whiskergalaxy.com", IP: net.IP{116, 90, 72, 243}},
{Region: "Australia", City: "Brisbane", Hostname: "au-007.whiskergalaxy.com", IP: net.IP{103, 62, 50, 208}},
{Region: "Australia", City: "Brisbane", Hostname: "au-014.whiskergalaxy.com", IP: net.IP{43, 245, 160, 35}},
{Region: "Australia", City: "Canberra", Hostname: "au-010.whiskergalaxy.com", IP: net.IP{116, 206, 229, 131}},
{Region: "Australia", City: "Melbourne ", Hostname: "au-005.whiskergalaxy.com", IP: net.IP{45, 121, 209, 160}},
{Region: "Australia", City: "Melbourne ", Hostname: "au-013.whiskergalaxy.com", IP: net.IP{116, 206, 228, 67}},
{Region: "Australia", City: "Perth", Hostname: "au-004.whiskergalaxy.com", IP: net.IP{45, 121, 208, 160}},
{Region: "Australia", City: "Perth", Hostname: "au-012.whiskergalaxy.com", IP: net.IP{103, 77, 234, 211}},
{Region: "Australia", City: "Sydney", Hostname: "au-009.whiskergalaxy.com", IP: net.IP{103, 77, 233, 67}},
{Region: "Australia", City: "Sydney", Hostname: "au-015.whiskergalaxy.com", IP: net.IP{103, 1, 213, 211}},
{Region: "Austria", City: "Vienna", Hostname: "at-001.whiskergalaxy.com", IP: net.IP{217, 64, 127, 11}},
{Region: "Austria", City: "Vienna", Hostname: "at-002.whiskergalaxy.com", IP: net.IP{89, 187, 168, 66}},
{Region: "Belgium", City: "Brussels", Hostname: "be-001.whiskergalaxy.com", IP: net.IP{194, 187, 251, 147}},
{Region: "Belgium", City: "Brussels", Hostname: "be-002.whiskergalaxy.com", IP: net.IP{185, 232, 21, 131}},
{Region: "Brazil", City: "Sao Paulo", Hostname: "br-004.whiskergalaxy.com", IP: net.IP{177, 67, 80, 59}},
{Region: "Brazil", City: "Sao Paulo", Hostname: "br-005.whiskergalaxy.com", IP: net.IP{177, 54, 157, 178}},
{Region: "Brazil", City: "Sao Paulo", Hostname: "br-006.whiskergalaxy.com", IP: net.IP{177, 54, 148, 247}},
{Region: "Bulgaria", City: "Sofia", Hostname: "bg-001.whiskergalaxy.com", IP: net.IP{185, 94, 192, 35}},
{Region: "Canada East", City: "Halifax", Hostname: "ca-029.whiskergalaxy.com", IP: net.IP{199, 204, 208, 158}},
{Region: "Canada East", City: "Montreal", Hostname: "ca-004.whiskergalaxy.com", IP: net.IP{66, 70, 148, 80}},
{Region: "Canada East", City: "Montreal", Hostname: "ca-027.whiskergalaxy.com", IP: net.IP{144, 168, 163, 160}},
{Region: "Canada East", City: "Montreal", Hostname: "ca-028.whiskergalaxy.com", IP: net.IP{144, 168, 163, 193}},
{Region: "Canada East", City: "Montreal", Hostname: "ca-032.whiskergalaxy.com", IP: net.IP{104, 227, 235, 129}},
{Region: "Canada East", City: "Montreal", Hostname: "ca-033.whiskergalaxy.com", IP: net.IP{198, 8, 85, 195}},
{Region: "Canada East", City: "Montreal", Hostname: "ca-034.whiskergalaxy.com", IP: net.IP{198, 8, 85, 210}},
{Region: "Canada East", City: "Toronto", Hostname: "ca-002.whiskergalaxy.com", IP: net.IP{104, 254, 92, 11}},
{Region: "Canada East", City: "Toronto", Hostname: "ca-009.whiskergalaxy.com", IP: net.IP{104, 254, 92, 91}},
{Region: "Canada East", City: "Toronto", Hostname: "ca-017.whiskergalaxy.com", IP: net.IP{184, 75, 212, 91}},
{Region: "Canada East", City: "Toronto", Hostname: "ca-025.whiskergalaxy.com", IP: net.IP{192, 190, 19, 65}},
{Region: "Canada East", City: "Toronto", Hostname: "ca-026.whiskergalaxy.com", IP: net.IP{192, 190, 19, 97}},
{Region: "Canada East", City: "Toronto", Hostname: "ca-030.whiskergalaxy.com", IP: net.IP{23, 154, 160, 177}},
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-005.whiskergalaxy.com", IP: net.IP{162, 221, 207, 95}},
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-011.whiskergalaxy.com", IP: net.IP{104, 218, 61, 1}},
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-012.whiskergalaxy.com", IP: net.IP{104, 218, 61, 33}},
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-016.whiskergalaxy.com", IP: net.IP{208, 78, 41, 1}},
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-017.whiskergalaxy.com", IP: net.IP{208, 78, 41, 131}},
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-019.whiskergalaxy.com", IP: net.IP{208, 78, 41, 163}},
{Region: "Colombia", City: "Bogota", Hostname: "co-001.whiskergalaxy.com", IP: net.IP{138, 121, 203, 203}},
{Region: "Colombia", City: "Bogota", Hostname: "co-002.whiskergalaxy.com", IP: net.IP{138, 186, 141, 155}},
{Region: "Croatia", City: "Zagreb", Hostname: "hr-002.whiskergalaxy.com", IP: net.IP{85, 10, 56, 129}},
{Region: "Cyprus", City: "Nicosia", Hostname: "cy-001.whiskergalaxy.com", IP: net.IP{157, 97, 132, 43}},
{Region: "Czech Republic", City: "Prague ", Hostname: "cz-002.whiskergalaxy.com", IP: net.IP{185, 246, 210, 2}},
{Region: "Czech Republic", City: "Prague", Hostname: "cz-001.whiskergalaxy.com", IP: net.IP{185, 156, 174, 11}},
{Region: "Denmark", City: "Copenhagen", Hostname: "dk-001.whiskergalaxy.com", IP: net.IP{185, 206, 224, 195}},
{Region: "Denmark", City: "Copenhagen", Hostname: "dk-002.whiskergalaxy.com", IP: net.IP{134, 90, 149, 147}},
{Region: "Estonia", City: "Tallinn", Hostname: "ee-001.whiskergalaxy.com", IP: net.IP{46, 22, 211, 251}},
{Region: "Estonia", City: "Tallinn", Hostname: "ee-002.whiskergalaxy.com", IP: net.IP{196, 196, 216, 131}},
{Region: "Fake Antarctica", City: "Troll", Hostname: "aq-001.whiskergalaxy.com", IP: net.IP{23, 154, 160, 212}},
{Region: "Fake Antarctica", City: "Troll", Hostname: "aq-002.whiskergalaxy.com", IP: net.IP{23, 154, 160, 222}},
{Region: "Finland", City: "Helsinki", Hostname: "fi-002.whiskergalaxy.com", IP: net.IP{185, 112, 82, 227}},
{Region: "Finland", City: "Helsinki", Hostname: "fi-003.whiskergalaxy.com", IP: net.IP{194, 34, 133, 82}},
{Region: "Finland", City: "Helsinki", Hostname: "fi-004.whiskergalaxy.com", IP: net.IP{196, 244, 192, 51}},
{Region: "France", City: "Paris", Hostname: "fr-004.whiskergalaxy.com", IP: net.IP{185, 156, 173, 187}},
{Region: "France", City: "Paris", Hostname: "fr-005.whiskergalaxy.com", IP: net.IP{82, 102, 18, 35}},
{Region: "France", City: "Paris", Hostname: "fr-008.whiskergalaxy.com", IP: net.IP{84, 17, 42, 34}},
{Region: "France", City: "Paris", Hostname: "fr-009.whiskergalaxy.com", IP: net.IP{84, 17, 42, 2}},
{Region: "France", City: "Paris", Hostname: "fr-011.whiskergalaxy.com", IP: net.IP{45, 89, 174, 35}},
{Region: "Germany", City: "Frankfurt", Hostname: "de-003.whiskergalaxy.com", IP: net.IP{89, 249, 65, 19}},
{Region: "Germany", City: "Frankfurt", Hostname: "de-006.whiskergalaxy.com", IP: net.IP{185, 130, 184, 195}},
{Region: "Germany", City: "Frankfurt", Hostname: "de-009.whiskergalaxy.com", IP: net.IP{195, 181, 170, 66}},
{Region: "Germany", City: "Frankfurt", Hostname: "de-010.whiskergalaxy.com", IP: net.IP{195, 181, 175, 98}},
{Region: "Germany", City: "Frankfurt", Hostname: "de-011.whiskergalaxy.com", IP: net.IP{217, 138, 194, 115}},
{Region: "Germany", City: "Frankfurt", Hostname: "de-012.whiskergalaxy.com", IP: net.IP{45, 87, 212, 51}},
{Region: "Greece", City: "Athens", Hostname: "gr-002.whiskergalaxy.com", IP: net.IP{78, 108, 38, 155}},
{Region: "Greece", City: "Athens", Hostname: "gr-004.whiskergalaxy.com", IP: net.IP{185, 226, 64, 111}},
{Region: "Greece", City: "Athens", Hostname: "gr-005.whiskergalaxy.com", IP: net.IP{188, 123, 126, 146}},
{Region: "Hong Kong", City: "Hong Kong", Hostname: "hk-005.whiskergalaxy.com", IP: net.IP{103, 10, 197, 99}},
{Region: "Hong Kong", City: "Hong Kong", Hostname: "hk-006.whiskergalaxy.com", IP: net.IP{84, 17, 57, 114}},
{Region: "Hungary", City: "Budapest", Hostname: "hu-001.whiskergalaxy.com", IP: net.IP{185, 104, 187, 43}},
{Region: "Iceland", City: "Reykjavik", Hostname: "is-001.whiskergalaxy.com", IP: net.IP{82, 221, 139, 38}},
{Region: "Iceland", City: "Reykjavik", Hostname: "is-002.whiskergalaxy.com", IP: net.IP{185, 165, 170, 2}},
{Region: "India", City: "Chennai", Hostname: "in-005.whiskergalaxy.com", IP: net.IP{169, 38, 68, 188}},
{Region: "India", City: "Chennai", Hostname: "in-006.whiskergalaxy.com", IP: net.IP{169, 38, 72, 14}},
{Region: "India", City: "Chennai", Hostname: "in-007.whiskergalaxy.com", IP: net.IP{169, 38, 72, 12}},
{Region: "India", City: "Mumbai", Hostname: "in-009.whiskergalaxy.com", IP: net.IP{165, 231, 253, 211}},
{Region: "India", City: "New Delhi", Hostname: "in-008.whiskergalaxy.com", IP: net.IP{103, 205, 140, 227}},
{Region: "Indonesia", City: "Jakarta", Hostname: "id-002.whiskergalaxy.com", IP: net.IP{45, 127, 134, 91}},
{Region: "Ireland", City: "Dublin", Hostname: "ie-001.whiskergalaxy.com", IP: net.IP{185, 24, 232, 146}},
{Region: "Ireland", City: "Dublin", Hostname: "ie-002.whiskergalaxy.com", IP: net.IP{185, 104, 219, 2}},
{Region: "Ireland", City: "Dublin", Hostname: "ie-003.whiskergalaxy.com", IP: net.IP{23, 92, 127, 35}},
{Region: "Israel", City: "Ashdod", Hostname: "il-002.whiskergalaxy.com", IP: net.IP{185, 191, 205, 139}},
{Region: "Israel", City: "Jerusalem", Hostname: "il-001.whiskergalaxy.com", IP: net.IP{160, 116, 0, 27}},
{Region: "Italy", City: "Milan", Hostname: "it-001.whiskergalaxy.com", IP: net.IP{37, 120, 135, 83}},
{Region: "Italy", City: "Milan", Hostname: "it-004.whiskergalaxy.com", IP: net.IP{84, 17, 59, 66}},
{Region: "Italy", City: "Milan", Hostname: "it-005.whiskergalaxy.com", IP: net.IP{89, 40, 182, 3}},
{Region: "Italy", City: "Rome", Hostname: "it-003.whiskergalaxy.com", IP: net.IP{87, 101, 94, 195}},
{Region: "Italy", City: "Rome", Hostname: "it-006.whiskergalaxy.com", IP: net.IP{37, 120, 207, 19}},
{Region: "Japan", City: "Tokyo", Hostname: "jp-004.whiskergalaxy.com", IP: net.IP{193, 148, 16, 243}},
{Region: "Japan", City: "Tokyo", Hostname: "jp-005.whiskergalaxy.com", IP: net.IP{89, 187, 161, 114}},
{Region: "Latvia", City: "Riga", Hostname: "lv-003.whiskergalaxy.com", IP: net.IP{85, 254, 72, 23}},
{Region: "Latvia", City: "Riga", Hostname: "lv-004.whiskergalaxy.com", IP: net.IP{89, 111, 33, 220}},
{Region: "Lithuania", City: "Siauliai", Hostname: "lt-003.whiskergalaxy.com", IP: net.IP{85, 206, 163, 225}},
{Region: "Malaysia", City: "Kuala Lumpur", Hostname: "my-001.whiskergalaxy.com", IP: net.IP{103, 106, 250, 31}},
{Region: "Malaysia", City: "Kuala Lumpur", Hostname: "my-003.whiskergalaxy.com", IP: net.IP{103, 212, 69, 232}},
{Region: "Mexico", City: "Guadalajara", Hostname: "mx-007.whiskergalaxy.com", IP: net.IP{201, 131, 125, 107}},
{Region: "Mexico", City: "Guadalajara", Hostname: "mx-008.whiskergalaxy.com", IP: net.IP{143, 255, 57, 67}},
{Region: "Mexico", City: "Mexico City", Hostname: "mx-009.whiskergalaxy.com", IP: net.IP{190, 103, 179, 211}},
{Region: "Mexico", City: "Mexico City", Hostname: "mx-010.whiskergalaxy.com", IP: net.IP{190, 103, 179, 217}},
{Region: "Moldova", City: "Chisinau", Hostname: "md-002.whiskergalaxy.com", IP: net.IP{178, 175, 144, 123}},
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-001.whiskergalaxy.com", IP: net.IP{46, 166, 143, 98}},
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-005.whiskergalaxy.com", IP: net.IP{185, 212, 171, 131}},
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-008.whiskergalaxy.com", IP: net.IP{185, 253, 96, 3}},
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-011.whiskergalaxy.com", IP: net.IP{84, 17, 46, 2}},
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-012.whiskergalaxy.com", IP: net.IP{37, 120, 192, 19}},
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-013.whiskergalaxy.com", IP: net.IP{72, 11, 157, 67}},
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-014.whiskergalaxy.com", IP: net.IP{72, 11, 157, 35}},
{Region: "Netherlands", City: "Amsterdam", Hostname: "nl-015.whiskergalaxy.com", IP: net.IP{109, 201, 130, 2}},
{Region: "New Zealand", City: "Auckland ", Hostname: "nz-003.whiskergalaxy.com", IP: net.IP{103, 108, 94, 163}},
{Region: "New Zealand", City: "Auckland", Hostname: "nz-002.whiskergalaxy.com", IP: net.IP{103, 62, 49, 113}},
{Region: "North Macedonia", City: "Skopje", Hostname: "mk-001.whiskergalaxy.com", IP: net.IP{185, 225, 28, 51}},
{Region: "Norway", City: "Oslo", Hostname: "no-003.whiskergalaxy.com", IP: net.IP{185, 206, 225, 131}},
{Region: "Norway", City: "Oslo", Hostname: "no-006.whiskergalaxy.com", IP: net.IP{37, 120, 203, 67}},
{Region: "Panama", City: "Panama City", Hostname: "pa-001.whiskergalaxy.com", IP: net.IP{138, 186, 142, 203}},
{Region: "Peru", City: "Lima", Hostname: "pe-002.whiskergalaxy.com", IP: net.IP{190, 120, 229, 139}},
{Region: "Philippines", City: "Manila", Hostname: "ph-003.whiskergalaxy.com", IP: net.IP{141, 98, 215, 211}},
{Region: "Philippines", City: "San Antonio", Hostname: "ph-002.whiskergalaxy.com", IP: net.IP{103, 103, 0, 118}},
{Region: "Poland", City: "Warsaw", Hostname: "pl-002.whiskergalaxy.com", IP: net.IP{185, 244, 214, 35}},
{Region: "Poland", City: "Warsaw", Hostname: "pl-004.whiskergalaxy.com", IP: net.IP{84, 17, 55, 98}},
{Region: "Poland", City: "Warsaw", Hostname: "pl-005.whiskergalaxy.com", IP: net.IP{5, 133, 11, 116}},
{Region: "Portugal", City: "Lisbon", Hostname: "pt-002.whiskergalaxy.com", IP: net.IP{94, 46, 13, 215}},
{Region: "Portugal", City: "Lisbon", Hostname: "pt-003.whiskergalaxy.com", IP: net.IP{185, 15, 21, 66}},
{Region: "Romania", City: "Bucharest", Hostname: "ro-006.whiskergalaxy.com", IP: net.IP{89, 46, 103, 147}},
{Region: "Romania", City: "Bucharest", Hostname: "ro-008.whiskergalaxy.com", IP: net.IP{91, 207, 102, 147}},
{Region: "Russia", City: "Moscow", Hostname: "ru-010.whiskergalaxy.com", IP: net.IP{95, 213, 193, 227}},
{Region: "Russia", City: "Moscow", Hostname: "ru-011.whiskergalaxy.com", IP: net.IP{95, 213, 193, 195}},
{Region: "Russia", City: "Saint Petersburg", Hostname: "ru-008.whiskergalaxy.com", IP: net.IP{94, 242, 62, 19}},
{Region: "Russia", City: "Saint Petersburg", Hostname: "ru-009.whiskergalaxy.com", IP: net.IP{94, 242, 62, 67}},
{Region: "Russia", City: "Saint Petersburg", Hostname: "ru-012.whiskergalaxy.com", IP: net.IP{188, 124, 42, 115}},
{Region: "Russia", City: "Saint Petersburg", Hostname: "ru-013.whiskergalaxy.com", IP: net.IP{188, 124, 42, 99}},
{Region: "Serbia", City: "Belgrade", Hostname: "rs-003.whiskergalaxy.com", IP: net.IP{141, 98, 103, 19}},
{Region: "Singapore", City: "Singapore", Hostname: "sg-003.whiskergalaxy.com", IP: net.IP{185, 200, 117, 163}},
{Region: "Singapore", City: "Singapore", Hostname: "sg-004.whiskergalaxy.com", IP: net.IP{82, 102, 25, 131}},
{Region: "Singapore", City: "Singapore", Hostname: "sg-005.whiskergalaxy.com", IP: net.IP{103, 62, 48, 224}},
{Region: "Singapore", City: "Singapore", Hostname: "sg-006.whiskergalaxy.com", IP: net.IP{156, 146, 56, 98}},
{Region: "Singapore", City: "Singapore", Hostname: "sg-007.whiskergalaxy.com", IP: net.IP{156, 146, 56, 111}},
{Region: "Slovakia", City: "Bratislava", Hostname: "sk-001.whiskergalaxy.com", IP: net.IP{185, 245, 85, 3}},
{Region: "South Africa", City: "Johannesburg", Hostname: "za-001.whiskergalaxy.com", IP: net.IP{197, 242, 157, 235}},
{Region: "South Africa", City: "Johannesburg", Hostname: "za-002.whiskergalaxy.com", IP: net.IP{129, 232, 167, 211}},
{Region: "South Africa", City: "Johannesburg", Hostname: "za-003.whiskergalaxy.com", IP: net.IP{197, 242, 156, 53}},
{Region: "South Africa", City: "Johannesburg", Hostname: "za-004.whiskergalaxy.com", IP: net.IP{165, 73, 248, 91}},
{Region: "South Korea", City: "Seoul", Hostname: "kr-001.whiskergalaxy.com", IP: net.IP{103, 212, 223, 3}},
{Region: "South Korea", City: "Seoul", Hostname: "kr-002.whiskergalaxy.com", IP: net.IP{218, 232, 76, 179}},
{Region: "South Korea", City: "Seoul", Hostname: "kr-005.whiskergalaxy.com", IP: net.IP{45, 133, 194, 235}},
{Region: "Spain", City: "Barcelona", Hostname: "es-004.whiskergalaxy.com", IP: net.IP{37, 120, 142, 227}},
{Region: "Spain", City: "Madrid", Hostname: "es-002.whiskergalaxy.com", IP: net.IP{89, 238, 178, 43}},
{Region: "Spain", City: "Madrid", Hostname: "es-003.whiskergalaxy.com", IP: net.IP{217, 138, 218, 99}},
{Region: "Sweden", City: "Stockholm", Hostname: "se-001.whiskergalaxy.com", IP: net.IP{31, 13, 191, 67}},
{Region: "Sweden", City: "Stockholm", Hostname: "se-002.whiskergalaxy.com", IP: net.IP{79, 142, 76, 198}},
{Region: "Sweden", City: "Stockholm", Hostname: "se-003.whiskergalaxy.com", IP: net.IP{195, 181, 166, 129}},
{Region: "Switzerland", City: "Zurich", Hostname: "ch-001.whiskergalaxy.com", IP: net.IP{31, 7, 57, 242}},
{Region: "Switzerland", City: "Zurich", Hostname: "ch-003.whiskergalaxy.com", IP: net.IP{185, 156, 175, 179}},
{Region: "Switzerland", City: "Zurich", Hostname: "ch-005.whiskergalaxy.com", IP: net.IP{89, 187, 165, 98}},
{Region: "Switzerland", City: "Zurich", Hostname: "ch-006.whiskergalaxy.com", IP: net.IP{84, 17, 53, 2}},
{Region: "Switzerland", City: "Zurich", Hostname: "ch-008.whiskergalaxy.com", IP: net.IP{37, 120, 213, 163}},
{Region: "Taiwan", City: "Taipei", Hostname: "tw-008.whiskergalaxy.com", IP: net.IP{103, 4, 29, 77}},
{Region: "Taiwan", City: "Taipei", Hostname: "tw-009.whiskergalaxy.com", IP: net.IP{185, 189, 160, 12}},
{Region: "Taiwan", City: "Taipei", Hostname: "tw-010.whiskergalaxy.com", IP: net.IP{185, 189, 160, 27}},
{Region: "Taiwan", City: "Taipei", Hostname: "tw-011.whiskergalaxy.com", IP: net.IP{185, 189, 160, 32}},
{Region: "Thailand", City: "Bangkok", Hostname: "th-003.whiskergalaxy.com", IP: net.IP{27, 254, 130, 221}},
{Region: "Thailand", City: "Bangkok", Hostname: "th-005.whiskergalaxy.com", IP: net.IP{202, 129, 16, 147}},
{Region: "Thailand", City: "Bangkok", Hostname: "th-006.whiskergalaxy.com", IP: net.IP{202, 129, 16, 155}},
{Region: "Tunisia", City: "Tunis", Hostname: "tn-001.whiskergalaxy.com", IP: net.IP{41, 231, 5, 23}},
{Region: "Turkey", City: "Bursa", Hostname: "tr-001.whiskergalaxy.com", IP: net.IP{45, 123, 118, 156}},
{Region: "Turkey", City: "Istanbul", Hostname: "tr-004.whiskergalaxy.com", IP: net.IP{45, 123, 119, 11}},
{Region: "Turkey", City: "Istanbul", Hostname: "tr-006.whiskergalaxy.com", IP: net.IP{185, 125, 33, 227}},
{Region: "Turkey", City: "Istanbul", Hostname: "tr-009.whiskergalaxy.com", IP: net.IP{79, 98, 131, 43}},
{Region: "Turkey", City: "Istanbul", Hostname: "tr-011.whiskergalaxy.com", IP: net.IP{176, 53, 113, 163}},
{Region: "US Central", City: "Atlanta", Hostname: "us-central-016.whiskergalaxy.com", IP: net.IP{104, 129, 18, 3}},
{Region: "US Central", City: "Atlanta", Hostname: "us-central-020.whiskergalaxy.com", IP: net.IP{104, 129, 18, 131}},
{Region: "US Central", City: "Atlanta", Hostname: "us-central-034.whiskergalaxy.com", IP: net.IP{161, 129, 70, 195}},
{Region: "US Central", City: "Atlanta", Hostname: "us-central-046.whiskergalaxy.com", IP: net.IP{198, 12, 76, 211}},
{Region: "US Central", City: "Atlanta", Hostname: "us-central-049.whiskergalaxy.com", IP: net.IP{107, 150, 31, 3}},
{Region: "US Central", City: "Atlanta", Hostname: "us-central-050.whiskergalaxy.com", IP: net.IP{107, 150, 31, 67}},
{Region: "US Central", City: "Atlanta", Hostname: "us-central-051.whiskergalaxy.com", IP: net.IP{162, 222, 198, 67}},
{Region: "US Central", City: "Atlanta", Hostname: "us-central-054.whiskergalaxy.com", IP: net.IP{104, 223, 92, 163}},
{Region: "US Central", City: "Atlanta", Hostname: "us-central-056.whiskergalaxy.com", IP: net.IP{206, 217, 143, 131}},
{Region: "US Central", City: "Dallas", Hostname: "us-central-014.whiskergalaxy.com", IP: net.IP{69, 12, 94, 67}},
{Region: "US Central", City: "Dallas", Hostname: "us-central-029.whiskergalaxy.com", IP: net.IP{198, 55, 125, 195}},
{Region: "US Central", City: "Dallas", Hostname: "us-central-036.whiskergalaxy.com", IP: net.IP{204, 44, 112, 67}},
{Region: "US Central", City: "Dallas", Hostname: "us-central-037.whiskergalaxy.com", IP: net.IP{204, 44, 112, 131}},
{Region: "US Central", City: "Dallas", Hostname: "us-central-044.whiskergalaxy.com", IP: net.IP{206, 217, 139, 195}},
{Region: "US Central", City: "Dallas", Hostname: "us-central-045.whiskergalaxy.com", IP: net.IP{172, 241, 131, 129}},
{Region: "US Central", City: "Dallas", Hostname: "us-central-055.whiskergalaxy.com", IP: net.IP{206, 217, 139, 19}},
{Region: "US Central", City: "Dallas", Hostname: "us-central-057.whiskergalaxy.com", IP: net.IP{172, 241, 26, 78}},
{Region: "US Central", City: "Dallas", Hostname: "us-central-060.whiskergalaxy.com", IP: net.IP{198, 55, 126, 131}},
{Region: "US Central", City: "Denver", Hostname: "us-central-043.whiskergalaxy.com", IP: net.IP{199, 115, 96, 83}},
{Region: "US Central", City: "Denver", Hostname: "us-central-058.whiskergalaxy.com", IP: net.IP{198, 54, 128, 116}},
{Region: "US Central", City: "Denver", Hostname: "us-central-062.whiskergalaxy.com", IP: net.IP{174, 128, 251, 147}},
{Region: "US Central", City: "Kansas City", Hostname: "us-central-063.whiskergalaxy.com", IP: net.IP{38, 146, 5, 51}},
{Region: "US Central", City: "Salt Lake City", Hostname: "us-central-047.whiskergalaxy.com", IP: net.IP{107, 182, 234, 240}},
{Region: "US Central", City: "Salt Lake City", Hostname: "us-central-052.whiskergalaxy.com", IP: net.IP{67, 212, 238, 196}},
{Region: "US East", City: "Boston", Hostname: "us-east-039.whiskergalaxy.com", IP: net.IP{199, 217, 104, 227}},
{Region: "US East", City: "Boston", Hostname: "us-east-051.whiskergalaxy.com", IP: net.IP{199, 217, 105, 227}},
{Region: "US East", City: "Buffalo", Hostname: "us-east-045.whiskergalaxy.com", IP: net.IP{104, 168, 34, 147}},
{Region: "US East", City: "Buffalo", Hostname: "us-east-065.whiskergalaxy.com", IP: net.IP{198, 12, 64, 35}},
{Region: "US East", City: "Charlotte", Hostname: "us-east-040.whiskergalaxy.com", IP: net.IP{67, 21, 32, 145}},
{Region: "US East", City: "Chicago", Hostname: "us-east-015.whiskergalaxy.com", IP: net.IP{68, 235, 50, 227}},
{Region: "US East", City: "Chicago", Hostname: "us-east-019.whiskergalaxy.com", IP: net.IP{23, 226, 141, 195}},
{Region: "US East", City: "Chicago", Hostname: "us-east-022.whiskergalaxy.com", IP: net.IP{167, 160, 172, 3}},
{Region: "US East", City: "Chicago", Hostname: "us-east-047.whiskergalaxy.com", IP: net.IP{23, 83, 91, 170}},
{Region: "US East", City: "Chicago", Hostname: "us-east-053.whiskergalaxy.com", IP: net.IP{107, 150, 29, 131}},
{Region: "US East", City: "Chicago", Hostname: "us-east-069.whiskergalaxy.com", IP: net.IP{68, 235, 35, 172}},
{Region: "US East", City: "Chicago", Hostname: "us-east-071.whiskergalaxy.com", IP: net.IP{68, 235, 35, 12}},
{Region: "US East", City: "Chicago", Hostname: "us-east-077.whiskergalaxy.com", IP: net.IP{68, 235, 43, 204}},
{Region: "US East", City: "Cleveland", Hostname: "us-east-078.whiskergalaxy.com", IP: net.IP{38, 101, 74, 19}},
{Region: "US East", City: "Columbus", Hostname: "us-east-059.whiskergalaxy.com", IP: net.IP{67, 219, 146, 67}},
{Region: "US East", City: "Detroit", Hostname: "us-east-079.whiskergalaxy.com", IP: net.IP{104, 244, 210, 51}},
{Region: "US East", City: "Miami", Hostname: "us-east-006.whiskergalaxy.com", IP: net.IP{173, 44, 36, 67}},
{Region: "US East", City: "Miami", Hostname: "us-east-012.whiskergalaxy.com", IP: net.IP{45, 87, 214, 35}},
{Region: "US East", City: "Miami", Hostname: "us-east-028.whiskergalaxy.com", IP: net.IP{104, 223, 127, 195}},
{Region: "US East", City: "Miami", Hostname: "us-east-049.whiskergalaxy.com", IP: net.IP{23, 82, 136, 93}},
{Region: "US East", City: "Miami", Hostname: "us-east-067.whiskergalaxy.com", IP: net.IP{86, 106, 87, 83}},
{Region: "US East", City: "New Jersey", Hostname: "us-east-020.whiskergalaxy.com", IP: net.IP{162, 222, 195, 67}},
{Region: "US East", City: "New Jersey", Hostname: "us-east-054.whiskergalaxy.com", IP: net.IP{167, 160, 167, 195}},
{Region: "US East", City: "New York", Hostname: "us-east-013.whiskergalaxy.com", IP: net.IP{185, 232, 22, 195}},
{Region: "US East", City: "New York", Hostname: "us-east-046.whiskergalaxy.com", IP: net.IP{206, 217, 129, 227}},
{Region: "US East", City: "New York", Hostname: "us-east-050.whiskergalaxy.com", IP: net.IP{173, 208, 45, 33}},
{Region: "US East", City: "New York", Hostname: "us-east-064.whiskergalaxy.com", IP: net.IP{206, 217, 128, 3}},
{Region: "US East", City: "New York", Hostname: "us-east-068.whiskergalaxy.com", IP: net.IP{142, 234, 200, 176}},
{Region: "US East", City: "New York", Hostname: "us-east-073.whiskergalaxy.com", IP: net.IP{217, 138, 255, 163}},
{Region: "US East", City: "New York", Hostname: "us-east-074.whiskergalaxy.com", IP: net.IP{217, 138, 255, 179}},
{Region: "US East", City: "Orlando", Hostname: "us-east-052.whiskergalaxy.com", IP: net.IP{198, 147, 22, 225}},
{Region: "US East", City: "Philadelphia", Hostname: "us-east-060.whiskergalaxy.com", IP: net.IP{76, 72, 175, 99}},
{Region: "US East", City: "Philadelphia", Hostname: "us-east-061.whiskergalaxy.com", IP: net.IP{156, 96, 59, 102}},
{Region: "US East", City: "Washington DC", Hostname: "us-east-048.whiskergalaxy.com", IP: net.IP{23, 82, 8, 143}},
{Region: "US East", City: "Washington DC", Hostname: "us-east-055.whiskergalaxy.com", IP: net.IP{23, 105, 170, 139}},
{Region: "US East", City: "Washington DC", Hostname: "us-east-057.whiskergalaxy.com", IP: net.IP{23, 105, 170, 130}},
{Region: "US East", City: "Washington DC", Hostname: "us-east-058.whiskergalaxy.com", IP: net.IP{23, 105, 170, 151}},
{Region: "US West", City: "Bend", Hostname: "us-west-038.whiskergalaxy.com", IP: net.IP{104, 152, 222, 33}},
{Region: "US West", City: "Las Vegas", Hostname: "us-west-018.whiskergalaxy.com", IP: net.IP{82, 102, 30, 67}},
{Region: "US West", City: "Las Vegas", Hostname: "us-west-030.whiskergalaxy.com", IP: net.IP{37, 120, 147, 163}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-004.whiskergalaxy.com", IP: net.IP{185, 236, 200, 35}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-015.whiskergalaxy.com", IP: net.IP{216, 45, 53, 131}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-027.whiskergalaxy.com", IP: net.IP{212, 103, 49, 67}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-040.whiskergalaxy.com", IP: net.IP{89, 187, 185, 34}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-044.whiskergalaxy.com", IP: net.IP{192, 3, 20, 51}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-047.whiskergalaxy.com", IP: net.IP{172, 241, 214, 202}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-055.whiskergalaxy.com", IP: net.IP{104, 129, 3, 67}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-059.whiskergalaxy.com", IP: net.IP{104, 129, 3, 163}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-060.whiskergalaxy.com", IP: net.IP{217, 138, 217, 51}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-063.whiskergalaxy.com", IP: net.IP{198, 23, 242, 147}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-065.whiskergalaxy.com", IP: net.IP{217, 138, 217, 211}},
{Region: "US West", City: "Los Angeles", Hostname: "us-west-066.whiskergalaxy.com", IP: net.IP{89, 187, 187, 98}},
{Region: "US West", City: "Phoenix", Hostname: "us-west-046.whiskergalaxy.com", IP: net.IP{23, 83, 130, 166}},
{Region: "US West", City: "Phoenix", Hostname: "us-west-061.whiskergalaxy.com", IP: net.IP{23, 83, 131, 187}},
{Region: "US West", City: "San Francisco", Hostname: "us-west-048.whiskergalaxy.com", IP: net.IP{172, 241, 250, 131}},
{Region: "US West", City: "San Francisco", Hostname: "us-west-053.whiskergalaxy.com", IP: net.IP{209, 58, 129, 121}},
{Region: "US West", City: "San Francisco", Hostname: "us-west-054.whiskergalaxy.com", IP: net.IP{172, 255, 125, 141}},
{Region: "US West", City: "San Jose", Hostname: "us-west-052.whiskergalaxy.com", IP: net.IP{66, 115, 176, 3}},
{Region: "US West", City: "Santa Clara", Hostname: "us-west-050.whiskergalaxy.com", IP: net.IP{167, 88, 60, 227}},
{Region: "US West", City: "Santa Clara", Hostname: "us-west-051.whiskergalaxy.com", IP: net.IP{167, 88, 60, 243}},
{Region: "US West", City: "Seattle", Hostname: "us-west-043.whiskergalaxy.com", IP: net.IP{23, 94, 74, 99}},
{Region: "US West", City: "Seattle", Hostname: "us-west-045.whiskergalaxy.com", IP: net.IP{64, 120, 2, 174}},
{Region: "US West", City: "Seattle", Hostname: "us-west-056.whiskergalaxy.com", IP: net.IP{104, 129, 56, 67}},
{Region: "US West", City: "Seattle", Hostname: "us-west-057.whiskergalaxy.com", IP: net.IP{104, 129, 56, 131}},
{Region: "US West", City: "Seattle", Hostname: "us-west-062.whiskergalaxy.com", IP: net.IP{198, 12, 116, 195}},
{Region: "Ukraine", City: "Kyiv", Hostname: "ua-006.whiskergalaxy.com", IP: net.IP{45, 141, 156, 11}},
{Region: "Ukraine", City: "Kyiv", Hostname: "ua-007.whiskergalaxy.com", IP: net.IP{45, 141, 156, 50}},
{Region: "United Arab Emirates", City: "Dubai", Hostname: "ae-001.whiskergalaxy.com", IP: net.IP{45, 9, 249, 43}},
{Region: "United Kingdom", City: "Edinburgh", Hostname: "uk-026.whiskergalaxy.com", IP: net.IP{193, 36, 118, 243}},
{Region: "United Kingdom", City: "London", Hostname: "uk-007.whiskergalaxy.com", IP: net.IP{185, 212, 168, 133}},
{Region: "United Kingdom", City: "London", Hostname: "uk-013.whiskergalaxy.com", IP: net.IP{89, 238, 150, 229}},
{Region: "United Kingdom", City: "London", Hostname: "uk-014.whiskergalaxy.com", IP: net.IP{2, 58, 29, 145}},
{Region: "United Kingdom", City: "London", Hostname: "uk-015.whiskergalaxy.com", IP: net.IP{2, 58, 29, 17}},
{Region: "United Kingdom", City: "London", Hostname: "uk-017.whiskergalaxy.com", IP: net.IP{84, 17, 50, 130}},
{Region: "United Kingdom", City: "London", Hostname: "uk-021.whiskergalaxy.com", IP: net.IP{212, 102, 63, 32}},
{Region: "United Kingdom", City: "London", Hostname: "uk-022.whiskergalaxy.com", IP: net.IP{212, 102, 63, 62}},
{Region: "United Kingdom", City: "London", Hostname: "uk-024.whiskergalaxy.com", IP: net.IP{217, 138, 254, 51}},
{Region: "United Kingdom", City: "Manchester", Hostname: "uk-008.whiskergalaxy.com", IP: net.IP{81, 92, 207, 69}},
{Region: "United Kingdom", City: "Manchester", Hostname: "uk-010.whiskergalaxy.com", IP: net.IP{89, 238, 135, 133}},
{Region: "United Kingdom", City: "Manchester", Hostname: "uk-025.whiskergalaxy.com", IP: net.IP{89, 44, 201, 99}},
{Region: "Vietnam", City: "Hanoi", Hostname: "vn-001.whiskergalaxy.com", IP: net.IP{103, 9, 76, 197}},
{Region: "Vietnam", City: "Hanoi", Hostname: "vn-002.whiskergalaxy.com", IP: net.IP{103, 9, 79, 186}},
{Region: "Vietnam", City: "Hanoi", Hostname: "vn-003.whiskergalaxy.com", IP: net.IP{103, 9, 79, 219}},
{Region: "WINDFLIX CA", City: "Toronto", Hostname: "wf-ca-003.whiskergalaxy.com", IP: net.IP{104, 218, 60, 111}},
{Region: "WINDFLIX CA", City: "Toronto", Hostname: "wf-ca-004.whiskergalaxy.com", IP: net.IP{104, 254, 92, 99}},
{Region: "WINDFLIX JP", City: "Tokyo", Hostname: "wf-jp-002.whiskergalaxy.com", IP: net.IP{5, 181, 235, 67}},
{Region: "WINDFLIX UK", City: "London", Hostname: "wf-uk-001.whiskergalaxy.com", IP: net.IP{45, 9, 248, 3}},
{Region: "WINDFLIX UK", City: "London", Hostname: "wf-uk-006.whiskergalaxy.com", IP: net.IP{81, 92, 200, 85}},
{Region: "WINDFLIX UK", City: "London", Hostname: "wf-uk-007.whiskergalaxy.com", IP: net.IP{89, 47, 62, 83}},
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-010.whiskergalaxy.com", IP: net.IP{38, 132, 122, 195}},
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-011.whiskergalaxy.com", IP: net.IP{38, 132, 122, 131}},
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-012.whiskergalaxy.com", IP: net.IP{185, 232, 22, 131}},
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-013.whiskergalaxy.com", IP: net.IP{217, 138, 206, 211}},
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-014.whiskergalaxy.com", IP: net.IP{77, 81, 136, 99}},
{Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-015.whiskergalaxy.com", IP: net.IP{38, 132, 101, 211}},
}
}

View File

@@ -94,6 +94,10 @@ func (c *configurator) enable(ctx context.Context) (err error) {
return fmt.Errorf("cannot enable firewall: %w", err)
}
if err := c.acceptOutputFromIPToSubnet(ctx, c.defaultInterface, c.localIP, c.localSubnet, remove); err != nil {
return fmt.Errorf("cannot enable firewall: %w", err)
}
for _, subnet := range c.outboundSubnets {
if err := c.acceptOutputFromIPToSubnet(ctx, c.defaultInterface, c.localIP, subnet, remove); err != nil {
return fmt.Errorf("cannot enable firewall: %w", err)

View File

@@ -6,8 +6,10 @@ type OpenVPNConnection struct {
IP net.IP
Port uint16
Protocol NetworkProtocol
Hostname string // Privado for tls verification
}
func (o *OpenVPNConnection) Equal(other OpenVPNConnection) bool {
return o.IP.Equal(other.IP) && o.Port == other.Port && o.Protocol == other.Protocol
return o.IP.Equal(other.IP) && o.Port == other.Port && o.Protocol == other.Protocol &&
o.Hostname == other.Hostname
}

View File

@@ -25,9 +25,9 @@ type ServerSelection struct {
// Cyberghost
Group string `json:"group"`
// Mullvad, PureVPN
Countries []string `json:"countries"`
Cities []string `json:"cities"`
Countries []string `json:"countries"` // Mullvad, PureVPN
Cities []string `json:"cities"` // Mullvad, PureVPN, Windscribe
Hostnames []string `json:"hostnames"` // Windscribe, Privado
// Mullvad
ISPs []string `json:"isps"`
@@ -130,6 +130,11 @@ func (p *ProviderSettings) String() string {
"Countries: "+commaJoin(p.ServerSelection.Countries),
"Cities: "+commaJoin(p.ServerSelection.Cities),
)
case "privado":
settingsList = append(settingsList,
"Cities: "+commaJoin(p.ServerSelection.Cities),
"Server numbers: "+commaJoin(numbers),
)
default:
settingsList = append(settingsList,
"<Missing String method, please implement me!>",

View File

@@ -28,15 +28,6 @@ func (p *PIAServer) String() string {
p.Region, p.PortForward, p.OpenvpnUDP.String(), p.OpenvpnTCP.String())
}
type PIAOldServer struct {
IPs []net.IP `json:"ips"`
Region string `json:"region"`
}
func (p *PIAOldServer) String() string {
return fmt.Sprintf("{Region: %q, IPs: %s}", p.Region, goStringifyIPs(p.IPs))
}
type MullvadServer struct {
IPs []net.IP `json:"ips"`
IPsV6 []net.IP `json:"ipsv6"`
@@ -52,12 +43,15 @@ func (s *MullvadServer) String() string {
}
type WindscribeServer struct {
Region string `json:"region"`
IPs []net.IP `json:"ips"`
Region string `json:"region"`
City string `json:"city"`
Hostname string `json:"hostname"`
IP net.IP `json:"ip"`
}
func (s *WindscribeServer) String() string {
return fmt.Sprintf("{Region: %q, IPs: %s}", s.Region, goStringifyIPs(s.IPs))
return fmt.Sprintf("{Region: %q, City: %q, Hostname: %q, IP: %s}",
s.Region, s.City, s.Hostname, goStringifyIP(s.IP))
}
type SurfsharkServer struct {
@@ -113,6 +107,16 @@ func (s *PurevpnServer) String() string {
s.Region, s.Country, s.City, goStringifyIPs(s.IPs))
}
type PrivadoServer struct {
IP net.IP `json:"ip"`
Hostname string `json:"hostname"`
}
func (s *PrivadoServer) String() string {
return fmt.Sprintf("{Hostname: %q, IP: %s}",
s.Hostname, goStringifyIP(s.IP))
}
func goStringifyIP(ip net.IP) string {
s := fmt.Sprintf("%#v", ip)
s = strings.TrimSuffix(strings.TrimPrefix(s, "net.IP{"), "}")

View File

@@ -7,31 +7,6 @@ import (
"github.com/stretchr/testify/assert"
)
func Test_PIAOldServer_String(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
server PIAOldServer
s string
}{
"no ips": {
server: PIAOldServer{Region: "a b"},
s: `{Region: "a b", IPs: []net.IP{}}`,
},
"with ips": {
server: PIAOldServer{Region: "a b", IPs: []net.IP{{1, 1, 1, 1}, {2, 2, 2, 2}}},
s: `{Region: "a b", IPs: []net.IP{{1, 1, 1, 1}, {2, 2, 2, 2}}}`,
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
s := testCase.server.String()
assert.Equal(t, testCase.s, s)
})
}
}
func Test_MullvadServer_String(t *testing.T) {
t.Parallel()
testCases := map[string]struct {

View File

@@ -5,8 +5,8 @@ type AllServers struct {
Cyberghost CyberghostServers `json:"cyberghost"`
Mullvad MullvadServers `json:"mullvad"`
Nordvpn NordvpnServers `json:"nordvpn"`
PiaOld PiaOldServers `json:"piaOld"`
Pia PiaServers `json:"pia"`
Privado PrivadoServers `json:"privado"`
Purevpn PurevpnServers `json:"purevpn"`
Surfshark SurfsharkServers `json:"surfshark"`
Vyprvpn VyprvpnServers `json:"vyprvpn"`
@@ -28,20 +28,20 @@ type NordvpnServers struct {
Timestamp int64 `json:"timestamp"`
Servers []NordvpnServer `json:"servers"`
}
type PiaOldServers struct {
Version uint16 `json:"version"`
Timestamp int64 `json:"timestamp"`
Servers []PIAOldServer `json:"servers"`
}
type PiaServers struct {
Version uint16 `json:"version"`
Timestamp int64 `json:"timestamp"`
Servers []PIAServer `json:"servers"`
}
type PrivadoServers struct {
Version uint16 `json:"version"`
Timestamp int64 `json:"timestamp"`
Servers []PrivadoServer `json:"servers"`
}
type PurevpnServers struct {
Version uint16 `json:"version"`
Timestamp int64 `json:"timestamp"`
Servers []PurevpnServer `json:"purevpn"`
Servers []PurevpnServer `json:"servers"`
}
type SurfsharkServers struct {
Version uint16 `json:"version"`

View File

@@ -62,7 +62,6 @@ type Reader interface {
GetPortForwardingStatusFilepath() (filepath models.Filepath, err error)
GetPIAEncryptionPreset() (preset string, err error)
GetPIARegions() (regions []string, err error)
GetPIAOldRegions() (regions []string, err error)
// Mullvad getters
GetMullvadCountries() (countries []string, err error)
@@ -73,6 +72,8 @@ type Reader interface {
// Windscribe getters
GetWindscribeRegions() (countries []string, err error)
GetWindscribeCities() (cities []string, err error)
GetWindscribeHostnames() (hostnames []string, err error)
GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error)
// Surfshark getters
@@ -90,6 +91,9 @@ type Reader interface {
GetNordvpnRegions() (regions []string, err error)
GetNordvpnNumbers() (numbers []uint16, err error)
// Privado getters
GetPrivadoHostnames() (hostnames []string, err error)
// PureVPN getters
GetPurevpnRegions() (regions []string, err error)
GetPurevpnCountries() (countries []string, err error)
@@ -147,9 +151,9 @@ func (r *reader) GetVPNSP() (vpnServiceProvider models.VPNProvider, err error) {
s, err := r.envParams.GetValueIfInside(
"VPNSP",
[]string{
"pia", "private internet access", "private internet access old",
"pia", "private internet access",
"mullvad", "windscribe", "surfshark", "cyberghost",
"vyprvpn", "nordvpn", "purevpn",
"vyprvpn", "nordvpn", "purevpn", "privado",
}, libparams.Default("private internet access"))
if s == "pia" {
s = "private internet access"

View File

@@ -63,9 +63,3 @@ func (r *reader) GetPIAEncryptionPreset() (preset string, err error) {
func (r *reader) GetPIARegions() (regions []string, err error) {
return r.envParams.GetCSVInPossibilities("REGION", constants.PIAGeoChoices())
}
// GetPIAOldRegions obtains the regions for the PIA servers from the
// environment variable REGION.
func (r *reader) GetPIAOldRegions() (regions []string, err error) {
return r.envParams.GetCSVInPossibilities("REGION", constants.PIAOldGeoChoices())
}

View File

@@ -0,0 +1,11 @@
package params
import (
"github.com/qdm12/gluetun/internal/constants"
)
// GetPrivadoHostnames obtains the hostnames for the Privado server from the
// environment variable HOSTNAME.
func (r *reader) GetPrivadoHostnames() (hosts []string, err error) {
return r.envParams.GetCSVInPossibilities("HOSTNAME", constants.PrivadoHostnameChoices())
}

View File

@@ -14,7 +14,19 @@ func (r *reader) GetWindscribeRegions() (regions []string, err error) {
return r.envParams.GetCSVInPossibilities("REGION", constants.WindscribeRegionChoices())
}
// GetMullvadPort obtains the port to reach the Mullvad server on from the
// GetWindscribeCities obtains the cities for the Windscribe servers from the
// environment variable CITY.
func (r *reader) GetWindscribeCities() (cities []string, err error) {
return r.envParams.GetCSVInPossibilities("CITY", constants.WindscribeCityChoices())
}
// GetWindscribeHostnames obtains the hostnames for the Windscribe servers from the
// environment variable HOSTNAME.
func (r *reader) GetWindscribeHostnames() (hostnames []string, err error) {
return r.envParams.GetCSVInPossibilities("HOSTNAME", constants.WindscribeHostnameChoices())
}
// GetWindscribePort obtains the port to reach the Windscribe server on from the
// environment variable PORT.
//nolint:gomnd
func (r *reader) GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error) {

View File

@@ -2,4 +2,5 @@ package provider
const (
aes256cbc = "aes-256-cbc"
sha256 = "sha256"
)

View File

@@ -68,7 +68,7 @@ func (c *cyberghost) BuildConf(connection models.OpenVPNConnection, verbosity,
cipher = aes256cbc
}
if len(auth) == 0 {
auth = "SHA256"
auth = sha256
}
lines = []string{
"client",

View File

@@ -1,156 +0,0 @@
package provider
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"math/rand"
"net"
"net/http"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/firewall"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/golibs/files"
"github.com/qdm12/golibs/logging"
)
type piaV3 struct {
servers []models.PIAOldServer
randSource rand.Source
}
func newPrivateInternetAccessV3(servers []models.PIAOldServer, timeNow timeNowFunc) *piaV3 {
return &piaV3{
servers: servers,
randSource: rand.NewSource(timeNow().UnixNano()),
}
}
func (p *piaV3) GetOpenVPNConnection(selection models.ServerSelection) (
connection models.OpenVPNConnection, err error) {
var port uint16
switch selection.Protocol {
case constants.TCP:
switch selection.EncryptionPreset {
case constants.PIAEncryptionPresetNormal:
port = 502
case constants.PIAEncryptionPresetStrong:
port = 501
}
case constants.UDP:
switch selection.EncryptionPreset {
case constants.PIAEncryptionPresetNormal:
port = 1198
case constants.PIAEncryptionPresetStrong:
port = 1197
}
}
if port == 0 {
return connection, fmt.Errorf(
"combination of protocol %q and encryption %q does not yield any port number",
selection.Protocol, selection.EncryptionPreset)
}
if selection.TargetIP != nil {
return models.OpenVPNConnection{IP: selection.TargetIP, Port: port, Protocol: selection.Protocol}, nil
}
servers := filterPIAOldServers(p.servers, selection.Regions)
if len(servers) == 0 {
return connection, fmt.Errorf("no server found for regions %s", commaJoin(selection.Regions))
}
var connections []models.OpenVPNConnection
for _, server := range servers {
for _, IP := range server.IPs {
connections = append(connections, models.OpenVPNConnection{IP: IP, Port: port, Protocol: selection.Protocol})
}
}
return pickRandomConnection(connections, p.randSource), nil
}
func (p *piaV3) BuildConf(connection models.OpenVPNConnection, verbosity, uid, gid int,
root bool, cipher, auth string, extras models.ExtraConfigOptions) (lines []string) {
return buildPIAConf(connection, verbosity, root, cipher, auth, extras)
}
func (p *piaV3) PortForward(ctx context.Context, client *http.Client,
fileManager files.FileManager, pfLogger logging.Logger, gateway net.IP, fw firewall.Configurator,
syncState func(port uint16) (pfFilepath models.Filepath)) {
const uuidLength = 32
b := make([]byte, uuidLength)
n, err := rand.New(p.randSource).Read(b) //nolint:gosec
if err != nil {
pfLogger.Error(err)
return
} else if n != uuidLength {
pfLogger.Error("only read %d bytes instead of %d", n, uuidLength)
return
}
clientID := hex.EncodeToString(b)
url := fmt.Sprintf("%s/?client_id=%s", constants.PIAPortForwardURL, clientID)
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
pfLogger.Error(err)
return
}
response, err := client.Do(request)
if err != nil {
pfLogger.Error(err)
return
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
pfLogger.Error("%s for %s; does your PIA server support port forwarding?", response.Status, url)
return
}
b, err = ioutil.ReadAll(response.Body)
if err != nil {
pfLogger.Error(err)
return
} else if len(b) == 0 {
pfLogger.Error("port forwarding is already activated on this connection, has expired, or you are not connected to a PIA region that supports port forwarding") //nolint:lll
return
}
body := struct {
Port uint16 `json:"port"`
}{}
if err := json.Unmarshal(b, &body); err != nil {
pfLogger.Error("port forwarding response: %s", err)
return
}
port := body.Port
filepath := syncState(port)
pfLogger.Info("Writing port to %s", filepath)
if err := fileManager.WriteToFile(
string(filepath), []byte(fmt.Sprintf("%d", port)),
files.Permissions(constants.AllReadWritePermissions),
); err != nil {
pfLogger.Error(err)
}
if err := fw.SetAllowedPort(ctx, port, string(constants.TUN)); err != nil {
pfLogger.Error(err)
}
<-ctx.Done()
if err := fw.RemoveAllowedPort(ctx, port); err != nil {
pfLogger.Error(err)
}
}
func filterPIAOldServers(servers []models.PIAOldServer, regions []string) (filtered []models.PIAOldServer) {
for _, server := range servers {
switch {
case filterByPossibilities(server.Region, regions):
default:
filtered = append(filtered, server)
}
}
return filtered
}

View File

@@ -0,0 +1,123 @@
package provider
import (
"context"
"fmt"
"math/rand"
"net"
"net/http"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/firewall"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/golibs/files"
"github.com/qdm12/golibs/logging"
)
type privado struct {
servers []models.PrivadoServer
randSource rand.Source
}
func newPrivado(servers []models.PrivadoServer, timeNow timeNowFunc) *privado {
return &privado{
servers: servers,
randSource: rand.NewSource(timeNow().UnixNano()),
}
}
func (s *privado) filterServers(hostnames []string) (servers []models.PrivadoServer) {
for _, server := range s.servers {
switch {
case filterByPossibilities(server.Hostname, hostnames):
default:
servers = append(servers, server)
}
}
return servers
}
func (s *privado) GetOpenVPNConnection(selection models.ServerSelection) (
connection models.OpenVPNConnection, err error) {
var port uint16 = 1194
switch selection.Protocol {
case constants.UDP:
default:
return connection, fmt.Errorf("protocol %q is not supported by Privado", selection.Protocol)
}
if selection.TargetIP != nil {
return models.OpenVPNConnection{IP: selection.TargetIP, Port: port, Protocol: selection.Protocol}, nil
}
servers := s.filterServers(selection.Hostnames)
if len(servers) == 0 {
return connection, fmt.Errorf("no server found for cities %s and server numbers %v",
commaJoin(selection.Cities), selection.Numbers)
}
connections := make([]models.OpenVPNConnection, len(servers))
for i := range servers {
connection := models.OpenVPNConnection{
IP: servers[i].IP,
Port: port,
Protocol: selection.Protocol,
Hostname: servers[i].Hostname,
}
connections = append(connections, connection)
}
return pickRandomConnection(connections, s.randSource), nil
}
func (s *privado) BuildConf(connection models.OpenVPNConnection, verbosity, uid, gid int, root bool,
cipher, auth string, extras models.ExtraConfigOptions) (lines []string) {
if len(cipher) == 0 {
cipher = aes256cbc
}
if len(auth) == 0 {
auth = sha256
}
lines = []string{
"client",
"dev tun",
"nobind",
"persist-key",
// Privado specific
"tls-cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-DSS-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA",
fmt.Sprintf("verify-x509-name %s name", connection.Hostname),
// Added constant values
"auth-nocache",
"mute-replay-warnings",
"pull-filter ignore \"auth-token\"", // prevent auth failed loops
"auth-retry nointeract",
"suppress-timestamps",
// Modified variables
fmt.Sprintf("verb %d", verbosity),
fmt.Sprintf("auth-user-pass %s", constants.OpenVPNAuthConf),
fmt.Sprintf("proto %s", connection.Protocol),
fmt.Sprintf("remote %s %d", connection.IP, connection.Port),
fmt.Sprintf("cipher %s", cipher),
fmt.Sprintf("auth %s", auth),
}
if !root {
lines = append(lines, "user nonrootuser")
}
lines = append(lines, []string{
"<ca>",
"-----BEGIN CERTIFICATE-----",
constants.PrivadoCertificate,
"-----END CERTIFICATE-----",
"</ca>",
}...)
return lines
}
func (s *privado) PortForward(ctx context.Context, client *http.Client,
fileManager files.FileManager, pfLogger logging.Logger, gateway net.IP, fw firewall.Configurator,
syncState func(port uint16) (pfFilepath models.Filepath)) {
panic("port forwarding is not supported for privado")
}

View File

@@ -26,8 +26,6 @@ func New(provider models.VPNProvider, allServers models.AllServers, timeNow time
switch provider {
case constants.PrivateInternetAccess:
return newPrivateInternetAccessV4(allServers.Pia.Servers, timeNow)
case constants.PrivateInternetAccessOld:
return newPrivateInternetAccessV3(allServers.PiaOld.Servers, timeNow)
case constants.Mullvad:
return newMullvad(allServers.Mullvad.Servers, timeNow)
case constants.Windscribe:
@@ -42,6 +40,8 @@ func New(provider models.VPNProvider, allServers models.AllServers, timeNow time
return newNordvpn(allServers.Nordvpn.Servers, timeNow)
case constants.Purevpn:
return newPurevpn(allServers.Purevpn.Servers, timeNow)
case constants.Privado:
return newPrivado(allServers.Privado.Servers, timeNow)
default:
return nil // should never occur
}

View File

@@ -27,11 +27,13 @@ func newWindscribe(servers []models.WindscribeServer, timeNow timeNowFunc) *wind
}
}
func (w *windscribe) filterServers(regions []string) (servers []models.WindscribeServer) {
func (w *windscribe) filterServers(regions, cities, hostnames []string) (servers []models.WindscribeServer) {
for _, server := range w.servers {
switch {
case
filterByPossibilities(server.Region, regions):
filterByPossibilities(server.Region, regions),
filterByPossibilities(server.City, cities),
filterByPossibilities(server.Hostname, hostnames):
default:
servers = append(servers, server)
}
@@ -57,16 +59,14 @@ func (w *windscribe) GetOpenVPNConnection(selection models.ServerSelection) (con
return models.OpenVPNConnection{IP: selection.TargetIP, Port: port, Protocol: selection.Protocol}, nil
}
servers := w.filterServers(selection.Regions)
servers := w.filterServers(selection.Regions, selection.Cities, selection.Hostnames)
if len(servers) == 0 {
return connection, fmt.Errorf("no server found for region %s", commaJoin(selection.Regions))
}
var connections []models.OpenVPNConnection
connections := make([]models.OpenVPNConnection, len(servers))
for _, server := range servers {
for _, IP := range server.IPs {
connections = append(connections, models.OpenVPNConnection{IP: IP, Port: port, Protocol: selection.Protocol})
}
connections = append(connections, models.OpenVPNConnection{IP: server.IP, Port: port, Protocol: selection.Protocol})
}
return pickRandomConnection(connections, w.randSource), nil

View File

@@ -0,0 +1,70 @@
package server
import (
"fmt"
"net/http"
"github.com/qdm12/gluetun/internal/dns"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/openvpn"
"github.com/qdm12/gluetun/internal/updater"
"github.com/qdm12/golibs/logging"
)
func newHandler(logger logging.Logger, logging bool,
buildInfo models.BuildInformation,
openvpnLooper openvpn.Looper,
unboundLooper dns.Looper,
updaterLooper updater.Looper,
) http.Handler {
return &handler{
logger: logger,
logging: logging,
buildInfo: buildInfo,
openvpnLooper: openvpnLooper,
unboundLooper: unboundLooper,
updaterLooper: updaterLooper,
}
}
type handler struct {
logger logging.Logger
logging bool
buildInfo models.BuildInformation
openvpnLooper openvpn.Looper
unboundLooper dns.Looper
updaterLooper updater.Looper
}
func (h *handler) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request) {
if h.logging {
h.logger.Info("HTTP %s %s", request.Method, request.RequestURI)
}
switch request.Method {
case http.MethodGet:
switch request.RequestURI {
case "/version":
h.getVersion(responseWriter)
responseWriter.WriteHeader(http.StatusOK)
case "/openvpn/actions/restart":
h.openvpnLooper.Restart()
responseWriter.WriteHeader(http.StatusOK)
case "/unbound/actions/restart":
h.unboundLooper.Restart()
responseWriter.WriteHeader(http.StatusOK)
case "/openvpn/portforwarded":
h.getPortForwarded(responseWriter)
case "/openvpn/settings":
h.getOpenvpnSettings(responseWriter)
case "/updater/restart":
h.updaterLooper.Restart()
responseWriter.WriteHeader(http.StatusOK)
default:
errString := fmt.Sprintf("Nothing here for %s %s", request.Method, request.RequestURI)
http.Error(responseWriter, errString, http.StatusBadRequest)
}
default:
errString := fmt.Sprintf("Nothing here for %s %s", request.Method, request.RequestURI)
http.Error(responseWriter, errString, http.StatusBadRequest)
}
}

View File

@@ -5,32 +5,32 @@ import (
"net/http"
)
func (s *server) handleGetPortForwarded(w http.ResponseWriter) {
port := s.openvpnLooper.GetPortForwarded()
func (h *handler) getPortForwarded(w http.ResponseWriter) {
port := h.openvpnLooper.GetPortForwarded()
data, err := json.Marshal(struct {
Port uint16 `json:"port"`
}{port})
if err != nil {
s.logger.Warn(err)
h.logger.Warn(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if _, err := w.Write(data); err != nil {
s.logger.Warn(err)
h.logger.Warn(err)
w.WriteHeader(http.StatusInternalServerError)
}
}
func (s *server) handleGetOpenvpnSettings(w http.ResponseWriter) {
settings := s.openvpnLooper.GetSettings()
func (h *handler) getOpenvpnSettings(w http.ResponseWriter) {
settings := h.openvpnLooper.GetSettings()
data, err := json.Marshal(settings)
if err != nil {
s.logger.Warn(err)
h.logger.Warn(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if _, err := w.Write(data); err != nil {
s.logger.Warn(err)
h.logger.Warn(err)
w.WriteHeader(http.StatusInternalServerError)
}
}

View File

@@ -2,7 +2,6 @@ package server
import (
"context"
"fmt"
"net/http"
"sync"
"time"
@@ -19,30 +18,24 @@ type Server interface {
}
type server struct {
address string
logging bool
logger logging.Logger
buildInfo models.BuildInformation
openvpnLooper openvpn.Looper
unboundLooper dns.Looper
updaterLooper updater.Looper
address string
logger logging.Logger
handler http.Handler
}
func New(address string, logging bool, logger logging.Logger, buildInfo models.BuildInformation,
openvpnLooper openvpn.Looper, unboundLooper dns.Looper, updaterLooper updater.Looper) Server {
serverLogger := logger.WithPrefix("http server: ")
handler := newHandler(serverLogger, logging, buildInfo, openvpnLooper, unboundLooper, updaterLooper)
return &server{
address: address,
logging: logging,
logger: logger.WithPrefix("http server: "),
buildInfo: buildInfo,
openvpnLooper: openvpnLooper,
unboundLooper: unboundLooper,
updaterLooper: updaterLooper,
address: address,
logger: serverLogger,
handler: handler,
}
}
func (s *server) Run(ctx context.Context, wg *sync.WaitGroup) {
server := http.Server{Addr: s.address, Handler: s.makeHandler()}
server := http.Server{Addr: s.address, Handler: s.handler}
go func() {
defer wg.Done()
<-ctx.Done()
@@ -61,42 +54,3 @@ func (s *server) Run(ctx context.Context, wg *sync.WaitGroup) {
s.logger.Error(err)
}
}
func (s *server) makeHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
s.logger.Info("HTTP %s %s", r.Method, r.RequestURI)
switch r.Method {
case http.MethodGet:
switch r.RequestURI {
case "/version":
s.handleGetVersion(w)
w.WriteHeader(http.StatusOK)
case "/openvpn/actions/restart":
s.openvpnLooper.Restart()
w.WriteHeader(http.StatusOK)
case "/unbound/actions/restart":
s.unboundLooper.Restart()
w.WriteHeader(http.StatusOK)
case "/openvpn/portforwarded":
s.handleGetPortForwarded(w)
case "/openvpn/settings":
s.handleGetOpenvpnSettings(w)
case "/updater/restart":
s.updaterLooper.Restart()
w.WriteHeader(http.StatusOK)
default:
routeDoesNotExist(s.logger, w, r)
}
default:
routeDoesNotExist(s.logger, w, r)
}
}
}
func routeDoesNotExist(logger logging.Logger, w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadRequest)
_, err := w.Write([]byte(fmt.Sprintf("Nothing here for %s %s", r.Method, r.RequestURI)))
if err != nil {
logger.Error(err)
}
}

View File

@@ -5,15 +5,15 @@ import (
"net/http"
)
func (s *server) handleGetVersion(w http.ResponseWriter) {
data, err := json.Marshal(s.buildInfo)
func (h *handler) getVersion(w http.ResponseWriter) {
data, err := json.Marshal(h.buildInfo)
if err != nil {
s.logger.Warn(err)
h.logger.Warn(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if _, err := w.Write(data); err != nil {
s.logger.Warn(err)
h.logger.Warn(err)
w.WriteHeader(http.StatusInternalServerError)
}
}

View File

@@ -54,8 +54,6 @@ 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:
@@ -70,6 +68,8 @@ func GetOpenVPNSettings(paramsReader params.Reader, vpnProvider models.VPNProvid
settings.Provider, err = GetNordvpnSettings(paramsReader)
case constants.Purevpn:
settings.Provider, err = GetPurevpnSettings(paramsReader)
case constants.Privado:
settings.Provider, err = GetPrivadoSettings(paramsReader)
default:
err = fmt.Errorf("VPN service provider %q is not valid", vpnProvider)
}

View File

@@ -20,7 +20,7 @@ func Test_OpenVPN_JSON(t *testing.T) {
data, err := json.Marshal(in)
require.NoError(t, err)
//nolint:lll
assert.Equal(t, `{"user":"","verbosity":0,"runAsRoot":true,"cipher":"","auth":"","provider":{"name":"name","serverSelection":{"networkProtocol":"","regions":null,"group":"","countries":null,"cities":null,"isps":null,"owned":false,"customPort":0,"numbers":null,"encryptionPreset":""},"extraConfig":{"encryptionPreset":"","openvpnIPv6":false},"portForwarding":{"enabled":false,"filepath":""}}}`, string(data))
assert.Equal(t, `{"user":"","verbosity":0,"runAsRoot":true,"cipher":"","auth":"","provider":{"name":"name","serverSelection":{"networkProtocol":"","regions":null,"group":"","countries":null,"cities":null,"hostnames":null,"isps":null,"owned":false,"customPort":0,"numbers":null,"encryptionPreset":""},"extraConfig":{"encryptionPreset":"","openvpnIPv6":false},"portForwarding":{"enabled":false,"filepath":""}}}`, string(data))
var out OpenVPN
err = json.Unmarshal(data, &out)
require.NoError(t, err)

View File

@@ -10,17 +10,7 @@ import (
// GetPIASettings obtains PIA settings from environment variables using the params package.
func GetPIASettings(paramsReader params.Reader) (settings models.ProviderSettings, err error) {
return getPIASettings(paramsReader, constants.PrivateInternetAccess)
}
// 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) {
return getPIASettings(paramsReader, constants.PrivateInternetAccessOld)
}
func getPIASettings(paramsReader params.Reader, name models.VPNProvider) (settings models.ProviderSettings, err error) {
settings.Name = name
settings.Name = constants.PrivateInternetAccess
settings.ServerSelection.Protocol, err = paramsReader.GetNetworkProtocol()
if err != nil {
return settings, err
@@ -118,6 +108,14 @@ func GetWindscribeSettings(paramsReader params.Reader) (settings models.Provider
if err != nil {
return settings, err
}
settings.ServerSelection.Cities, err = paramsReader.GetWindscribeCities()
if err != nil {
return settings, err
}
settings.ServerSelection.Hostnames, err = paramsReader.GetWindscribeHostnames()
if err != nil {
return settings, err
}
settings.ServerSelection.CustomPort, err = paramsReader.GetWindscribePort(settings.ServerSelection.Protocol)
if err != nil {
return settings, err
@@ -234,3 +232,21 @@ func GetPurevpnSettings(paramsReader params.Reader) (settings models.ProviderSet
}
return settings, nil
}
// GetPrivadoSettings obtains Privado settings from environment variables using the params package.
func GetPrivadoSettings(paramsReader params.Reader) (settings models.ProviderSettings, err error) {
settings.Name = constants.Privado
settings.ServerSelection.Protocol, err = paramsReader.GetNetworkProtocol()
if err != nil {
return settings, err
}
settings.ServerSelection.TargetIP, err = paramsReader.GetTargetIP()
if err != nil {
return settings, err
}
settings.ServerSelection.Hostnames, err = paramsReader.GetPrivadoHostnames()
if err != nil {
return settings, err
}
return settings, nil
}

View File

@@ -47,12 +47,19 @@ func (s *storage) mergeServers(hardcoded, persistent models.AllServers) (merged
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.Privado = hardcoded.Privado
versionDiff := int(persistent.Privado.Version) - int(hardcoded.Privado.Version)
switch {
case versionDiff > 0:
s.logger.Info("Using Privado servers from file (%d version(s) more recent)", versionDiff)
merged.Privado = persistent.Privado
case persistent.Privado.Timestamp > hardcoded.Privado.Timestamp:
s.logger.Info("Using Privado servers from file (%s more recent)",
getUnixTimeDifference(persistent.Privado.Timestamp, hardcoded.Privado.Timestamp))
merged.Privado = persistent.Privado
}
merged.Purevpn = hardcoded.Purevpn
if persistent.Purevpn.Timestamp > hardcoded.Purevpn.Timestamp {
s.logger.Info("Using Purevpn servers from file (%s more recent)",
@@ -73,9 +80,14 @@ func (s *storage) mergeServers(hardcoded, persistent models.AllServers) (merged
}
merged.Windscribe = hardcoded.Windscribe
if persistent.Windscribe.Timestamp > hardcoded.Windscribe.Timestamp {
s.logger.Info("Using Windscribe servers from file (%s more recent)",
getUnixTimeDifference(persistent.Windscribe.Timestamp, hardcoded.Windscribe.Timestamp))
merged.Windscribe = persistent.Windscribe
if hardcoded.Windscribe.Version == 2 && persistent.Windscribe.Version == 1 {
s.logger.Info("Windscribe servers from file discarded because they are one version behind")
merged.Windscribe = hardcoded.Windscribe
} else {
s.logger.Info("Using Windscribe servers from file (%s more recent)",
getUnixTimeDifference(persistent.Windscribe.Timestamp, hardcoded.Windscribe.Timestamp))
merged.Windscribe = persistent.Windscribe
}
}
return merged
}

View File

@@ -18,7 +18,7 @@ func countServers(allServers models.AllServers) int {
len(allServers.Mullvad.Servers) +
len(allServers.Nordvpn.Servers) +
len(allServers.Pia.Servers) +
len(allServers.PiaOld.Servers) +
len(allServers.Privado.Servers) +
len(allServers.Purevpn.Servers) +
len(allServers.Surfshark.Servers) +
len(allServers.Vyprvpn.Servers) +

View File

@@ -101,6 +101,20 @@ func getCyberghostGroups() map[string]string {
}
}
func mergeCountryCodes(base, extend map[string]string) (merged map[string]string) {
merged = make(map[string]string, len(base))
for countryCode, region := range base {
merged[countryCode] = region
}
for countryCode := range base {
delete(extend, countryCode)
}
for countryCode, region := range extend {
merged[countryCode] = region
}
return merged
}
func getCyberghostSubdomainToRegion() map[string]string { //nolint:dupl
return map[string]string{
"af": "Afghanistan",

View File

@@ -5,7 +5,7 @@ type Options struct {
Mullvad bool
Nordvpn bool
PIA bool
PIAold bool
Privado bool
Purevpn bool
Surfshark bool
Vyprvpn bool
@@ -21,7 +21,6 @@ func NewOptions(dnsAddress string) Options {
Mullvad: true,
Nordvpn: true,
PIA: true,
PIAold: true,
Purevpn: true,
Surfshark: true,
Vyprvpn: true,

View File

@@ -1,101 +0,0 @@
package updater
import (
"context"
"fmt"
"net"
"sort"
"strings"
"sync"
"github.com/qdm12/gluetun/internal/models"
)
func (u *updater) updatePIAOld(ctx context.Context) (err error) {
const zipURL = "https://www.privateinternetaccess.com/openvpn/openvpn.zip"
contents, err := fetchAndExtractFiles(ctx, u.client, zipURL)
if err != nil {
return err
}
const maxGoroutines = 10
guard := make(chan struct{}, maxGoroutines)
errors := make(chan error)
serversCh := make(chan models.PIAOldServer)
servers := make([]models.PIAOldServer, 0, len(contents))
ctx, cancel := context.WithCancel(ctx)
wg := &sync.WaitGroup{}
defer func() {
cancel()
wg.Wait()
defer close(guard)
defer close(errors)
defer close(serversCh)
}()
for fileName, content := range contents {
remoteLines := extractRemoteLinesFromOpenvpn(content)
if len(remoteLines) == 0 {
return fmt.Errorf("cannot find any remote lines in %s", fileName)
}
hosts := extractHostnamesFromRemoteLines(remoteLines)
if len(hosts) == 0 {
return fmt.Errorf("cannot find any hosts in %s", fileName)
}
region := strings.TrimSuffix(fileName, ".ovpn")
wg.Add(1)
go resolvePIAv3Hostname(ctx, wg, region, hosts, u.lookupIP, errors, serversCh, guard)
}
for range contents {
select {
case err := <-errors:
return err
case server := <-serversCh:
servers = append(servers, server)
}
}
sort.Slice(servers, func(i, j int) bool {
return servers[i].Region < servers[j].Region
})
if u.options.Stdout {
u.println(stringifyPIAOldServers(servers))
}
u.servers.PiaOld.Timestamp = u.timeNow().Unix()
u.servers.PiaOld.Servers = servers
return nil
}
func resolvePIAv3Hostname(ctx context.Context, wg *sync.WaitGroup,
region string, hosts []string, lookupIP lookupIPFunc,
errors chan<- error, serversCh chan<- models.PIAOldServer, guard chan struct{}) {
guard <- struct{}{}
defer func() {
<-guard
wg.Done()
}()
var IPs []net.IP //nolint:prealloc
// usually one single host in this case
// so no need to run in goroutines the for loop below
for _, host := range hosts {
const repetition = 5
newIPs, err := resolveRepeat(ctx, lookupIP, host, repetition)
if err != nil {
errors <- err
return
}
IPs = append(IPs, newIPs...)
}
serversCh <- models.PIAOldServer{
Region: region,
IPs: uniqueSortedIPs(IPs),
}
}
func stringifyPIAOldServers(servers []models.PIAOldServer) (s string) {
s = "func PIAOldServers() []models.PIAOldServer {\n"
s += " return []models.PIAOldServer{\n"
for _, server := range servers {
s += " " + server.String() + ",\n"
}
s += " }\n"
s += "}"
return s
}

View File

@@ -0,0 +1,94 @@
package updater
import (
"context"
"fmt"
"net"
"sort"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/golibs/network"
)
func (u *updater) updatePrivado(ctx context.Context) (err error) {
servers, warnings, err := findPrivadoServersFromZip(ctx, u.client, u.lookupIP)
if u.options.CLI {
for _, warning := range warnings {
u.logger.Warn("Privado: %s", warning)
}
}
if err != nil {
return fmt.Errorf("cannot update Privado servers: %w", err)
}
if u.options.Stdout {
u.println(stringifyPrivadoServers(servers))
}
u.servers.Privado.Timestamp = u.timeNow().Unix()
u.servers.Privado.Servers = servers
return nil
}
func findPrivadoServersFromZip(ctx context.Context, client network.Client, lookupIP lookupIPFunc) (
servers []models.PrivadoServer, warnings []string, err error) {
const zipURL = "https://privado.io/apps/ovpn_configs.zip"
contents, err := fetchAndExtractFiles(ctx, client, zipURL)
if err != nil {
return nil, nil, err
}
for fileName, content := range contents {
if err := ctx.Err(); err != nil {
return nil, warnings, err
}
remoteLines := extractRemoteLinesFromOpenvpn(content)
if len(remoteLines) == 0 {
return nil, warnings, fmt.Errorf("cannot find any remote lines in %s", fileName)
}
hostnames := extractHostnamesFromRemoteLines(remoteLines)
if len(hostnames) == 0 {
return nil, warnings, fmt.Errorf("cannot find any hosts in %s", fileName)
} else if len(hostnames) > 1 {
warning := fmt.Sprintf("more than one host in %q, only taking first one %q into account", fileName, hostnames[0])
warnings = append(warnings, warning)
}
hostname := hostnames[0]
if net.ParseIP(hostname) != nil {
warning := fmt.Sprintf("ignoring IP address host %q in %s", hostname, fileName)
warnings = append(warnings, warning)
continue
}
const repetition = 1
IPs, err := resolveRepeat(ctx, lookupIP, hostname, repetition)
switch {
case err != nil:
return nil, warnings, err
case len(IPs) == 0:
warning := fmt.Sprintf("no IP address found for host %q", hostname)
warnings = append(warnings, warning)
continue
case len(IPs) > 1:
warning := fmt.Sprintf("more than one IP address found for host %q", hostname)
warnings = append(warnings, warning)
}
server := models.PrivadoServer{
Hostname: hostname,
IP: IPs[0],
}
servers = append(servers, server)
}
sort.Slice(servers, func(i, j int) bool {
return servers[i].Hostname < servers[j].Hostname
})
return servers, warnings, nil
}
func stringifyPrivadoServers(servers []models.PrivadoServer) (s string) {
s = "func PrivadoServers() []models.PrivadoServer {\n"
s += " return []models.PrivadoServer{\n"
for _, server := range servers {
s += " " + server.String() + ",\n"
}
s += " }\n"
s += "}"
return s
}

View File

@@ -90,14 +90,14 @@ func (u *updater) UpdateServers(ctx context.Context) (allServers models.AllServe
}
}
if u.options.PIAold {
u.logger.Info("updating Private Internet Access old (v3) servers...")
if err := u.updatePIAOld(ctx); err != nil {
if ctxErr := ctx.Err(); ctxErr != nil {
return allServers, ctxErr
}
if u.options.Privado {
u.logger.Info("updating Privado servers...")
if err := u.updatePrivado(ctx); err != nil {
u.logger.Error(err)
}
if ctx.Err() != nil {
return allServers, ctx.Err()
}
}
if u.options.Purevpn {

View File

@@ -2,14 +2,19 @@ package updater
import (
"context"
"encoding/json"
"fmt"
"net"
"net/http"
"sort"
"time"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/golibs/network"
)
func (u *updater) updateWindscribe(ctx context.Context) (err error) {
servers, err := findWindscribeServers(ctx, u.lookupIP)
servers, err := findWindscribeServers(ctx, u.client)
if err != nil {
return fmt.Errorf("cannot update Windscribe servers: %w", err)
}
@@ -21,46 +26,53 @@ func (u *updater) updateWindscribe(ctx context.Context) (err error) {
return nil
}
func findWindscribeServers(ctx context.Context, lookupIP lookupIPFunc) (servers []models.WindscribeServer, err error) {
allCountryCodes := getCountryCodes()
windscribeCountryCodes := getWindscribeSubdomainToRegion()
possibleCountryCodes := mergeCountryCodes(windscribeCountryCodes, allCountryCodes)
const domain = "windscribe.com"
for countryCode, region := range possibleCountryCodes {
if err := ctx.Err(); err != nil {
return nil, err
func findWindscribeServers(ctx context.Context, client network.Client) (servers []models.WindscribeServer, err error) {
const baseURL = "https://assets.windscribe.com/serverlist/mob-v2/1/"
cacheBreaker := time.Now().Unix()
url := fmt.Sprintf("%s%d", baseURL, cacheBreaker)
content, status, err := client.Get(ctx, url)
if err != nil {
return nil, err
} else if status != http.StatusOK {
return nil, fmt.Errorf(http.StatusText(status))
}
var jsonData struct {
Data []struct {
Region string `json:"name"`
Groups []struct {
City string `json:"city"`
Nodes []struct {
Hostname string `json:"hostname"`
OpenvpnIP net.IP `json:"ip2"`
} `json:"nodes"`
} `json:"groups"`
} `json:"data"`
}
if err := json.Unmarshal(content, &jsonData); err != nil {
return nil, err
}
for _, regionBlock := range jsonData.Data {
region := regionBlock.Region
for _, group := range regionBlock.Groups {
city := group.City
for _, node := range group.Nodes {
server := models.WindscribeServer{
Region: region,
City: city,
Hostname: node.Hostname,
IP: node.OpenvpnIP,
}
servers = append(servers, server)
}
}
host := countryCode + "." + domain
const repetitions = 5
ips, err := resolveRepeat(ctx, lookupIP, host, repetitions)
if err != nil || len(ips) == 0 {
continue
}
servers = append(servers, models.WindscribeServer{
Region: region,
IPs: ips,
})
}
sort.Slice(servers, func(i, j int) bool {
return servers[i].Region < servers[j].Region
return servers[i].Region+servers[i].City+servers[i].Hostname <
servers[j].Region+servers[j].City+servers[j].Hostname
})
return servers, nil
}
func mergeCountryCodes(base, extend map[string]string) (merged map[string]string) {
merged = make(map[string]string, len(base))
for countryCode, region := range base {
merged[countryCode] = region
}
for countryCode := range base {
delete(extend, countryCode)
}
for countryCode, region := range extend {
merged[countryCode] = region
}
return merged
}
func stringifyWindscribeServers(servers []models.WindscribeServer) (s string) {
s = "func WindscribeServers() []models.WindscribeServer {\n"
s += " return []models.WindscribeServer{\n"
@@ -71,77 +83,3 @@ func stringifyWindscribeServers(servers []models.WindscribeServer) (s string) {
s += "}"
return s
}
func getWindscribeSubdomainToRegion() map[string]string {
return map[string]string{
"al": "Albania",
"ar": "Argentina",
"au": "Australia",
"at": "Austria",
"az": "Azerbaijan",
"be": "Belgium",
"ba": "Bosnia",
"br": "Brazil",
"bg": "Bulgaria",
"ca": "Canada East",
"ca-west": "Canada West",
"co": "Colombia",
"hr": "Croatia",
"cy": "Cyprus",
"cz": "Czech republic",
"dk": "Denmark",
"ee": "Estonia",
"aq": "Fake antarctica",
"fi": "Finland",
"fr": "France",
"ge": "Georgia",
"de": "Germany",
"gr": "Greece",
"hk": "Hong kong",
"hu": "Hungary",
"is": "Iceland",
"in": "India",
"id": "Indonesia",
"ie": "Ireland",
"il": "Israel",
"it": "Italy",
"jp": "Japan",
"lv": "Latvia",
"lt": "Lithuania",
"mk": "Macedonia",
"my": "Malaysia",
"mx": "Mexico",
"md": "Moldova",
"nl": "Netherlands",
"nz": "New zealand",
"no": "Norway",
"ph": "Philippines",
"pl": "Poland",
"pt": "Portugal",
"ro": "Romania",
"ru": "Russia",
"rs": "Serbia",
"sg": "Singapore",
"sk": "Slovakia",
"si": "Slovenia",
"za": "South Africa",
"kr": "South Korea",
"es": "Spain",
"se": "Sweden",
"ch": "Switzerland",
"th": "Thailand",
"tn": "Tunisia",
"tr": "Turkey",
"ua": "Ukraine",
"ae": "United Arab Emirates",
"uk": "United Kingdom",
"us-central": "US Central",
"us-east": "US East",
"us-west": "US West",
"vn": "Vietnam",
"wf-ca": "Windflix CA",
"wf-jp": "Windflix JP",
"wf-uk": "Windflix UK",
"wf-us": "Windflix US",
}
}