Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f48392064e | ||
|
|
994bdd0ca7 | ||
|
|
40ed070f21 | ||
|
|
f1e4b9937b | ||
|
|
0423388b52 | ||
|
|
096a9c5fc0 | ||
|
|
7518f74729 | ||
|
|
854401a150 | ||
|
|
a7a7efe9c3 | ||
|
|
31883f9adb |
46
.github/ISSUE_TEMPLATE/bug.md
vendored
46
.github/ISSUE_TEMPLATE/bug.md
vendored
@@ -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
|
**What VPN provider are you using**:
|
||||||
- [x] No
|
|
||||||
|
|
||||||
2. What VPN service provider are you using?
|
**What are you using to run your container?**: Docker Compose
|
||||||
|
|
||||||
- [x] PIA
|
**What is the version of the program** (See the line at the top of your logs)
|
||||||
- [ ] Mullvad
|
|
||||||
- [ ] Windscribe
|
|
||||||
- [ ] Surfshark
|
|
||||||
- [ ] Cyberghost
|
|
||||||
|
|
||||||
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
|
...*careful to remove i.e. token information with PIA port forwarding*
|
||||||
- [x] Docker Compose
|
|
||||||
- [ ] Kubernetes
|
|
||||||
- [ ] Docker stack
|
|
||||||
- [ ] Docker swarm
|
|
||||||
- [ ] Podman
|
|
||||||
- [ ] Other:
|
|
||||||
|
|
||||||
5. Extra information
|
|
||||||
|
|
||||||
Logs:
|
|
||||||
|
|
||||||
```log
|
```log
|
||||||
|
|
||||||
```
|
PASTE YOUR LOGS
|
||||||
|
IN THERE
|
||||||
Configuration file:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Host OS:
|
|
||||||
|
|||||||
11
.github/ISSUE_TEMPLATE/feature_request.md
vendored
11
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,14 +1,17 @@
|
|||||||
---
|
---
|
||||||
name: Feature request
|
name: Feature request
|
||||||
about: Suggest a feature to add to this project
|
about: Suggest a feature to add to this project
|
||||||
title: 'Feature request: ...'
|
title: 'Feature request: FILL THIS TEXT!'
|
||||||
labels: ":bulb: feature request"
|
labels: ":bulb: feature request"
|
||||||
assignees: qdm12
|
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
|
||||||
|
|||||||
56
.github/ISSUE_TEMPLATE/help.md
vendored
56
.github/ISSUE_TEMPLATE/help.md
vendored
@@ -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
|
**What VPN provider are you using**:
|
||||||
- [x] No
|
|
||||||
|
|
||||||
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
|
Running version latest built on 2020-03-13T01:30:06Z (commit d0f678c)
|
||||||
- [ ] Windscribe
|
```
|
||||||
- [ ] Surfshark
|
|
||||||
- [ ] Cyberghost
|
|
||||||
|
|
||||||
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?
|
...*careful to remove i.e. token information with PIA port forwarding*
|
||||||
|
|
||||||
- [ ] Docker run
|
|
||||||
- [x] Docker Compose
|
|
||||||
- [ ] Kubernetes
|
|
||||||
- [ ] Docker stack
|
|
||||||
- [ ] Docker swarm
|
|
||||||
- [ ] Podman
|
|
||||||
- [ ] Other:
|
|
||||||
|
|
||||||
5. Extra information
|
|
||||||
|
|
||||||
Logs:
|
|
||||||
|
|
||||||
```log
|
```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
|
```yml
|
||||||
|
your .yml
|
||||||
|
content
|
||||||
|
in here
|
||||||
```
|
```
|
||||||
|
|
||||||
Host OS:
|
or
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# your docker
|
||||||
|
# run command
|
||||||
|
# in here
|
||||||
|
```
|
||||||
|
|||||||
96
.github/labels.yml
vendored
96
.github/labels.yml
vendored
@@ -1,51 +1,67 @@
|
|||||||
- name: ":robot: bot"
|
- name: "Bug :bug:"
|
||||||
color: "69cde9"
|
|
||||||
description: ""
|
|
||||||
- name: ":bug: bug"
|
|
||||||
color: "b60205"
|
color: "b60205"
|
||||||
description: ""
|
description: ""
|
||||||
- name: ":game_die: dependencies"
|
- name: "Feature request :bulb:"
|
||||||
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"
|
|
||||||
color: "0e8a16"
|
color: "0e8a16"
|
||||||
description: ""
|
description: ""
|
||||||
- name: ":mega: feedback"
|
- name: "Help wanted :pray:"
|
||||||
color: "03a9f4"
|
|
||||||
description: ""
|
|
||||||
- name: ":rocket: future maybe"
|
|
||||||
color: "fef2c0"
|
|
||||||
description: ""
|
|
||||||
- name: ":hatching_chick: good first issue"
|
|
||||||
color: "7057ff"
|
|
||||||
description: ""
|
|
||||||
- name: ":pray: help wanted"
|
|
||||||
color: "4caf50"
|
color: "4caf50"
|
||||||
description: ""
|
description: ""
|
||||||
- name: ":hand: hold"
|
- name: "Documentation :memo:"
|
||||||
color: "24292f"
|
color: "c5def5"
|
||||||
description: ""
|
description: ""
|
||||||
- name: ":no_entry_sign: invalid"
|
- name: "Needs more info :thinking:"
|
||||||
color: "e6e6e6"
|
|
||||||
description: ""
|
|
||||||
- name: ":interrobang: maybe bug"
|
|
||||||
color: "ff5722"
|
|
||||||
description: ""
|
|
||||||
- name: ":thinking: needs more info"
|
|
||||||
color: "795548"
|
color: "795548"
|
||||||
description: ""
|
description: ""
|
||||||
- name: ":question: question"
|
|
||||||
color: "3f51b5"
|
# VPN providers
|
||||||
|
- name: ":cloud: Cyberghost"
|
||||||
|
color: "cfe8d4"
|
||||||
description: ""
|
description: ""
|
||||||
- name: ":coffin: wontfix"
|
- name: ":cloud: Mullvad"
|
||||||
color: "ffffff"
|
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: ""
|
description: ""
|
||||||
|
|||||||
@@ -58,7 +58,10 @@ ENV VPNSP=pia \
|
|||||||
PORT_FORWARDING_STATUS_FILE="/tmp/gluetun/forwarded_port" \
|
PORT_FORWARDING_STATUS_FILE="/tmp/gluetun/forwarded_port" \
|
||||||
# Mullvad and PureVPN only
|
# Mullvad and PureVPN only
|
||||||
COUNTRY= \
|
COUNTRY= \
|
||||||
|
# Mullvad, PureVPN, Windscribe only
|
||||||
CITY= \
|
CITY= \
|
||||||
|
# Windscribe only
|
||||||
|
HOSTNAME= \
|
||||||
# Mullvad only
|
# Mullvad only
|
||||||
ISP= \
|
ISP= \
|
||||||
OWNED=no \
|
OWNED=no \
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -1,7 +1,7 @@
|
|||||||
# Gluetun VPN client
|
# Gluetun VPN client
|
||||||
|
|
||||||
*Lightweight swiss-knife-like VPN client to tunnel to Private Internet Access,
|
*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*
|
**ANNOUNCEMENT**: *Github Wiki reworked*
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ Mullvad, Windscribe, Surfshark Cyberghost, VyprVPN, NordVPN and PureVPN VPN serv
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Based on Alpine 3.12 for a small Docker image of 52MB
|
- 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
|
- Supports Openvpn only for now
|
||||||
- DNS over TLS baked in with service provider(s) of your choice
|
- 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
|
- 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 |
|
| 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 |
|
| `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 |
|
| `PROTOCOL` | `udp` | `udp` or `tcp` | Network protocol to use |
|
||||||
| `OPENVPN_VERBOSITY` | `1` | `0` to `6` | Openvpn verbosity level |
|
| `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`
|
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 |
|
| Variable | Default | Choices | Description |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| 🏁 `USER` | | | Your username |
|
| 🏁 `USER` | | | Your username |
|
||||||
| 🏁 `PASSWORD` | | | Your password |
|
| 🏁 `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 |
|
| `PORT` | | One from the [this list of ports](https://windscribe.com/getconfig/openvpn) | Custom VPN port to use |
|
||||||
|
|
||||||
- Surfshark
|
- 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 |
|
| `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 |
|
| `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
|
### DNS over TLS
|
||||||
|
|
||||||
None of the following values are required.
|
None of the following values are required.
|
||||||
|
|||||||
@@ -38,13 +38,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gochecknoglobals
|
//nolint:gochecknoglobals
|
||||||
var buildInfo = models.BuildInformation{
|
var (
|
||||||
Version: "unknown",
|
buildInfo models.BuildInformation
|
||||||
Commit: "unknown",
|
version = "unknown"
|
||||||
BuildDate: "an unknown date",
|
commit = "unknown"
|
||||||
}
|
buildDate = "an unknown date"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
buildInfo.Version = version
|
||||||
|
buildInfo.Commit = commit
|
||||||
|
buildInfo.BuildDate = buildDate
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
os.Exit(_main(ctx, os.Args))
|
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)
|
logger.Info("VPN routing IP address: %s", vpnDestination)
|
||||||
}
|
}
|
||||||
if portForwardingEnabled {
|
if portForwardingEnabled {
|
||||||
// TODO make instantaneous once v3 go out of service
|
// vpnGateway required only for PIA v4
|
||||||
const waitDuration = 5 * time.Second
|
vpnGateway, err := routing.VPNLocalGatewayIP()
|
||||||
timer := time.NewTimer(waitDuration)
|
if err != nil {
|
||||||
select {
|
logger.Error(err)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
logger.Info("VPN gateway IP address: %s", vpnGateway)
|
||||||
|
startPortForward(vpnGateway)
|
||||||
}
|
}
|
||||||
case <-dnsReadyCh:
|
case <-dnsReadyCh:
|
||||||
publicIPLooper.Restart() // TODO do not restart if disabled
|
publicIPLooper.Restart() // TODO do not restart if disabled
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ func Update(args []string) error {
|
|||||||
flagSet.BoolVar(&options.Mullvad, "mullvad", false, "Update Mullvad servers")
|
flagSet.BoolVar(&options.Mullvad, "mullvad", false, "Update Mullvad servers")
|
||||||
flagSet.BoolVar(&options.Nordvpn, "nordvpn", false, "Update Nordvpn 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.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.Purevpn, "purevpn", false, "Update Purevpn servers")
|
||||||
flagSet.BoolVar(&options.Surfshark, "surfshark", false, "Update Surfshark servers")
|
flagSet.BoolVar(&options.Surfshark, "surfshark", false, "Update Surfshark servers")
|
||||||
flagSet.BoolVar(&options.Vyprvpn, "vyprvpn", false, "Update Vyprvpn servers")
|
flagSet.BoolVar(&options.Vyprvpn, "vyprvpn", false, "Update Vyprvpn servers")
|
||||||
|
|||||||
@@ -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}}}},
|
{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"
|
|
||||||
)
|
|
||||||
|
|||||||
206
internal/constants/privado.go
Normal file
206
internal/constants/privado.go
Normal 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}},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,16 +26,16 @@ func GetAllServers() (allServers models.AllServers) {
|
|||||||
Timestamp: 1602531173,
|
Timestamp: 1602531173,
|
||||||
Servers: PIAServers(),
|
Servers: PIAServers(),
|
||||||
},
|
},
|
||||||
PiaOld: models.PiaOldServers{
|
|
||||||
Version: 1,
|
|
||||||
Timestamp: 1602523433,
|
|
||||||
Servers: PIAOldServers(),
|
|
||||||
},
|
|
||||||
Purevpn: models.PurevpnServers{
|
Purevpn: models.PurevpnServers{
|
||||||
Version: 1,
|
Version: 1,
|
||||||
Timestamp: 1599323261,
|
Timestamp: 1599323261,
|
||||||
Servers: PurevpnServers(),
|
Servers: PurevpnServers(),
|
||||||
},
|
},
|
||||||
|
Privado: models.PrivadoServers{
|
||||||
|
Version: 2,
|
||||||
|
Timestamp: 1604963273,
|
||||||
|
Servers: PrivadoServers(),
|
||||||
|
},
|
||||||
Surfshark: models.SurfsharkServers{
|
Surfshark: models.SurfsharkServers{
|
||||||
Version: 1,
|
Version: 1,
|
||||||
Timestamp: 1599957644,
|
Timestamp: 1599957644,
|
||||||
@@ -47,8 +47,8 @@ func GetAllServers() (allServers models.AllServers) {
|
|||||||
Servers: VyprvpnServers(),
|
Servers: VyprvpnServers(),
|
||||||
},
|
},
|
||||||
Windscribe: models.WindscribeServers{
|
Windscribe: models.WindscribeServers{
|
||||||
Version: 1,
|
Version: 2,
|
||||||
Timestamp: 1599323261,
|
Timestamp: 1604019438,
|
||||||
Servers: WindscribeServers(),
|
Servers: WindscribeServers(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,10 +54,10 @@ func Test_versions(t *testing.T) {
|
|||||||
version: allServers.Pia.Version,
|
version: allServers.Pia.Version,
|
||||||
digest: "f1e01afe",
|
digest: "f1e01afe",
|
||||||
},
|
},
|
||||||
"Private Internet Access Old": {
|
"Privado": {
|
||||||
model: models.PIAOldServer{},
|
model: models.PrivadoServer{},
|
||||||
version: allServers.PiaOld.Version,
|
version: allServers.Privado.Version,
|
||||||
digest: "4e25ce4a",
|
digest: "1d5aeb23",
|
||||||
},
|
},
|
||||||
"Purevpn": {
|
"Purevpn": {
|
||||||
model: models.PurevpnServer{},
|
model: models.PurevpnServer{},
|
||||||
@@ -77,7 +77,7 @@ func Test_versions(t *testing.T) {
|
|||||||
"Windscribe": {
|
"Windscribe": {
|
||||||
model: models.WindscribeServer{},
|
model: models.WindscribeServer{},
|
||||||
version: allServers.Windscribe.Version,
|
version: allServers.Windscribe.Version,
|
||||||
digest: "042bef64",
|
digest: "6e3ca639",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for name, testCase := range testCases {
|
for name, testCase := range testCases {
|
||||||
@@ -135,16 +135,16 @@ func Test_timestamps(t *testing.T) {
|
|||||||
timestamp: allServers.Pia.Timestamp,
|
timestamp: allServers.Pia.Timestamp,
|
||||||
digest: "1571e777",
|
digest: "1571e777",
|
||||||
},
|
},
|
||||||
"Private Internet Access Old": {
|
|
||||||
servers: allServers.PiaOld.Servers,
|
|
||||||
timestamp: allServers.PiaOld.Timestamp,
|
|
||||||
digest: "3566a800",
|
|
||||||
},
|
|
||||||
"Purevpn": {
|
"Purevpn": {
|
||||||
servers: allServers.Purevpn.Servers,
|
servers: allServers.Purevpn.Servers,
|
||||||
timestamp: allServers.Purevpn.Timestamp,
|
timestamp: allServers.Purevpn.Timestamp,
|
||||||
digest: "cdf9b708",
|
digest: "cdf9b708",
|
||||||
},
|
},
|
||||||
|
"Privado": {
|
||||||
|
servers: allServers.Privado.Servers,
|
||||||
|
timestamp: allServers.Privado.Timestamp,
|
||||||
|
digest: "df2a046d",
|
||||||
|
},
|
||||||
"Surfshark": {
|
"Surfshark": {
|
||||||
servers: allServers.Surfshark.Servers,
|
servers: allServers.Surfshark.Servers,
|
||||||
timestamp: allServers.Surfshark.Timestamp,
|
timestamp: allServers.Surfshark.Timestamp,
|
||||||
@@ -158,7 +158,7 @@ func Test_timestamps(t *testing.T) {
|
|||||||
"Windscribe": {
|
"Windscribe": {
|
||||||
servers: allServers.Windscribe.Servers,
|
servers: allServers.Windscribe.Servers,
|
||||||
timestamp: allServers.Windscribe.Timestamp,
|
timestamp: allServers.Windscribe.Timestamp,
|
||||||
digest: "eacad593",
|
digest: "fd87502e",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for name, testCase := range testCases {
|
for name, testCase := range testCases {
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ package constants
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Announcement is a message announcement.
|
// 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 is the expiration date of the announcement in format yyyy-mm-dd.
|
||||||
AnnouncementExpiration = "2020-11-15"
|
AnnouncementExpiration = "2020-11-25"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import (
|
|||||||
const (
|
const (
|
||||||
// PrivateInternetAccess is a VPN provider.
|
// PrivateInternetAccess is a VPN provider.
|
||||||
PrivateInternetAccess models.VPNProvider = "private internet access"
|
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 is a VPN provider.
|
||||||
Mullvad models.VPNProvider = "mullvad"
|
Mullvad models.VPNProvider = "mullvad"
|
||||||
// Windscribe is a VPN provider.
|
// Windscribe is a VPN provider.
|
||||||
@@ -23,6 +21,8 @@ const (
|
|||||||
Nordvpn models.VPNProvider = "nordvpn"
|
Nordvpn models.VPNProvider = "nordvpn"
|
||||||
// PureVPN is a VPN provider.
|
// PureVPN is a VPN provider.
|
||||||
Purevpn models.VPNProvider = "purevpn"
|
Purevpn models.VPNProvider = "purevpn"
|
||||||
|
// Privado is a VPN provider.
|
||||||
|
Privado models.VPNProvider = "privado"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -21,79 +21,319 @@ func WindscribeRegionChoices() (choices []string) {
|
|||||||
return choices
|
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
|
//nolint:lll
|
||||||
func WindscribeServers() []models.WindscribeServer {
|
func WindscribeServers() []models.WindscribeServer {
|
||||||
return []models.WindscribeServer{
|
return []models.WindscribeServer{
|
||||||
{Region: "Albania", IPs: []net.IP{{31, 171, 152, 179}}},
|
{Region: "Albania", City: "Tirana", Hostname: "al-002.whiskergalaxy.com", IP: 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: "Argentina", City: "Buenos Aires", Hostname: "ar-001.whiskergalaxy.com", IP: net.IP{200, 85, 152, 110}},
|
||||||
{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: "Argentina", City: "Buenos Aires", Hostname: "ar-003.whiskergalaxy.com", IP: net.IP{167, 250, 6, 121}},
|
||||||
{Region: "Austria", IPs: []net.IP{{89, 187, 168, 66}, {217, 64, 127, 11}}},
|
{Region: "Argentina", City: "Buenos Aires", Hostname: "ar-004.whiskergalaxy.com", IP: net.IP{190, 105, 236, 50}},
|
||||||
{Region: "Azerbaijan", IPs: []net.IP{{85, 132, 61, 123}}},
|
{Region: "Argentina", City: "Buenos Aires", Hostname: "ar-005.whiskergalaxy.com", IP: net.IP{190, 105, 236, 32}},
|
||||||
{Region: "Belgium", IPs: []net.IP{{185, 232, 21, 131}, {194, 187, 251, 147}}},
|
{Region: "Argentina", City: "Buenos Aires", Hostname: "ar-006.whiskergalaxy.com", IP: net.IP{190, 105, 236, 19}},
|
||||||
{Region: "Bosnia", IPs: []net.IP{{185, 99, 3, 24}}},
|
{Region: "Australia", City: "Adelaide ", Hostname: "au-011.whiskergalaxy.com", IP: net.IP{103, 108, 92, 83}},
|
||||||
{Region: "Brazil", IPs: []net.IP{{177, 54, 144, 68}, {177, 67, 80, 59}, {189, 1, 172, 12}}},
|
{Region: "Australia", City: "Adelaide", Hostname: "au-008.whiskergalaxy.com", IP: net.IP{116, 90, 72, 243}},
|
||||||
{Region: "Bulgaria", IPs: []net.IP{{185, 94, 192, 35}}},
|
{Region: "Australia", City: "Brisbane", Hostname: "au-007.whiskergalaxy.com", IP: net.IP{103, 62, 50, 208}},
|
||||||
{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: "Australia", City: "Brisbane", Hostname: "au-014.whiskergalaxy.com", IP: net.IP{43, 245, 160, 35}},
|
||||||
{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: "Australia", City: "Canberra", Hostname: "au-010.whiskergalaxy.com", IP: net.IP{116, 206, 229, 131}},
|
||||||
{Region: "Colombia", IPs: []net.IP{{138, 121, 203, 203}, {138, 186, 141, 155}}},
|
{Region: "Australia", City: "Melbourne ", Hostname: "au-005.whiskergalaxy.com", IP: net.IP{45, 121, 209, 160}},
|
||||||
{Region: "Croatia", IPs: []net.IP{{85, 10, 56, 252}}},
|
{Region: "Australia", City: "Melbourne ", Hostname: "au-013.whiskergalaxy.com", IP: net.IP{116, 206, 228, 67}},
|
||||||
{Region: "Cyprus", IPs: []net.IP{{157, 97, 132, 43}}},
|
{Region: "Australia", City: "Perth", Hostname: "au-004.whiskergalaxy.com", IP: net.IP{45, 121, 208, 160}},
|
||||||
{Region: "Czech republic", IPs: []net.IP{{185, 156, 174, 11}, {185, 246, 210, 2}}},
|
{Region: "Australia", City: "Perth", Hostname: "au-012.whiskergalaxy.com", IP: net.IP{103, 77, 234, 211}},
|
||||||
{Region: "Denmark", IPs: []net.IP{{134, 90, 149, 147}, {185, 206, 224, 195}}},
|
{Region: "Australia", City: "Sydney", Hostname: "au-009.whiskergalaxy.com", IP: net.IP{103, 77, 233, 67}},
|
||||||
{Region: "Estonia", IPs: []net.IP{{46, 22, 211, 251}, {196, 196, 216, 131}}},
|
{Region: "Australia", City: "Sydney", Hostname: "au-015.whiskergalaxy.com", IP: net.IP{103, 1, 213, 211}},
|
||||||
{Region: "Fake antarctica", IPs: []net.IP{{23, 154, 160, 212}, {23, 154, 160, 222}}},
|
{Region: "Austria", City: "Vienna", Hostname: "at-001.whiskergalaxy.com", IP: net.IP{217, 64, 127, 11}},
|
||||||
{Region: "Finland", IPs: []net.IP{{185, 112, 82, 227}, {194, 34, 133, 82}}},
|
{Region: "Austria", City: "Vienna", Hostname: "at-002.whiskergalaxy.com", IP: net.IP{89, 187, 168, 66}},
|
||||||
{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: "Belgium", City: "Brussels", Hostname: "be-001.whiskergalaxy.com", IP: net.IP{194, 187, 251, 147}},
|
||||||
{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: "Belgium", City: "Brussels", Hostname: "be-002.whiskergalaxy.com", IP: net.IP{185, 232, 21, 131}},
|
||||||
{Region: "Greece", IPs: []net.IP{{78, 108, 38, 155}, {185, 226, 64, 111}, {188, 123, 126, 146}}},
|
{Region: "Brazil", City: "Sao Paulo", Hostname: "br-004.whiskergalaxy.com", IP: net.IP{177, 67, 80, 59}},
|
||||||
{Region: "Guinea-Bissau", IPs: []net.IP{{149, 56, 10, 82}}},
|
{Region: "Brazil", City: "Sao Paulo", Hostname: "br-005.whiskergalaxy.com", IP: net.IP{177, 54, 157, 178}},
|
||||||
{Region: "Hong kong", IPs: []net.IP{{84, 17, 57, 114}, {103, 10, 197, 99}}},
|
{Region: "Brazil", City: "Sao Paulo", Hostname: "br-006.whiskergalaxy.com", IP: net.IP{177, 54, 148, 247}},
|
||||||
{Region: "Hungary", IPs: []net.IP{{185, 104, 187, 43}}},
|
{Region: "Bulgaria", City: "Sofia", Hostname: "bg-001.whiskergalaxy.com", IP: net.IP{185, 94, 192, 35}},
|
||||||
{Region: "Iceland", IPs: []net.IP{{82, 221, 139, 38}, {185, 165, 170, 2}}},
|
{Region: "Canada East", City: "Halifax", Hostname: "ca-029.whiskergalaxy.com", IP: net.IP{199, 204, 208, 158}},
|
||||||
{Region: "India", IPs: []net.IP{{103, 205, 140, 227}, {169, 38, 68, 188}, {169, 38, 72, 12}, {169, 38, 72, 14}}},
|
{Region: "Canada East", City: "Montreal", Hostname: "ca-004.whiskergalaxy.com", IP: net.IP{66, 70, 148, 80}},
|
||||||
{Region: "Indonesia", IPs: []net.IP{{45, 127, 134, 91}}},
|
{Region: "Canada East", City: "Montreal", Hostname: "ca-027.whiskergalaxy.com", IP: net.IP{144, 168, 163, 160}},
|
||||||
{Region: "Ireland", IPs: []net.IP{{185, 24, 232, 146}, {185, 104, 219, 2}}},
|
{Region: "Canada East", City: "Montreal", Hostname: "ca-028.whiskergalaxy.com", IP: net.IP{144, 168, 163, 193}},
|
||||||
{Region: "Israel", IPs: []net.IP{{160, 116, 0, 27}, {185, 191, 205, 139}}},
|
{Region: "Canada East", City: "Montreal", Hostname: "ca-032.whiskergalaxy.com", IP: net.IP{104, 227, 235, 129}},
|
||||||
{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: "Canada East", City: "Montreal", Hostname: "ca-033.whiskergalaxy.com", IP: net.IP{198, 8, 85, 195}},
|
||||||
{Region: "Japan", IPs: []net.IP{{89, 187, 161, 114}, {193, 148, 16, 243}}},
|
{Region: "Canada East", City: "Montreal", Hostname: "ca-034.whiskergalaxy.com", IP: net.IP{198, 8, 85, 210}},
|
||||||
{Region: "Latvia", IPs: []net.IP{{85, 254, 72, 23}, {89, 111, 33, 220}}},
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-002.whiskergalaxy.com", IP: net.IP{104, 254, 92, 11}},
|
||||||
{Region: "Lithuania", IPs: []net.IP{{85, 206, 163, 225}}},
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-009.whiskergalaxy.com", IP: net.IP{104, 254, 92, 91}},
|
||||||
{Region: "Macedonia", IPs: []net.IP{{185, 225, 28, 51}}},
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-017.whiskergalaxy.com", IP: net.IP{184, 75, 212, 91}},
|
||||||
{Region: "Madagascar", IPs: []net.IP{{104, 20, 26, 217}, {104, 20, 27, 217}, {172, 67, 17, 175}}},
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-025.whiskergalaxy.com", IP: net.IP{192, 190, 19, 65}},
|
||||||
{Region: "Malaysia", IPs: []net.IP{{103, 106, 250, 31}, {103, 212, 69, 232}}},
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-026.whiskergalaxy.com", IP: net.IP{192, 190, 19, 97}},
|
||||||
{Region: "Mexico", IPs: []net.IP{{143, 255, 57, 67}, {190, 103, 179, 211}, {190, 103, 179, 217}, {201, 131, 125, 107}}},
|
{Region: "Canada East", City: "Toronto", Hostname: "ca-030.whiskergalaxy.com", IP: net.IP{23, 154, 160, 177}},
|
||||||
{Region: "Moldova", IPs: []net.IP{{178, 175, 144, 123}}},
|
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-005.whiskergalaxy.com", IP: net.IP{162, 221, 207, 95}},
|
||||||
{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: "Canada West", City: "Vancouver", Hostname: "ca-west-011.whiskergalaxy.com", IP: net.IP{104, 218, 61, 1}},
|
||||||
{Region: "New zealand", IPs: []net.IP{{103, 62, 49, 113}}},
|
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-012.whiskergalaxy.com", IP: net.IP{104, 218, 61, 33}},
|
||||||
{Region: "Norway", IPs: []net.IP{{37, 120, 203, 67}, {185, 206, 225, 131}}},
|
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-016.whiskergalaxy.com", IP: net.IP{208, 78, 41, 1}},
|
||||||
{Region: "Panama", IPs: []net.IP{{138, 186, 142, 203}}},
|
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-017.whiskergalaxy.com", IP: net.IP{208, 78, 41, 131}},
|
||||||
{Region: "Peru", IPs: []net.IP{{190, 120, 229, 139}}},
|
{Region: "Canada West", City: "Vancouver", Hostname: "ca-west-019.whiskergalaxy.com", IP: net.IP{208, 78, 41, 163}},
|
||||||
{Region: "Philippines", IPs: []net.IP{{103, 103, 0, 118}, {141, 98, 215, 211}}},
|
{Region: "Colombia", City: "Bogota", Hostname: "co-001.whiskergalaxy.com", IP: net.IP{138, 121, 203, 203}},
|
||||||
{Region: "Poland", IPs: []net.IP{{5, 133, 11, 116}, {84, 17, 55, 98}, {185, 244, 214, 35}}},
|
{Region: "Colombia", City: "Bogota", Hostname: "co-002.whiskergalaxy.com", IP: net.IP{138, 186, 141, 155}},
|
||||||
{Region: "Portugal", IPs: []net.IP{{94, 46, 13, 215}, {185, 15, 21, 66}}},
|
{Region: "Croatia", City: "Zagreb", Hostname: "hr-002.whiskergalaxy.com", IP: net.IP{85, 10, 56, 129}},
|
||||||
{Region: "Romania", IPs: []net.IP{{89, 46, 103, 147}, {91, 207, 102, 147}}},
|
{Region: "Cyprus", City: "Nicosia", Hostname: "cy-001.whiskergalaxy.com", IP: net.IP{157, 97, 132, 43}},
|
||||||
{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: "Czech Republic", City: "Prague ", Hostname: "cz-002.whiskergalaxy.com", IP: net.IP{185, 246, 210, 2}},
|
||||||
{Region: "Serbia", IPs: []net.IP{{141, 98, 103, 19}}},
|
{Region: "Czech Republic", City: "Prague", Hostname: "cz-001.whiskergalaxy.com", IP: net.IP{185, 156, 174, 11}},
|
||||||
{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: "Denmark", City: "Copenhagen", Hostname: "dk-001.whiskergalaxy.com", IP: net.IP{185, 206, 224, 195}},
|
||||||
{Region: "Slovakia", IPs: []net.IP{{185, 245, 85, 3}}},
|
{Region: "Denmark", City: "Copenhagen", Hostname: "dk-002.whiskergalaxy.com", IP: net.IP{134, 90, 149, 147}},
|
||||||
{Region: "South Africa", IPs: []net.IP{{129, 232, 167, 211}, {165, 73, 248, 91}, {197, 242, 157, 235}}},
|
{Region: "Estonia", City: "Tallinn", Hostname: "ee-001.whiskergalaxy.com", IP: net.IP{46, 22, 211, 251}},
|
||||||
{Region: "South Korea", IPs: []net.IP{{27, 255, 92, 52}, {103, 212, 223, 3}, {218, 232, 76, 179}}},
|
{Region: "Estonia", City: "Tallinn", Hostname: "ee-002.whiskergalaxy.com", IP: net.IP{196, 196, 216, 131}},
|
||||||
{Region: "Spain", IPs: []net.IP{{37, 120, 142, 227}, {89, 238, 178, 43}, {185, 253, 99, 131}, {217, 138, 218, 99}}},
|
{Region: "Fake Antarctica", City: "Troll", Hostname: "aq-001.whiskergalaxy.com", IP: net.IP{23, 154, 160, 212}},
|
||||||
{Region: "Sweden", IPs: []net.IP{{31, 13, 191, 67}, {79, 142, 76, 198}, {195, 181, 166, 129}}},
|
{Region: "Fake Antarctica", City: "Troll", Hostname: "aq-002.whiskergalaxy.com", IP: net.IP{23, 154, 160, 222}},
|
||||||
{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: "Finland", City: "Helsinki", Hostname: "fi-002.whiskergalaxy.com", IP: net.IP{185, 112, 82, 227}},
|
||||||
{Region: "Taiwan", IPs: []net.IP{{103, 4, 29, 77}, {185, 189, 160, 12}, {185, 189, 160, 27}, {185, 189, 160, 32}}},
|
{Region: "Finland", City: "Helsinki", Hostname: "fi-003.whiskergalaxy.com", IP: net.IP{194, 34, 133, 82}},
|
||||||
{Region: "Thailand", IPs: []net.IP{{27, 254, 130, 221}, {202, 129, 16, 147}, {202, 129, 16, 155}}},
|
{Region: "Finland", City: "Helsinki", Hostname: "fi-004.whiskergalaxy.com", IP: net.IP{196, 244, 192, 51}},
|
||||||
{Region: "Tunisia", IPs: []net.IP{{41, 231, 5, 23}}},
|
{Region: "France", City: "Paris", Hostname: "fr-004.whiskergalaxy.com", IP: net.IP{185, 156, 173, 187}},
|
||||||
{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: "France", City: "Paris", Hostname: "fr-005.whiskergalaxy.com", IP: net.IP{82, 102, 18, 35}},
|
||||||
{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: "France", City: "Paris", Hostname: "fr-008.whiskergalaxy.com", IP: net.IP{84, 17, 42, 34}},
|
||||||
{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: "France", City: "Paris", Hostname: "fr-009.whiskergalaxy.com", IP: net.IP{84, 17, 42, 2}},
|
||||||
{Region: "Ukraine", IPs: []net.IP{{45, 141, 156, 11}, {45, 141, 156, 50}}},
|
{Region: "France", City: "Paris", Hostname: "fr-011.whiskergalaxy.com", IP: net.IP{45, 89, 174, 35}},
|
||||||
{Region: "United Arab Emirates", IPs: []net.IP{{45, 9, 249, 43}}},
|
{Region: "Germany", City: "Frankfurt", Hostname: "de-003.whiskergalaxy.com", IP: net.IP{89, 249, 65, 19}},
|
||||||
{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: "Germany", City: "Frankfurt", Hostname: "de-006.whiskergalaxy.com", IP: net.IP{185, 130, 184, 195}},
|
||||||
{Region: "Vietnam", IPs: []net.IP{{103, 9, 76, 197}, {103, 9, 79, 186}, {103, 9, 79, 219}}},
|
{Region: "Germany", City: "Frankfurt", Hostname: "de-009.whiskergalaxy.com", IP: net.IP{195, 181, 170, 66}},
|
||||||
{Region: "Windflix CA", IPs: []net.IP{{104, 218, 60, 111}, {104, 254, 92, 99}}},
|
{Region: "Germany", City: "Frankfurt", Hostname: "de-010.whiskergalaxy.com", IP: net.IP{195, 181, 175, 98}},
|
||||||
{Region: "Windflix JP", IPs: []net.IP{{5, 181, 235, 67}}},
|
{Region: "Germany", City: "Frankfurt", Hostname: "de-011.whiskergalaxy.com", IP: net.IP{217, 138, 194, 115}},
|
||||||
{Region: "Windflix UK", IPs: []net.IP{{45, 9, 248, 3}, {81, 92, 200, 85}, {89, 47, 62, 83}}},
|
{Region: "Germany", City: "Frankfurt", Hostname: "de-012.whiskergalaxy.com", IP: net.IP{45, 87, 212, 51}},
|
||||||
{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: "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}},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,10 @@ func (c *configurator) enable(ctx context.Context) (err error) {
|
|||||||
return fmt.Errorf("cannot enable firewall: %w", err)
|
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 {
|
for _, subnet := range c.outboundSubnets {
|
||||||
if err := c.acceptOutputFromIPToSubnet(ctx, c.defaultInterface, c.localIP, subnet, remove); err != nil {
|
if err := c.acceptOutputFromIPToSubnet(ctx, c.defaultInterface, c.localIP, subnet, remove); err != nil {
|
||||||
return fmt.Errorf("cannot enable firewall: %w", err)
|
return fmt.Errorf("cannot enable firewall: %w", err)
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ type OpenVPNConnection struct {
|
|||||||
IP net.IP
|
IP net.IP
|
||||||
Port uint16
|
Port uint16
|
||||||
Protocol NetworkProtocol
|
Protocol NetworkProtocol
|
||||||
|
Hostname string // Privado for tls verification
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *OpenVPNConnection) Equal(other OpenVPNConnection) bool {
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ type ServerSelection struct {
|
|||||||
// Cyberghost
|
// Cyberghost
|
||||||
Group string `json:"group"`
|
Group string `json:"group"`
|
||||||
|
|
||||||
// Mullvad, PureVPN
|
Countries []string `json:"countries"` // Mullvad, PureVPN
|
||||||
Countries []string `json:"countries"`
|
Cities []string `json:"cities"` // Mullvad, PureVPN, Windscribe
|
||||||
Cities []string `json:"cities"`
|
Hostnames []string `json:"hostnames"` // Windscribe, Privado
|
||||||
|
|
||||||
// Mullvad
|
// Mullvad
|
||||||
ISPs []string `json:"isps"`
|
ISPs []string `json:"isps"`
|
||||||
@@ -130,6 +130,11 @@ func (p *ProviderSettings) String() string {
|
|||||||
"Countries: "+commaJoin(p.ServerSelection.Countries),
|
"Countries: "+commaJoin(p.ServerSelection.Countries),
|
||||||
"Cities: "+commaJoin(p.ServerSelection.Cities),
|
"Cities: "+commaJoin(p.ServerSelection.Cities),
|
||||||
)
|
)
|
||||||
|
case "privado":
|
||||||
|
settingsList = append(settingsList,
|
||||||
|
"Cities: "+commaJoin(p.ServerSelection.Cities),
|
||||||
|
"Server numbers: "+commaJoin(numbers),
|
||||||
|
)
|
||||||
default:
|
default:
|
||||||
settingsList = append(settingsList,
|
settingsList = append(settingsList,
|
||||||
"<Missing String method, please implement me!>",
|
"<Missing String method, please implement me!>",
|
||||||
|
|||||||
@@ -28,15 +28,6 @@ func (p *PIAServer) String() string {
|
|||||||
p.Region, p.PortForward, p.OpenvpnUDP.String(), p.OpenvpnTCP.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 {
|
type MullvadServer struct {
|
||||||
IPs []net.IP `json:"ips"`
|
IPs []net.IP `json:"ips"`
|
||||||
IPsV6 []net.IP `json:"ipsv6"`
|
IPsV6 []net.IP `json:"ipsv6"`
|
||||||
@@ -52,12 +43,15 @@ func (s *MullvadServer) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WindscribeServer struct {
|
type WindscribeServer struct {
|
||||||
Region string `json:"region"`
|
Region string `json:"region"`
|
||||||
IPs []net.IP `json:"ips"`
|
City string `json:"city"`
|
||||||
|
Hostname string `json:"hostname"`
|
||||||
|
IP net.IP `json:"ip"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WindscribeServer) String() string {
|
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 {
|
type SurfsharkServer struct {
|
||||||
@@ -113,6 +107,16 @@ func (s *PurevpnServer) String() string {
|
|||||||
s.Region, s.Country, s.City, goStringifyIPs(s.IPs))
|
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 {
|
func goStringifyIP(ip net.IP) string {
|
||||||
s := fmt.Sprintf("%#v", ip)
|
s := fmt.Sprintf("%#v", ip)
|
||||||
s = strings.TrimSuffix(strings.TrimPrefix(s, "net.IP{"), "}")
|
s = strings.TrimSuffix(strings.TrimPrefix(s, "net.IP{"), "}")
|
||||||
|
|||||||
@@ -7,31 +7,6 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"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) {
|
func Test_MullvadServer_String(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ type AllServers struct {
|
|||||||
Cyberghost CyberghostServers `json:"cyberghost"`
|
Cyberghost CyberghostServers `json:"cyberghost"`
|
||||||
Mullvad MullvadServers `json:"mullvad"`
|
Mullvad MullvadServers `json:"mullvad"`
|
||||||
Nordvpn NordvpnServers `json:"nordvpn"`
|
Nordvpn NordvpnServers `json:"nordvpn"`
|
||||||
PiaOld PiaOldServers `json:"piaOld"`
|
|
||||||
Pia PiaServers `json:"pia"`
|
Pia PiaServers `json:"pia"`
|
||||||
|
Privado PrivadoServers `json:"privado"`
|
||||||
Purevpn PurevpnServers `json:"purevpn"`
|
Purevpn PurevpnServers `json:"purevpn"`
|
||||||
Surfshark SurfsharkServers `json:"surfshark"`
|
Surfshark SurfsharkServers `json:"surfshark"`
|
||||||
Vyprvpn VyprvpnServers `json:"vyprvpn"`
|
Vyprvpn VyprvpnServers `json:"vyprvpn"`
|
||||||
@@ -28,20 +28,20 @@ type NordvpnServers struct {
|
|||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
Servers []NordvpnServer `json:"servers"`
|
Servers []NordvpnServer `json:"servers"`
|
||||||
}
|
}
|
||||||
type PiaOldServers struct {
|
|
||||||
Version uint16 `json:"version"`
|
|
||||||
Timestamp int64 `json:"timestamp"`
|
|
||||||
Servers []PIAOldServer `json:"servers"`
|
|
||||||
}
|
|
||||||
type PiaServers struct {
|
type PiaServers struct {
|
||||||
Version uint16 `json:"version"`
|
Version uint16 `json:"version"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
Servers []PIAServer `json:"servers"`
|
Servers []PIAServer `json:"servers"`
|
||||||
}
|
}
|
||||||
|
type PrivadoServers struct {
|
||||||
|
Version uint16 `json:"version"`
|
||||||
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
Servers []PrivadoServer `json:"servers"`
|
||||||
|
}
|
||||||
type PurevpnServers struct {
|
type PurevpnServers struct {
|
||||||
Version uint16 `json:"version"`
|
Version uint16 `json:"version"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
Servers []PurevpnServer `json:"purevpn"`
|
Servers []PurevpnServer `json:"servers"`
|
||||||
}
|
}
|
||||||
type SurfsharkServers struct {
|
type SurfsharkServers struct {
|
||||||
Version uint16 `json:"version"`
|
Version uint16 `json:"version"`
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ type Reader interface {
|
|||||||
GetPortForwardingStatusFilepath() (filepath models.Filepath, err error)
|
GetPortForwardingStatusFilepath() (filepath models.Filepath, err error)
|
||||||
GetPIAEncryptionPreset() (preset string, err error)
|
GetPIAEncryptionPreset() (preset string, err error)
|
||||||
GetPIARegions() (regions []string, err error)
|
GetPIARegions() (regions []string, err error)
|
||||||
GetPIAOldRegions() (regions []string, err error)
|
|
||||||
|
|
||||||
// Mullvad getters
|
// Mullvad getters
|
||||||
GetMullvadCountries() (countries []string, err error)
|
GetMullvadCountries() (countries []string, err error)
|
||||||
@@ -73,6 +72,8 @@ type Reader interface {
|
|||||||
|
|
||||||
// Windscribe getters
|
// Windscribe getters
|
||||||
GetWindscribeRegions() (countries []string, err error)
|
GetWindscribeRegions() (countries []string, err error)
|
||||||
|
GetWindscribeCities() (cities []string, err error)
|
||||||
|
GetWindscribeHostnames() (hostnames []string, err error)
|
||||||
GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error)
|
GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error)
|
||||||
|
|
||||||
// Surfshark getters
|
// Surfshark getters
|
||||||
@@ -90,6 +91,9 @@ type Reader interface {
|
|||||||
GetNordvpnRegions() (regions []string, err error)
|
GetNordvpnRegions() (regions []string, err error)
|
||||||
GetNordvpnNumbers() (numbers []uint16, err error)
|
GetNordvpnNumbers() (numbers []uint16, err error)
|
||||||
|
|
||||||
|
// Privado getters
|
||||||
|
GetPrivadoHostnames() (hostnames []string, err error)
|
||||||
|
|
||||||
// PureVPN getters
|
// PureVPN getters
|
||||||
GetPurevpnRegions() (regions []string, err error)
|
GetPurevpnRegions() (regions []string, err error)
|
||||||
GetPurevpnCountries() (countries []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(
|
s, err := r.envParams.GetValueIfInside(
|
||||||
"VPNSP",
|
"VPNSP",
|
||||||
[]string{
|
[]string{
|
||||||
"pia", "private internet access", "private internet access old",
|
"pia", "private internet access",
|
||||||
"mullvad", "windscribe", "surfshark", "cyberghost",
|
"mullvad", "windscribe", "surfshark", "cyberghost",
|
||||||
"vyprvpn", "nordvpn", "purevpn",
|
"vyprvpn", "nordvpn", "purevpn", "privado",
|
||||||
}, libparams.Default("private internet access"))
|
}, libparams.Default("private internet access"))
|
||||||
if s == "pia" {
|
if s == "pia" {
|
||||||
s = "private internet access"
|
s = "private internet access"
|
||||||
|
|||||||
@@ -63,9 +63,3 @@ func (r *reader) GetPIAEncryptionPreset() (preset string, err error) {
|
|||||||
func (r *reader) GetPIARegions() (regions []string, err error) {
|
func (r *reader) GetPIARegions() (regions []string, err error) {
|
||||||
return r.envParams.GetCSVInPossibilities("REGION", constants.PIAGeoChoices())
|
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())
|
|
||||||
}
|
|
||||||
|
|||||||
11
internal/params/privado.go
Normal file
11
internal/params/privado.go
Normal 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())
|
||||||
|
}
|
||||||
@@ -14,7 +14,19 @@ func (r *reader) GetWindscribeRegions() (regions []string, err error) {
|
|||||||
return r.envParams.GetCSVInPossibilities("REGION", constants.WindscribeRegionChoices())
|
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.
|
// environment variable PORT.
|
||||||
//nolint:gomnd
|
//nolint:gomnd
|
||||||
func (r *reader) GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error) {
|
func (r *reader) GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error) {
|
||||||
|
|||||||
@@ -2,4 +2,5 @@ package provider
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
aes256cbc = "aes-256-cbc"
|
aes256cbc = "aes-256-cbc"
|
||||||
|
sha256 = "sha256"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ func (c *cyberghost) BuildConf(connection models.OpenVPNConnection, verbosity,
|
|||||||
cipher = aes256cbc
|
cipher = aes256cbc
|
||||||
}
|
}
|
||||||
if len(auth) == 0 {
|
if len(auth) == 0 {
|
||||||
auth = "SHA256"
|
auth = sha256
|
||||||
}
|
}
|
||||||
lines = []string{
|
lines = []string{
|
||||||
"client",
|
"client",
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
123
internal/provider/privado.go
Normal file
123
internal/provider/privado.go
Normal 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")
|
||||||
|
}
|
||||||
@@ -26,8 +26,6 @@ func New(provider models.VPNProvider, allServers models.AllServers, timeNow time
|
|||||||
switch provider {
|
switch provider {
|
||||||
case constants.PrivateInternetAccess:
|
case constants.PrivateInternetAccess:
|
||||||
return newPrivateInternetAccessV4(allServers.Pia.Servers, timeNow)
|
return newPrivateInternetAccessV4(allServers.Pia.Servers, timeNow)
|
||||||
case constants.PrivateInternetAccessOld:
|
|
||||||
return newPrivateInternetAccessV3(allServers.PiaOld.Servers, timeNow)
|
|
||||||
case constants.Mullvad:
|
case constants.Mullvad:
|
||||||
return newMullvad(allServers.Mullvad.Servers, timeNow)
|
return newMullvad(allServers.Mullvad.Servers, timeNow)
|
||||||
case constants.Windscribe:
|
case constants.Windscribe:
|
||||||
@@ -42,6 +40,8 @@ func New(provider models.VPNProvider, allServers models.AllServers, timeNow time
|
|||||||
return newNordvpn(allServers.Nordvpn.Servers, timeNow)
|
return newNordvpn(allServers.Nordvpn.Servers, timeNow)
|
||||||
case constants.Purevpn:
|
case constants.Purevpn:
|
||||||
return newPurevpn(allServers.Purevpn.Servers, timeNow)
|
return newPurevpn(allServers.Purevpn.Servers, timeNow)
|
||||||
|
case constants.Privado:
|
||||||
|
return newPrivado(allServers.Privado.Servers, timeNow)
|
||||||
default:
|
default:
|
||||||
return nil // should never occur
|
return nil // should never occur
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
for _, server := range w.servers {
|
||||||
switch {
|
switch {
|
||||||
case
|
case
|
||||||
filterByPossibilities(server.Region, regions):
|
filterByPossibilities(server.Region, regions),
|
||||||
|
filterByPossibilities(server.City, cities),
|
||||||
|
filterByPossibilities(server.Hostname, hostnames):
|
||||||
default:
|
default:
|
||||||
servers = append(servers, server)
|
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
|
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 {
|
if len(servers) == 0 {
|
||||||
return connection, fmt.Errorf("no server found for region %s", commaJoin(selection.Regions))
|
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 _, server := range servers {
|
||||||
for _, IP := range server.IPs {
|
connections = append(connections, models.OpenVPNConnection{IP: server.IP, Port: port, Protocol: selection.Protocol})
|
||||||
connections = append(connections, models.OpenVPNConnection{IP: IP, Port: port, Protocol: selection.Protocol})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pickRandomConnection(connections, w.randSource), nil
|
return pickRandomConnection(connections, w.randSource), nil
|
||||||
|
|||||||
70
internal/server/handler.go
Normal file
70
internal/server/handler.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,32 +5,32 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *server) handleGetPortForwarded(w http.ResponseWriter) {
|
func (h *handler) getPortForwarded(w http.ResponseWriter) {
|
||||||
port := s.openvpnLooper.GetPortForwarded()
|
port := h.openvpnLooper.GetPortForwarded()
|
||||||
data, err := json.Marshal(struct {
|
data, err := json.Marshal(struct {
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
}{port})
|
}{port})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Warn(err)
|
h.logger.Warn(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := w.Write(data); err != nil {
|
if _, err := w.Write(data); err != nil {
|
||||||
s.logger.Warn(err)
|
h.logger.Warn(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) handleGetOpenvpnSettings(w http.ResponseWriter) {
|
func (h *handler) getOpenvpnSettings(w http.ResponseWriter) {
|
||||||
settings := s.openvpnLooper.GetSettings()
|
settings := h.openvpnLooper.GetSettings()
|
||||||
data, err := json.Marshal(settings)
|
data, err := json.Marshal(settings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Warn(err)
|
h.logger.Warn(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := w.Write(data); err != nil {
|
if _, err := w.Write(data); err != nil {
|
||||||
s.logger.Warn(err)
|
h.logger.Warn(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -19,30 +18,24 @@ type Server interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type server struct {
|
type server struct {
|
||||||
address string
|
address string
|
||||||
logging bool
|
logger logging.Logger
|
||||||
logger logging.Logger
|
handler http.Handler
|
||||||
buildInfo models.BuildInformation
|
|
||||||
openvpnLooper openvpn.Looper
|
|
||||||
unboundLooper dns.Looper
|
|
||||||
updaterLooper updater.Looper
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(address string, logging bool, logger logging.Logger, buildInfo models.BuildInformation,
|
func New(address string, logging bool, logger logging.Logger, buildInfo models.BuildInformation,
|
||||||
openvpnLooper openvpn.Looper, unboundLooper dns.Looper, updaterLooper updater.Looper) Server {
|
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{
|
return &server{
|
||||||
address: address,
|
address: address,
|
||||||
logging: logging,
|
logger: serverLogger,
|
||||||
logger: logger.WithPrefix("http server: "),
|
handler: handler,
|
||||||
buildInfo: buildInfo,
|
|
||||||
openvpnLooper: openvpnLooper,
|
|
||||||
unboundLooper: unboundLooper,
|
|
||||||
updaterLooper: updaterLooper,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) Run(ctx context.Context, wg *sync.WaitGroup) {
|
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() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
@@ -61,42 +54,3 @@ func (s *server) Run(ctx context.Context, wg *sync.WaitGroup) {
|
|||||||
s.logger.Error(err)
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *server) handleGetVersion(w http.ResponseWriter) {
|
func (h *handler) getVersion(w http.ResponseWriter) {
|
||||||
data, err := json.Marshal(s.buildInfo)
|
data, err := json.Marshal(h.buildInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Warn(err)
|
h.logger.Warn(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := w.Write(data); err != nil {
|
if _, err := w.Write(data); err != nil {
|
||||||
s.logger.Warn(err)
|
h.logger.Warn(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ func GetOpenVPNSettings(paramsReader params.Reader, vpnProvider models.VPNProvid
|
|||||||
switch vpnProvider {
|
switch vpnProvider {
|
||||||
case constants.PrivateInternetAccess:
|
case constants.PrivateInternetAccess:
|
||||||
settings.Provider, err = GetPIASettings(paramsReader)
|
settings.Provider, err = GetPIASettings(paramsReader)
|
||||||
case constants.PrivateInternetAccessOld:
|
|
||||||
settings.Provider, err = GetPIAOldSettings(paramsReader)
|
|
||||||
case constants.Mullvad:
|
case constants.Mullvad:
|
||||||
settings.Provider, err = GetMullvadSettings(paramsReader)
|
settings.Provider, err = GetMullvadSettings(paramsReader)
|
||||||
case constants.Windscribe:
|
case constants.Windscribe:
|
||||||
@@ -70,6 +68,8 @@ func GetOpenVPNSettings(paramsReader params.Reader, vpnProvider models.VPNProvid
|
|||||||
settings.Provider, err = GetNordvpnSettings(paramsReader)
|
settings.Provider, err = GetNordvpnSettings(paramsReader)
|
||||||
case constants.Purevpn:
|
case constants.Purevpn:
|
||||||
settings.Provider, err = GetPurevpnSettings(paramsReader)
|
settings.Provider, err = GetPurevpnSettings(paramsReader)
|
||||||
|
case constants.Privado:
|
||||||
|
settings.Provider, err = GetPrivadoSettings(paramsReader)
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("VPN service provider %q is not valid", vpnProvider)
|
err = fmt.Errorf("VPN service provider %q is not valid", vpnProvider)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func Test_OpenVPN_JSON(t *testing.T) {
|
|||||||
data, err := json.Marshal(in)
|
data, err := json.Marshal(in)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
//nolint:lll
|
//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
|
var out OpenVPN
|
||||||
err = json.Unmarshal(data, &out)
|
err = json.Unmarshal(data, &out)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -10,17 +10,7 @@ import (
|
|||||||
|
|
||||||
// GetPIASettings obtains PIA settings from environment variables using the params package.
|
// GetPIASettings obtains PIA settings from environment variables using the params package.
|
||||||
func GetPIASettings(paramsReader params.Reader) (settings models.ProviderSettings, err error) {
|
func GetPIASettings(paramsReader params.Reader) (settings models.ProviderSettings, err error) {
|
||||||
return getPIASettings(paramsReader, constants.PrivateInternetAccess)
|
settings.Name = 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.ServerSelection.Protocol, err = paramsReader.GetNetworkProtocol()
|
settings.ServerSelection.Protocol, err = paramsReader.GetNetworkProtocol()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return settings, err
|
return settings, err
|
||||||
@@ -118,6 +108,14 @@ func GetWindscribeSettings(paramsReader params.Reader) (settings models.Provider
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return settings, err
|
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)
|
settings.ServerSelection.CustomPort, err = paramsReader.GetWindscribePort(settings.ServerSelection.Protocol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return settings, err
|
return settings, err
|
||||||
@@ -234,3 +232,21 @@ func GetPurevpnSettings(paramsReader params.Reader) (settings models.ProviderSet
|
|||||||
}
|
}
|
||||||
return settings, nil
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,12 +47,19 @@ func (s *storage) mergeServers(hardcoded, persistent models.AllServers) (merged
|
|||||||
merged.Pia = persistent.Pia
|
merged.Pia = persistent.Pia
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
merged.PiaOld = hardcoded.PiaOld
|
|
||||||
if persistent.PiaOld.Timestamp > hardcoded.PiaOld.Timestamp {
|
merged.Privado = hardcoded.Privado
|
||||||
s.logger.Info("Using Private Internet Access older servers from file (%s more recent)",
|
versionDiff := int(persistent.Privado.Version) - int(hardcoded.Privado.Version)
|
||||||
getUnixTimeDifference(persistent.PiaOld.Timestamp, hardcoded.PiaOld.Timestamp))
|
switch {
|
||||||
merged.PiaOld = persistent.PiaOld
|
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
|
merged.Purevpn = hardcoded.Purevpn
|
||||||
if persistent.Purevpn.Timestamp > hardcoded.Purevpn.Timestamp {
|
if persistent.Purevpn.Timestamp > hardcoded.Purevpn.Timestamp {
|
||||||
s.logger.Info("Using Purevpn servers from file (%s more recent)",
|
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
|
merged.Windscribe = hardcoded.Windscribe
|
||||||
if persistent.Windscribe.Timestamp > hardcoded.Windscribe.Timestamp {
|
if persistent.Windscribe.Timestamp > hardcoded.Windscribe.Timestamp {
|
||||||
s.logger.Info("Using Windscribe servers from file (%s more recent)",
|
if hardcoded.Windscribe.Version == 2 && persistent.Windscribe.Version == 1 {
|
||||||
getUnixTimeDifference(persistent.Windscribe.Timestamp, hardcoded.Windscribe.Timestamp))
|
s.logger.Info("Windscribe servers from file discarded because they are one version behind")
|
||||||
merged.Windscribe = persistent.Windscribe
|
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
|
return merged
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func countServers(allServers models.AllServers) int {
|
|||||||
len(allServers.Mullvad.Servers) +
|
len(allServers.Mullvad.Servers) +
|
||||||
len(allServers.Nordvpn.Servers) +
|
len(allServers.Nordvpn.Servers) +
|
||||||
len(allServers.Pia.Servers) +
|
len(allServers.Pia.Servers) +
|
||||||
len(allServers.PiaOld.Servers) +
|
len(allServers.Privado.Servers) +
|
||||||
len(allServers.Purevpn.Servers) +
|
len(allServers.Purevpn.Servers) +
|
||||||
len(allServers.Surfshark.Servers) +
|
len(allServers.Surfshark.Servers) +
|
||||||
len(allServers.Vyprvpn.Servers) +
|
len(allServers.Vyprvpn.Servers) +
|
||||||
|
|||||||
@@ -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
|
func getCyberghostSubdomainToRegion() map[string]string { //nolint:dupl
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
"af": "Afghanistan",
|
"af": "Afghanistan",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ type Options struct {
|
|||||||
Mullvad bool
|
Mullvad bool
|
||||||
Nordvpn bool
|
Nordvpn bool
|
||||||
PIA bool
|
PIA bool
|
||||||
PIAold bool
|
Privado bool
|
||||||
Purevpn bool
|
Purevpn bool
|
||||||
Surfshark bool
|
Surfshark bool
|
||||||
Vyprvpn bool
|
Vyprvpn bool
|
||||||
@@ -21,7 +21,6 @@ func NewOptions(dnsAddress string) Options {
|
|||||||
Mullvad: true,
|
Mullvad: true,
|
||||||
Nordvpn: true,
|
Nordvpn: true,
|
||||||
PIA: true,
|
PIA: true,
|
||||||
PIAold: true,
|
|
||||||
Purevpn: true,
|
Purevpn: true,
|
||||||
Surfshark: true,
|
Surfshark: true,
|
||||||
Vyprvpn: true,
|
Vyprvpn: true,
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
94
internal/updater/privado.go
Normal file
94
internal/updater/privado.go
Normal 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
|
||||||
|
}
|
||||||
@@ -90,14 +90,14 @@ func (u *updater) UpdateServers(ctx context.Context) (allServers models.AllServe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.options.PIAold {
|
if u.options.Privado {
|
||||||
u.logger.Info("updating Private Internet Access old (v3) servers...")
|
u.logger.Info("updating Privado servers...")
|
||||||
if err := u.updatePIAOld(ctx); err != nil {
|
if err := u.updatePrivado(ctx); err != nil {
|
||||||
if ctxErr := ctx.Err(); ctxErr != nil {
|
|
||||||
return allServers, ctxErr
|
|
||||||
}
|
|
||||||
u.logger.Error(err)
|
u.logger.Error(err)
|
||||||
}
|
}
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return allServers, ctx.Err()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.options.Purevpn {
|
if u.options.Purevpn {
|
||||||
|
|||||||
@@ -2,14 +2,19 @@ package updater
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
|
"github.com/qdm12/golibs/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *updater) updateWindscribe(ctx context.Context) (err error) {
|
func (u *updater) updateWindscribe(ctx context.Context) (err error) {
|
||||||
servers, err := findWindscribeServers(ctx, u.lookupIP)
|
servers, err := findWindscribeServers(ctx, u.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot update Windscribe servers: %w", err)
|
return fmt.Errorf("cannot update Windscribe servers: %w", err)
|
||||||
}
|
}
|
||||||
@@ -21,46 +26,53 @@ func (u *updater) updateWindscribe(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findWindscribeServers(ctx context.Context, lookupIP lookupIPFunc) (servers []models.WindscribeServer, err error) {
|
func findWindscribeServers(ctx context.Context, client network.Client) (servers []models.WindscribeServer, err error) {
|
||||||
allCountryCodes := getCountryCodes()
|
const baseURL = "https://assets.windscribe.com/serverlist/mob-v2/1/"
|
||||||
windscribeCountryCodes := getWindscribeSubdomainToRegion()
|
cacheBreaker := time.Now().Unix()
|
||||||
possibleCountryCodes := mergeCountryCodes(windscribeCountryCodes, allCountryCodes)
|
url := fmt.Sprintf("%s%d", baseURL, cacheBreaker)
|
||||||
const domain = "windscribe.com"
|
content, status, err := client.Get(ctx, url)
|
||||||
for countryCode, region := range possibleCountryCodes {
|
if err != nil {
|
||||||
if err := ctx.Err(); err != nil {
|
return nil, err
|
||||||
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 {
|
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
|
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) {
|
func stringifyWindscribeServers(servers []models.WindscribeServer) (s string) {
|
||||||
s = "func WindscribeServers() []models.WindscribeServer {\n"
|
s = "func WindscribeServers() []models.WindscribeServer {\n"
|
||||||
s += " return []models.WindscribeServer{\n"
|
s += " return []models.WindscribeServer{\n"
|
||||||
@@ -71,77 +83,3 @@ func stringifyWindscribeServers(servers []models.WindscribeServer) (s string) {
|
|||||||
s += "}"
|
s += "}"
|
||||||
return 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",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user