Compare commits

..

33 Commits

Author SHA1 Message Date
Quentin McGaw (desktop)
06c8792887 Doc: clarify setup instructions 2021-06-22 15:21:49 +00:00
Quentin McGaw (desktop)
3ea376a1b2 Doc: maintenance document 2021-06-22 14:42:15 +00:00
Quentin McGaw (desktop)
9667d30907 Doc: add code highlighting how-to to issue templates 2021-06-22 14:41:48 +00:00
Quentin McGaw (desktop)
3f7ccc6c49 Feature: improve Cyberghost updater
- Waits up to 20s for resolutions
- Update server information and timestamp
2021-06-21 20:29:55 +00:00
Quentin McGaw (desktop)
dd97ff5895 Maintenance: cache xcputranslate 2021-06-21 18:50:30 +00:00
Quentin McGaw (desktop)
2e4d80d9bc Maintenance: sleep for cross building 2021-06-21 18:35:40 +00:00
Quentin McGaw (desktop)
1227dc5a2b Maintenance: upgrade xcputranslate to v0.6.0 2021-06-21 18:01:21 +00:00
Quentin McGaw (desktop)
ed828bc733 Hotfix: VPN Unlimited variable choices 2021-06-21 13:32:03 +00:00
Quentin McGaw (desktop)
c25a018c05 Maintenance: CI deduplicate base stage build 2021-06-21 13:01:53 +00:00
Quentin McGaw (desktop)
266596af68 Fix errors introduced with golangci-lint 1.41.1 2021-06-20 16:39:38 +00:00
Quentin McGaw
2c77b73ebc IPVanish support (#475)
- Fix #410 and #416
2021-06-20 09:21:48 -07:00
Quentin McGaw
d81d4bbda3 VPN Unlimited support (#499)
- Fixes #420 
- Revert to docker/build-push-action@v2.4.0
2021-06-20 09:18:03 -07:00
Quentin McGaw (desktop)
400affe429 Maintenance: add revive linter 2021-06-20 16:12:39 +00:00
Quentin McGaw (desktop)
d3c63680e8 Maintenance: ugprade golangci-lint to v1.41.1 2021-06-20 16:12:09 +00:00
Quentin McGaw (desktop)
28de8a834c Maintenance: upgrade golang/mock to v1.6.0 2021-06-19 17:24:41 +00:00
Quentin McGaw (desktop)
208374fc54 Fix: Use name prefix for TLS check for IVPN 2021-06-19 16:34:50 +00:00
Quentin McGaw (desktop)
535a136a27 Feature: add IVPN Bulgaria and Spain servers 2021-06-19 16:34:36 +00:00
Quentin McGaw (desktop)
ba4c3e30a4 Doc: docker-compose.yml does not use secrets 2021-06-17 22:46:30 +00:00
Quentin McGaw (desktop)
16d8a388cb Maintenance: better layer caching
- Install g++ in base image before copying code
- Install xcputranslate in base image before copying code
- Install golangci-lint in base image before copying code
- Install golangci-lint using go get directly
2021-06-15 12:27:32 +00:00
Quentin McGaw (desktop)
5ea31b0b64 Maintenance: set entrypoint for test Docker stage 2021-06-15 12:25:57 +00:00
Quentin McGaw (desktop)
582c6d1c43 Fix: only use and write auth file if user is set
- Apply to custom openvpn configuration without username
2021-06-14 14:25:37 +00:00
Quentin McGaw (desktop)
c63ae3f3af Fix: custom openvpn config settings log 2021-06-14 14:24:38 +00:00
Quentin McGaw (desktop)
4c0df96a95 Maintenance: use github.com/qdm12/goshutdown 2021-06-10 15:03:47 +00:00
Quentin McGaw (desktop)
05c6b9379a Maintenance: prevent exit race condition for loops 2021-06-10 14:13:08 +00:00
Quentin McGaw (desktop)
fb7fdcd925 Fix: change PureVPN default cipher to AES-256-GCM 2021-06-08 00:24:46 +00:00
Quentin McGaw (desktop)
1774e2ad88 Maintenance: update list of linters 2021-06-07 23:31:52 +00:00
Quentin McGaw (desktop)
a402d9135e Fix: remote line for custom OpenVPN config 2021-06-07 19:46:21 +00:00
Quentin McGaw (desktop)
3d2c56d9ee Fix: custom cipher for custom files on Openvpn 2.5 2021-06-07 19:45:19 +00:00
Quentin McGaw (desktop)
f9308e6fed Remove dependency on github.com/kyokomi/emoji 2021-06-06 15:38:49 +00:00
Quentin McGaw (desktop)
6710468020 Maintenance: upgrade Go dependencies
- Upgrade fatih/color to v1.12.0
- Upgrade qdm12/dns to v1.8.0
- Upgrade qdm12/golibs
- Upgrade qdm12/updated
2021-06-03 21:31:50 +00:00
Quentin McGaw (desktop)
ad1981fff6 Maintenance: update PureVPN server information 2021-06-02 14:32:15 +00:00
Quentin McGaw (desktop)
01f9e71912 Fix: none encryption preset for PIA
- Set cipher and auth to `none`
- Add `ncp-disable` OpenVPN option in every case
2021-06-01 13:52:57 +00:00
Quentin McGaw (desktop)
d41b75ee35 Documentation: add discussion link for help issues 2021-06-01 13:44:04 +00:00
101 changed files with 5013 additions and 883 deletions

View File

@@ -39,3 +39,7 @@ PASTE YOUR LOGS
IN THERE
```
<!---
💡 You can highlight your code with https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlight
-->

View File

@@ -7,6 +7,12 @@ assignees:
---
<!---
⚠️ If this about a Docker configuration problem or another service:
Start a discussion at https://github.com/qdm12/gluetun/discussions/new
OR I WILL INSTA-CLOSE YOUR ISSUE.
-->
<!---
⚠️ Answer the following or I'll insta-close your issue
-->
@@ -40,6 +46,10 @@ IN THERE
**What are you using to run your container?**: Docker Compose
<!---
💡 You can highlight your code with https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlight
-->
Please also share your configuration file:
```yml

6
.github/labels.yml vendored
View File

@@ -21,6 +21,9 @@
- name: ":cloud: HideMyAss"
color: "cfe8d4"
description: ""
- name: ":cloud: IPVanish"
color: "cfe8d4"
description: ""
- name: ":cloud: IVPN"
color: "cfe8d4"
description: ""
@@ -53,6 +56,9 @@
- name: ":cloud: Torguard"
color: "cfe8d4"
description: ""
- name: ":cloud: VPNUnlimited"
color: "cfe8d4"
description: ""
- name: ":cloud: Vyprvpn"
color: "cfe8d4"
description: ""

View File

@@ -34,13 +34,7 @@ jobs:
touch coverage.txt
docker run --rm \
-v "$(pwd)/coverage.txt:/tmp/gobuild/coverage.txt" \
test-container \
go test \
-race \
-coverpkg=./... \
-coverprofile=coverage.txt \
-covermode=atomic \
./...
test-container
- name: Code security analysis
uses: snyk/actions/golang@master
@@ -92,13 +86,14 @@ jobs:
fi
- name: Build and push final image
uses: docker/build-push-action@v2
uses: docker/build-push-action@v2.4.0
with:
platforms: ${{ steps.vars.outputs.platforms }}
build-args: |
BUILD_DATE=${{ steps.vars.outputs.build_date }}
COMMIT=${{ steps.vars.outputs.commit }}
VERSION=${{ steps.vars.outputs.version }}
ALLTARGETPLATFORMS=${{ steps.vars.outputs.platforms }}
tags: |
qmcgaw/gluetun:${{ steps.vars.outputs.version }}
qmcgaw/private-internet-access:${{ steps.vars.outputs.version }}

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
scratch.txt

View File

@@ -17,6 +17,15 @@ issues:
- path: internal/configuration/
linters:
- dupl
- text: "exported: exported var Err*"
linters:
- revive
- text: "mnd: Magic number: 0644*"
linters:
- gomnd
- text: "mnd: Magic number: 0400*"
linters:
- gomnd
linters:
disable-all: true
enable:
@@ -36,12 +45,12 @@ linters:
- gocritic
- gocyclo
- godot
- goerr113
- goheader
- goimports
- gomnd
- goprintffuncname
- gosec
- goerr113
- gosimple
- govet
- importas
@@ -55,8 +64,8 @@ linters:
- nolintlint
- prealloc
- predeclared
- revive
- rowserrcheck
- exportloopref
- sqlclosecheck
- staticcheck
- structcheck

View File

@@ -2,9 +2,14 @@ ARG ALPINE_VERSION=3.13
ARG GO_VERSION=1.16
ARG BUILDPLATFORM=linux/amd64
FROM --platform=$BUILDPLATFORM qmcgaw/xcputranslate:v0.6.0 AS xcputranslate
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
RUN apk --update add git
COPY --from=xcputranslate /xcputranslate /usr/local/bin/xcputranslate
RUN apk --update add git g++
ENV CGO_ENABLED=0
ARG GOLANGCI_LINT_VERSION=v1.41.1
RUN go get github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION}
WORKDIR /tmp/gobuild
COPY go.mod go.sum ./
RUN go mod download
@@ -14,14 +19,11 @@ COPY internal/ ./internal/
FROM --platform=$BUILDPLATFORM base AS test
# Note on the go race detector:
# - we set CGO_ENABLED=1 to have it enabled
# - we install g++ to support the race detector
# - we installed g++ to support the race detector
ENV CGO_ENABLED=1
RUN apk --update --no-cache add g++
ENTRYPOINT go test -race -coverpkg=./... -coverprofile=coverage.txt -covermode=atomic ./...
FROM --platform=$BUILDPLATFORM base AS lint
ARG GOLANGCI_LINT_VERSION=v1.40.1
RUN wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | \
sh -s -- -b /usr/local/bin ${GOLANGCI_LINT_VERSION}
COPY .golangci.yml ./
RUN golangci-lint run --timeout=10m
@@ -35,13 +37,14 @@ RUN git init && \
git diff --exit-code -- go.mod
FROM --platform=$BUILDPLATFORM base AS build
COPY --from=qmcgaw/xcputranslate:v0.4.0 /xcputranslate /usr/local/bin/xcputranslate
ARG TARGETPLATFORM
ARG ALLTARGETPLATFORMS=${TARGETPLATFORM}
ARG VERSION=unknown
ARG BUILD_DATE="an unknown date"
ARG COMMIT=unknown
RUN GOARCH="$(xcputranslate -field arch -targetplatform ${TARGETPLATFORM})" \
GOARM="$(xcputranslate -field arm -targetplatform ${TARGETPLATFORM})" \
RUN xcputranslate sleep -targetplatform ${TARGETPLATFORM} -buildtime=10s -order=${ALLTARGETPLATFORMS}
RUN GOARCH="$(xcputranslate translate -field arch -targetplatform ${TARGETPLATFORM})" \
GOARM="$(xcputranslate translate -field arm -targetplatform ${TARGETPLATFORM})" \
go build -trimpath -ldflags="-s -w \
-X 'main.version=$VERSION' \
-X 'main.buildDate=$BUILD_DATE' \

View File

@@ -1,8 +1,8 @@
# Gluetun VPN client
*Lightweight swiss-knife-like VPN client to tunnel to Cyberghost, FastestVPN,
HideMyAss, IVPN, Mullvad, NordVPN, Privado, Private Internet Access, PrivateVPN,
ProtonVPN, PureVPN, Surfshark, TorGuard, VyprVPN and Windscribe VPN servers
HideMyAss, IPVanish, IVPN, Mullvad, NordVPN, Privado, Private Internet Access, PrivateVPN,
ProtonVPN, PureVPN, Surfshark, TorGuard, VPNUnlimited, VyprVPN and Windscribe VPN servers
using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and an HTTP proxy*
**ANNOUNCEMENT**:
@@ -39,7 +39,7 @@ using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and an HTTP proxy*
## Features
- Based on Alpine 3.13 for a small Docker image of 54MB
- Supports: **Cyberghost**, **FastestVPN**, **HideMyAss**, **IVPN**, **Mullvad**, **NordVPN**, **Privado**, **Private Internet Access**, **PrivateVPN**, **ProtonVPN**, **PureVPN**, **Surfshark**, **TorGuard**, **Vyprvpn**, **Windscribe** servers
- Supports: **Cyberghost**, **FastestVPN**, **HideMyAss**, **IPVanish**, **IVPN**, **Mullvad**, **NordVPN**, **Privado**, **Private Internet Access**, **PrivateVPN**, **ProtonVPN**, **PureVPN**, **Surfshark**, **TorGuard**, **VPNUnlimited**, **Vyprvpn**, **Windscribe** servers
- Supports Openvpn only for now
- DNS over TLS baked in with service provider(s) of your choice
- DNS fine blocking of malicious/ads/surveillance hostnames and IP addresses, with live update every 24 hours
@@ -58,9 +58,17 @@ using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and an HTTP proxy*
## Setup
1. On some devices you may need to setup your tunnel kernel module on your host with `insmod /lib/modules/tun.ko` or `modprobe tun`
- [Synology users Wiki page](https://github.com/qdm12/gluetun/wiki/Synology-setup)
1. ⚠️ Raspberry Pi users running 32 bit systems: from image `v3.16.0` you need to do [this](https://github.com/alpinelinux/docker-alpine/issues/135#issuecomment-812287338) on your host to run the container.
1. Ensure your `tun` kernel module is setup:
```sh
sudo modprobe tun
# or, if you don't have modprobe, with
sudo insmod /lib/modules/tun.ko
```
1. Extra steps:
- [For Synology users](https://github.com/qdm12/gluetun/wiki/Synology-setup)
- [For 32 bit Operating systems (**Rasberry Pis**)](https://github.com/qdm12/gluetun/wiki/32-bit-setup)
1. Launch the container with:
```bash
@@ -74,8 +82,6 @@ using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and an HTTP proxy*
or use [docker-compose.yml](https://github.com/qdm12/gluetun/blob/master/docker-compose.yml) with:
```bash
echo "your openvpn username" > openvpn_user
echo "your openvpn password" > openvpn_password
docker-compose up -d
```
@@ -85,12 +91,12 @@ using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and an HTTP proxy*
The following points are all optional but should give you insights on all the possibilities with this container.
- Use [Docker secrets](https://github.com/qdm12/gluetun/wiki/Docker-secrets) to read your credentials instead of environment variables
- [Test your setup](https://github.com/qdm12/gluetun/wiki/Test-your-setup)
- [How to connect other containers and devices to Gluetun](https://github.com/qdm12/gluetun/wiki/Connect-to-gluetun)
- [VPN server side port forwarding](https://github.com/qdm12/gluetun/wiki/Port-forwarding)
- [HTTP control server](https://github.com/qdm12/gluetun/wiki/HTTP-Control-server) to automate things, restart Openvpn etc.
- Update the image with `docker pull qmcgaw/gluetun:latest`. See this [Wiki document](https://github.com/qdm12/gluetun/wiki/Docker-image-tags) for Docker tags available.
- Use [Docker secrets](https://github.com/qdm12/gluetun/wiki/Docker-secrets) to read your credentials instead of environment variables
## License

View File

@@ -29,7 +29,6 @@ import (
"github.com/qdm12/gluetun/internal/routing"
"github.com/qdm12/gluetun/internal/server"
"github.com/qdm12/gluetun/internal/shadowsocks"
"github.com/qdm12/gluetun/internal/shutdown"
"github.com/qdm12/gluetun/internal/storage"
"github.com/qdm12/gluetun/internal/unix"
"github.com/qdm12/gluetun/internal/updater"
@@ -38,6 +37,7 @@ import (
"github.com/qdm12/golibs/os"
"github.com/qdm12/golibs/os/user"
"github.com/qdm12/golibs/params"
"github.com/qdm12/goshutdown"
"github.com/qdm12/updated/pkg/dnscrypto"
)
@@ -275,82 +275,113 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
}
} // TODO move inside firewall?
const (
shutdownMaxTimeout = 3 * time.Second
shutdownRoutineTimeout = 400 * time.Millisecond
shutdownOpenvpnTimeout = time.Second
)
healthy := make(chan bool)
controlWave := shutdown.NewWave("control")
tickerWave := shutdown.NewWave("tickers")
healthWave := shutdown.NewWave("health")
dnsWave := shutdown.NewWave("DNS")
vpnWave := shutdown.NewWave("VPN")
serverWave := shutdown.NewWave("servers")
// Shutdown settings
const defaultShutdownTimeout = 400 * time.Millisecond
defaultShutdownOnSuccess := func(goRoutineName string) {
logger.Info(goRoutineName + ": terminated ✔️")
}
defaultShutdownOnFailure := func(goRoutineName string, err error) {
logger.Warn(goRoutineName + ": " + err.Error() + " ⚠️")
}
defaultGoRoutineSettings := goshutdown.GoRoutineSettings{Timeout: defaultShutdownTimeout}
defaultGroupSettings := goshutdown.GroupSettings{
Timeout: defaultShutdownTimeout,
OnFailure: defaultShutdownOnFailure,
OnSuccess: defaultShutdownOnSuccess,
}
controlGroupHandler := goshutdown.NewGroupHandler("control", defaultGroupSettings)
tickersGroupHandler := goshutdown.NewGroupHandler("tickers", defaultGroupSettings)
otherGroupHandler := goshutdown.NewGroupHandler("other", defaultGroupSettings)
openvpnLooper := openvpn.NewLooper(allSettings.OpenVPN, nonRootUsername, puid, pgid, allServers,
ovpnConf, firewallConf, routingConf, logger, httpClient, os.OpenFile, tunnelReadyCh, healthy)
openvpnCtx, openvpnDone := vpnWave.Add("openvpn", shutdownOpenvpnTimeout)
openvpnHandler, openvpnCtx, openvpnDone := goshutdown.NewGoRoutineHandler(
"openvpn", goshutdown.GoRoutineSettings{Timeout: time.Second})
// wait for restartOpenvpn
go openvpnLooper.Run(openvpnCtx, openvpnDone)
updaterLooper := updater.NewLooper(allSettings.Updater,
allServers, storage, openvpnLooper.SetServers, httpClient,
logger.NewChild(logging.Settings{Prefix: "updater: "}))
updaterCtx, updaterDone := tickerWave.Add("updater", shutdownRoutineTimeout)
updaterHandler, updaterCtx, updaterDone := goshutdown.NewGoRoutineHandler(
"updater", defaultGoRoutineSettings)
// wait for updaterLooper.Restart() or its ticket launched with RunRestartTicker
go updaterLooper.Run(updaterCtx, updaterDone)
tickersGroupHandler.Add(updaterHandler)
unboundLogger := logger.NewChild(logging.Settings{Prefix: "dns over tls: "})
unboundLooper := dns.NewLooper(dnsConf, allSettings.DNS, httpClient,
unboundLogger, os.OpenFile)
dnsCtx, dnsDone := dnsWave.Add("unbound", shutdownRoutineTimeout)
dnsHandler, dnsCtx, dnsDone := goshutdown.NewGoRoutineHandler(
"unbound", defaultGoRoutineSettings)
// wait for unboundLooper.Restart or its ticker launched with RunRestartTicker
go unboundLooper.Run(dnsCtx, dnsDone)
otherGroupHandler.Add(dnsHandler)
publicIPLooper := publicip.NewLooper(httpClient,
logger.NewChild(logging.Settings{Prefix: "ip getter: "}),
allSettings.PublicIP, puid, pgid, os)
pubIPCtx, pubIPDone := serverWave.Add("public IP", shutdownRoutineTimeout)
pubIPHandler, pubIPCtx, pubIPDone := goshutdown.NewGoRoutineHandler(
"public IP", defaultGoRoutineSettings)
go publicIPLooper.Run(pubIPCtx, pubIPDone)
otherGroupHandler.Add(pubIPHandler)
pubIPTickerCtx, pubIPTickerDone := tickerWave.Add("public IP", shutdownRoutineTimeout)
pubIPTickerHandler, pubIPTickerCtx, pubIPTickerDone := goshutdown.NewGoRoutineHandler(
"public IP", defaultGoRoutineSettings)
go publicIPLooper.RunRestartTicker(pubIPTickerCtx, pubIPTickerDone)
tickersGroupHandler.Add(pubIPTickerHandler)
httpProxyLooper := httpproxy.NewLooper(
logger.NewChild(logging.Settings{Prefix: "http proxy: "}),
allSettings.HTTPProxy)
httpProxyCtx, httpProxyDone := serverWave.Add("http proxy", shutdownRoutineTimeout)
httpProxyHandler, httpProxyCtx, httpProxyDone := goshutdown.NewGoRoutineHandler(
"http proxy", defaultGoRoutineSettings)
go httpProxyLooper.Run(httpProxyCtx, httpProxyDone)
otherGroupHandler.Add(httpProxyHandler)
shadowsocksLooper := shadowsocks.NewLooper(allSettings.ShadowSocks,
logger.NewChild(logging.Settings{Prefix: "shadowsocks: "}))
shadowsocksCtx, shadowsocksDone := serverWave.Add("shadowsocks proxy", shutdownRoutineTimeout)
shadowsocksHandler, shadowsocksCtx, shadowsocksDone := goshutdown.NewGoRoutineHandler(
"shadowsocks proxy", defaultGoRoutineSettings)
go shadowsocksLooper.Run(shadowsocksCtx, shadowsocksDone)
otherGroupHandler.Add(shadowsocksHandler)
eventsRoutingCtx, eventsRoutingDone := controlWave.Add("events routing", shutdownRoutineTimeout)
eventsRoutingHandler, eventsRoutingCtx, eventsRoutingDone := goshutdown.NewGoRoutineHandler(
"events routing", defaultGoRoutineSettings)
go routeReadyEvents(eventsRoutingCtx, eventsRoutingDone, buildInfo, tunnelReadyCh,
unboundLooper, updaterLooper, publicIPLooper, routingConf, logger, httpClient,
allSettings.VersionInformation, allSettings.OpenVPN.Provider.PortForwarding.Enabled, openvpnLooper.PortForward,
)
controlGroupHandler.Add(eventsRoutingHandler)
controlServerAddress := ":" + strconv.Itoa(int(allSettings.ControlServer.Port))
controlServerLogging := allSettings.ControlServer.Log
httpServer := server.New(controlServerAddress, controlServerLogging,
logger.NewChild(logging.Settings{Prefix: "http server: "}),
buildInfo, openvpnLooper, unboundLooper, updaterLooper, publicIPLooper)
httpServerCtx, httpServerDone := controlWave.Add("http server", shutdownRoutineTimeout)
httpServerHandler, httpServerCtx, httpServerDone := goshutdown.NewGoRoutineHandler(
"http server", defaultGoRoutineSettings)
go httpServer.Run(httpServerCtx, httpServerDone)
controlGroupHandler.Add(httpServerHandler)
healthcheckServer := healthcheck.NewServer(constants.HealthcheckAddress,
logger.NewChild(logging.Settings{Prefix: "healthcheck: "}))
healthServerCtx, healthServerDone := healthWave.Add("HTTP health server", shutdownRoutineTimeout)
healthServerHandler, healthServerCtx, healthServerDone := goshutdown.NewGoRoutineHandler(
"HTTP health server", defaultGoRoutineSettings)
go healthcheckServer.Run(healthServerCtx, healthy, healthServerDone)
shutdownOrder := shutdown.NewOrder()
shutdownOrder.Append(controlWave, tickerWave, healthWave,
dnsWave, vpnWave, serverWave,
)
const orderShutdownTimeout = 3 * time.Second
orderSettings := goshutdown.OrderSettings{
Timeout: orderShutdownTimeout,
OnFailure: defaultShutdownOnFailure,
OnSuccess: defaultShutdownOnSuccess,
}
orderHandler := goshutdown.NewOrder("gluetun", orderSettings)
orderHandler.Append(controlGroupHandler, tickersGroupHandler, healthServerHandler,
openvpnHandler, otherGroupHandler)
// Start openvpn for the first time in a blocking call
// until openvpn is launched
@@ -365,7 +396,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
}
}
return shutdownOrder.Shutdown(shutdownMaxTimeout, logger)
return orderHandler.Shutdown(context.Background())
}
type printVersionElement struct {

View File

@@ -14,18 +14,11 @@ services:
# command:
volumes:
- /yourpath:/gluetun
secrets:
- openvpn_user
- openvpn_password
environment:
# More variables are available, see the readme table
- OPENVPN_USER=
- OPENVPN_PASSWORD=
- VPNSP=private internet access
# Timezone for accurate logs times
- TZ=
restart: always
secrets:
openvpn_user:
file: ./openvpn_user
openvpn_password:
file: ./openvpn_password

12
go.mod
View File

@@ -3,13 +3,13 @@ module github.com/qdm12/gluetun
go 1.16
require (
github.com/fatih/color v1.10.0
github.com/golang/mock v1.5.0
github.com/kyokomi/emoji v2.2.4+incompatible
github.com/qdm12/dns v1.7.0
github.com/qdm12/golibs v0.0.0-20210402232648-cfebf1e87d1b
github.com/fatih/color v1.12.0
github.com/golang/mock v1.6.0
github.com/qdm12/dns v1.8.0
github.com/qdm12/golibs v0.0.0-20210603202746-e5494e9c2ebb
github.com/qdm12/goshutdown v0.1.0
github.com/qdm12/ss-server v0.2.0
github.com/qdm12/updated v0.0.0-20210102012151-76b7f5994638
github.com/qdm12/updated v0.0.0-20210603204757-205acfe6937e
github.com/stretchr/testify v1.7.0
github.com/vishvananda/netlink v1.1.0
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015

71
go.sum
View File

@@ -1,4 +1,3 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
@@ -12,9 +11,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
@@ -31,58 +29,52 @@ github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsd
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/validate v0.17.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gotify/go-api-client/v2 v2.0.4/go.mod h1:VKiah/UK20bXsr0JObE1eBVLW44zbBouzjuri9iwjFU=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kyokomi/emoji v2.2.4+incompatible h1:np0woGKwx9LiHAQmwZx79Oc0rHpNw3o+3evou4BEPv4=
github.com/kyokomi/emoji v2.2.4+incompatible/go.mod h1:mZ6aGCD7yk8j6QY6KICwnZ2pxoszVseX1DNoGtU2tBA=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/miekg/dns v1.1.40 h1:pyyPFfGMnciYUk/mXpKkVmeMQjfXqt3FAJ2hy7tPiLA=
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee/go.mod h1:3uODdxMgOaPYeWU7RzZLxVtJHZ/x1f/iHkBZuKJDzuY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/qdm12/dns v1.7.0 h1:R8YGDPREzsXKx0k0TUbzPoI0+1oRzAnn79hzRXPHPcg=
github.com/qdm12/dns v1.7.0/go.mod h1:f2zChaUVDmE1MxUx+MKMFmBSh4G6DSU0rFZ+hHExSu0=
github.com/qdm12/golibs v0.0.0-20201227203847-2fd99ffdfdba/go.mod h1:pikkTN7g7zRuuAnERwqW1yAFq6pYmxrxpjiwGvb0Ysc=
github.com/qdm12/golibs v0.0.0-20210402232648-cfebf1e87d1b h1:tSD0qWqssS8AUFTGmlP1JFfbLViOt7xrjIxGZ1AFacY=
github.com/qdm12/golibs v0.0.0-20210402232648-cfebf1e87d1b/go.mod h1:y0qNgur9dTkHK2Bb5tK0UCtYyvEiK08flVIglROmnBg=
github.com/qdm12/dns v1.8.0 h1:GZ40kptmfDHOMNxBKWSA4zrbNyGm41BA57zv2MaDtCI=
github.com/qdm12/dns v1.8.0/go.mod h1:P2mm63NDYZdx2NAd5CVLM0FBnNdi1ZgVjsRSnX+96vg=
github.com/qdm12/golibs v0.0.0-20210603202746-e5494e9c2ebb h1:5WkOssTWl6Tv2H7VFb2jwB08A7BxxNCebkkpvz1PzrY=
github.com/qdm12/golibs v0.0.0-20210603202746-e5494e9c2ebb/go.mod h1:15RBzkun0i8XB7ADIoLJWp9ITRgsz3LroEI2FiOXLRg=
github.com/qdm12/goshutdown v0.1.0 h1:lmwnygdXtnr2pa6VqfR/bm8077/BnBef1+7CP96B7Sw=
github.com/qdm12/goshutdown v0.1.0/go.mod h1:/LP3MWLqI+wGH/ijfaUG+RHzBbKXIiVKnrg5vXOCf6Q=
github.com/qdm12/ss-server v0.2.0 h1:+togLzeeLAJ68MD1JqOWvYi9rl9t/fx1Qh7wKzZhY1g=
github.com/qdm12/ss-server v0.2.0/go.mod h1:+1bWO1EfWNvsGM5Cuep6vneChK2OHniqtAsED9Fh1y0=
github.com/qdm12/updated v0.0.0-20210102012151-76b7f5994638 h1:dM8OO6LO+uou14C5a/LUrot0oyqzPcoiSho6cEmOROc=
github.com/qdm12/updated v0.0.0-20210102012151-76b7f5994638/go.mod h1:bbJGxEYCnsA8WU4vBcXYU6mOoHyzdP458FIKP4mfLJM=
github.com/qdm12/updated v0.0.0-20210603204757-205acfe6937e h1:4q+uFLawkaQRq3yARYLsjJPZd2wYwxn4g6G/5v0xW1g=
github.com/qdm12/updated v0.0.0-20210603204757-205acfe6937e/go.mod h1:UvJRGkZ9XL3/D7e7JiTTVLm1F3Cymd3/gFpD6frEpBo=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -90,7 +82,6 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
@@ -100,10 +91,7 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go4.org/intern v0.0.0-20210108033219-3eb7198706b2 h1:VFTf+jjIgsldaz/Mr00VaCSswHJrI2hIjQygE/W4IMg=
go4.org/intern v0.0.0-20210108033219-3eb7198706b2/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
@@ -111,68 +99,58 @@ go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063 h1:1tk03FU
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
@@ -181,8 +159,5 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
inet.af/netaddr v0.0.0-20210511181906-37180328850c h1:rzDy/tC8LjEdN94+i0Bu22tTo/qE9cvhKyfD0HMU0NU=
inet.af/netaddr v0.0.0-20210511181906-37180328850c/go.mod h1:z0nx+Dh+7N7CC8V5ayHtHGpZpxLQZZxkIaaz6HN65Ls=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@@ -33,6 +33,7 @@ func (c *cli) Update(ctx context.Context, args []string, os os.OS, logger loggin
flagSet.BoolVar(&options.Cyberghost, "cyberghost", false, "Update Cyberghost servers")
flagSet.BoolVar(&options.Fastestvpn, "fastestvpn", false, "Update FastestVPN servers")
flagSet.BoolVar(&options.HideMyAss, "hidemyass", false, "Update HideMyAss servers")
flagSet.BoolVar(&options.Ipvanish, "ipvanish", false, "Update IpVanish servers")
flagSet.BoolVar(&options.Ivpn, "ivpn", false, "Update IVPN servers")
flagSet.BoolVar(&options.Mullvad, "mullvad", false, "Update Mullvad servers")
flagSet.BoolVar(&options.Nordvpn, "nordvpn", false, "Update Nordvpn servers")
@@ -43,6 +44,7 @@ func (c *cli) Update(ctx context.Context, args []string, os os.OS, logger loggin
flagSet.BoolVar(&options.Purevpn, "purevpn", false, "Update Purevpn servers")
flagSet.BoolVar(&options.Surfshark, "surfshark", false, "Update Surfshark servers")
flagSet.BoolVar(&options.Torguard, "torguard", false, "Update Torguard servers")
flagSet.BoolVar(&options.VPNUnlimited, "vpnunlimited", false, "Update VPN Unlimited servers")
flagSet.BoolVar(&options.Vyprvpn, "vyprvpn", false, "Update Vyprvpn servers")
flagSet.BoolVar(&options.Windscribe, "windscribe", false, "Update Windscribe servers")
if err := flagSet.Parse(args); err != nil {

View File

@@ -1,10 +1,6 @@
package configuration
import (
"encoding/pem"
"errors"
"strings"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/golibs/params"
)
@@ -44,12 +40,12 @@ func (settings *Provider) readCyberghost(r reader) (err error) {
return err
}
settings.ExtraConfigOptions.ClientKey, err = readCyberghostClientKey(r)
settings.ExtraConfigOptions.ClientKey, err = readClientKey(r)
if err != nil {
return err
}
settings.ExtraConfigOptions.ClientCertificate, err = readCyberghostClientCertificate(r)
settings.ExtraConfigOptions.ClientCertificate, err = readClientCertificate(r)
if err != nil {
return err
}
@@ -72,49 +68,3 @@ func (settings *Provider) readCyberghost(r reader) (err error) {
return nil
}
func readCyberghostClientKey(r reader) (clientKey string, err error) {
b, err := r.getFromFileOrSecretFile("OPENVPN_CLIENTKEY", constants.ClientKey)
if err != nil {
return "", err
}
return extractClientKey(b)
}
var errDecodePEMBlockClientKey = errors.New("cannot decode PEM block from client key")
func extractClientKey(b []byte) (key string, err error) {
pemBlock, _ := pem.Decode(b)
if pemBlock == nil {
return "", errDecodePEMBlockClientKey
}
parsedBytes := pem.EncodeToMemory(pemBlock)
s := string(parsedBytes)
s = strings.ReplaceAll(s, "\n", "")
s = strings.TrimPrefix(s, "-----BEGIN PRIVATE KEY-----")
s = strings.TrimSuffix(s, "-----END PRIVATE KEY-----")
return s, nil
}
func readCyberghostClientCertificate(r reader) (clientCertificate string, err error) {
b, err := r.getFromFileOrSecretFile("OPENVPN_CLIENTCRT", constants.ClientCertificate)
if err != nil {
return "", err
}
return extractClientCertificate(b)
}
var errDecodePEMBlockClientCert = errors.New("cannot decode PEM block from client certificate")
func extractClientCertificate(b []byte) (certificate string, err error) {
pemBlock, _ := pem.Decode(b)
if pemBlock == nil {
return "", errDecodePEMBlockClientCert
}
parsedBytes := pem.EncodeToMemory(pemBlock)
s := string(parsedBytes)
s = strings.ReplaceAll(s, "\n", "")
s = strings.TrimPrefix(s, "-----BEGIN CERTIFICATE-----")
s = strings.TrimSuffix(s, "-----END CERTIFICATE-----")
return s, nil
}

View File

@@ -29,11 +29,7 @@ func (settings *DNS) readBlacklistBuilding(r reader) (err error) {
return err
}
if err := settings.readBlacklistUnblockedHostnames(r); err != nil {
return err
}
return nil
return settings.readBlacklistUnblockedHostnames(r)
}
var (

View File

@@ -69,11 +69,7 @@ func (settings *Firewall) read(r reader) (err error) {
return err
}
if err := settings.readOutboundSubnets(r); err != nil {
return err
}
return nil
return settings.readOutboundSubnets(r)
}
func (settings *Firewall) readVPNInputPorts(env params.Env) (err error) {

View File

@@ -0,0 +1,52 @@
package configuration
import (
"github.com/qdm12/gluetun/internal/constants"
)
func (settings *Provider) ipvanishLines() (lines []string) {
if len(settings.ServerSelection.Countries) > 0 {
lines = append(lines, lastIndent+"Countries: "+commaJoin(settings.ServerSelection.Countries))
}
if len(settings.ServerSelection.Cities) > 0 {
lines = append(lines, lastIndent+"Cities: "+commaJoin(settings.ServerSelection.Cities))
}
if len(settings.ServerSelection.Hostnames) > 0 {
lines = append(lines, lastIndent+"Hostnames: "+commaJoin(settings.ServerSelection.Hostnames))
}
return lines
}
func (settings *Provider) readIpvanish(r reader) (err error) {
settings.Name = constants.Ipvanish
settings.ServerSelection.TCP, err = readProtocol(r.env)
if err != nil {
return err
}
settings.ServerSelection.TargetIP, err = readTargetIP(r.env)
if err != nil {
return err
}
settings.ServerSelection.Countries, err = r.env.CSVInside("COUNTRY", constants.IpvanishCountryChoices())
if err != nil {
return err
}
settings.ServerSelection.Cities, err = r.env.CSVInside("CITY", constants.IpvanishCityChoices())
if err != nil {
return err
}
settings.ServerSelection.Hostnames, err = r.env.CSVInside("SERVER_HOSTNAME", constants.IpvanishHostnameChoices())
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,192 @@
package configuration
import (
"errors"
"net"
"testing"
"github.com/golang/mock/gomock"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/golibs/params/mock_params"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_Provider_ipvanishLines(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
settings Provider
lines []string
}{
"empty settings": {},
"full settings": {
settings: Provider{
ServerSelection: ServerSelection{
Countries: []string{"A", "B"},
Cities: []string{"C", "D"},
Hostnames: []string{"E", "F"},
},
},
lines: []string{
"|--Countries: A, B",
"|--Cities: C, D",
"|--Hostnames: E, F",
},
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
lines := testCase.settings.ipvanishLines()
assert.Equal(t, testCase.lines, lines)
})
}
}
func Test_Provider_readIpvanish(t *testing.T) {
t.Parallel()
var errDummy = errors.New("dummy test error")
type singleStringCall struct {
call bool
value string
err error
}
type sliceStringCall struct {
call bool
values []string
err error
}
testCases := map[string]struct {
protocol singleStringCall
targetIP singleStringCall
countries sliceStringCall
cities sliceStringCall
hostnames sliceStringCall
settings Provider
err error
}{
"protocol error": {
protocol: singleStringCall{call: true, err: errDummy},
settings: Provider{
Name: constants.Ipvanish,
},
err: errDummy,
},
"target IP error": {
protocol: singleStringCall{call: true},
targetIP: singleStringCall{call: true, value: "something", err: errDummy},
settings: Provider{
Name: constants.Ipvanish,
},
err: errDummy,
},
"countries error": {
protocol: singleStringCall{call: true},
targetIP: singleStringCall{call: true},
countries: sliceStringCall{call: true, err: errDummy},
settings: Provider{
Name: constants.Ipvanish,
},
err: errDummy,
},
"cities error": {
protocol: singleStringCall{call: true},
targetIP: singleStringCall{call: true},
countries: sliceStringCall{call: true},
cities: sliceStringCall{call: true, err: errDummy},
settings: Provider{
Name: constants.Ipvanish,
},
err: errDummy,
},
"hostnames error": {
protocol: singleStringCall{call: true},
targetIP: singleStringCall{call: true},
countries: sliceStringCall{call: true},
cities: sliceStringCall{call: true},
hostnames: sliceStringCall{call: true, err: errDummy},
settings: Provider{
Name: constants.Ipvanish,
},
err: errDummy,
},
"default settings": {
protocol: singleStringCall{call: true},
targetIP: singleStringCall{call: true},
countries: sliceStringCall{call: true},
cities: sliceStringCall{call: true},
hostnames: sliceStringCall{call: true},
settings: Provider{
Name: constants.Ipvanish,
},
},
"set settings": {
protocol: singleStringCall{call: true, value: constants.TCP},
targetIP: singleStringCall{call: true, value: "1.2.3.4"},
countries: sliceStringCall{call: true, values: []string{"A", "B"}},
cities: sliceStringCall{call: true, values: []string{"C", "D"}},
hostnames: sliceStringCall{call: true, values: []string{"E", "F"}},
settings: Provider{
Name: constants.Ipvanish,
ServerSelection: ServerSelection{
TCP: true,
TargetIP: net.IPv4(1, 2, 3, 4),
Countries: []string{"A", "B"},
Cities: []string{"C", "D"},
Hostnames: []string{"E", "F"},
},
},
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
env := mock_params.NewMockEnv(ctrl)
if testCase.protocol.call {
env.EXPECT().Inside("PROTOCOL", []string{constants.TCP, constants.UDP}, gomock.Any()).
Return(testCase.protocol.value, testCase.protocol.err)
}
if testCase.targetIP.call {
env.EXPECT().Get("OPENVPN_TARGET_IP").
Return(testCase.targetIP.value, testCase.targetIP.err)
}
if testCase.countries.call {
env.EXPECT().CSVInside("COUNTRY", constants.IpvanishCountryChoices()).
Return(testCase.countries.values, testCase.countries.err)
}
if testCase.cities.call {
env.EXPECT().CSVInside("CITY", constants.IpvanishCityChoices()).
Return(testCase.cities.values, testCase.cities.err)
}
if testCase.hostnames.call {
env.EXPECT().CSVInside("SERVER_HOSTNAME", constants.IpvanishHostnameChoices()).
Return(testCase.hostnames.values, testCase.hostnames.err)
}
r := reader{env: env}
var settings Provider
err := settings.readIpvanish(r)
if testCase.err != nil {
require.Error(t, err)
assert.Equal(t, testCase.err.Error(), err.Error())
} else {
assert.NoError(t, err)
}
assert.Equal(t, testCase.settings, settings)
})
}
}

View File

@@ -0,0 +1,55 @@
package configuration
import (
"encoding/pem"
"errors"
"strings"
"github.com/qdm12/gluetun/internal/constants"
)
func readClientKey(r reader) (clientKey string, err error) {
b, err := r.getFromFileOrSecretFile("OPENVPN_CLIENTKEY", constants.ClientKey)
if err != nil {
return "", err
}
return extractClientKey(b)
}
var errDecodePEMBlockClientKey = errors.New("cannot decode PEM block from client key")
func extractClientKey(b []byte) (key string, err error) {
pemBlock, _ := pem.Decode(b)
if pemBlock == nil {
return "", errDecodePEMBlockClientKey
}
parsedBytes := pem.EncodeToMemory(pemBlock)
s := string(parsedBytes)
s = strings.ReplaceAll(s, "\n", "")
s = strings.TrimPrefix(s, "-----BEGIN PRIVATE KEY-----")
s = strings.TrimSuffix(s, "-----END PRIVATE KEY-----")
return s, nil
}
func readClientCertificate(r reader) (clientCertificate string, err error) {
b, err := r.getFromFileOrSecretFile("OPENVPN_CLIENTCRT", constants.ClientCertificate)
if err != nil {
return "", err
}
return extractClientCertificate(b)
}
var errDecodePEMBlockClientCert = errors.New("cannot decode PEM block from client certificate")
func extractClientCertificate(b []byte) (certificate string, err error) {
pemBlock, _ := pem.Decode(b)
if pemBlock == nil {
return "", errDecodePEMBlockClientCert
}
parsedBytes := pem.EncodeToMemory(pemBlock)
s := string(parsedBytes)
s = strings.ReplaceAll(s, "\n", "")
s = strings.TrimPrefix(s, "-----BEGIN CERTIFICATE-----")
s = strings.TrimSuffix(s, "-----END CERTIFICATE-----")
return s, nil
}

View File

@@ -69,7 +69,8 @@ func (settings *Provider) readNordvpn(r reader) (err error) {
}
func readNordVPNServerNumbers(env params.Env) (numbers []uint16, err error) {
possibilities := make([]string, 65537)
const possiblePortsCount = 65537
possibilities := make([]string, possiblePortsCount)
for i := range possibilities {
possibilities[i] = fmt.Sprintf("%d", i)
}

View File

@@ -50,10 +50,14 @@ func (settings *OpenVPN) lines() (lines []string) {
lines = append(lines, indent+lastIndent+"Custom configuration: "+settings.Config)
}
if settings.Provider.Name == "" {
lines = append(lines, indent+lastIndent+"Provider: custom configuration")
} else {
lines = append(lines, indent+lastIndent+"Provider:")
for _, line := range settings.Provider.lines() {
lines = append(lines, indent+indent+line)
}
}
return lines
}
@@ -64,9 +68,9 @@ var (
func (settings *OpenVPN) read(r reader) (err error) {
vpnsp, err := r.env.Inside("VPNSP", []string{
"cyberghost", "fastestvpn", "hidemyass", "ivpn", "mullvad", "nordvpn",
"cyberghost", "fastestvpn", "hidemyass", "ipvanish", "ivpn", "mullvad", "nordvpn",
"privado", "pia", "private internet access", "privatevpn", "protonvpn",
"purevpn", "surfshark", "torguard", "vyprvpn", "windscribe"},
"purevpn", "surfshark", "torguard", constants.VPNUnlimited, "vyprvpn", "windscribe"},
params.Default("private internet access"))
if err != nil {
return err
@@ -81,8 +85,13 @@ func (settings *OpenVPN) read(r reader) (err error) {
if err != nil {
return err
}
customConfig := settings.Config != ""
credentialsRequired := len(settings.Config) == 0
if customConfig {
settings.Provider.Name = ""
}
credentialsRequired := !customConfig && settings.Provider.Name != constants.VPNUnlimited
settings.User, err = r.getFromEnvOrSecretFile("OPENVPN_USER", credentialsRequired, []string{"USER"})
if err != nil {
@@ -106,7 +115,7 @@ func (settings *OpenVPN) read(r reader) (err error) {
return err
}
settings.Verbosity, err = r.env.IntRange("OPENVPN_VERBOSITY", 0, 6, params.Default("1"))
settings.Verbosity, err = r.env.IntRange("OPENVPN_VERBOSITY", 0, 6, params.Default("1")) //nolint:gomnd
if err != nil {
return err
}
@@ -126,20 +135,28 @@ func (settings *OpenVPN) read(r reader) (err error) {
return err
}
mssFix, err := r.env.IntRange("OPENVPN_MSSFIX", 0, 10000, params.Default("0"))
const maxMSSFix = 10000
mssFix, err := r.env.IntRange("OPENVPN_MSSFIX", 0, maxMSSFix, params.Default("0"))
if err != nil {
return err
}
settings.MSSFix = uint16(mssFix)
return settings.readProvider(r)
}
func (settings *OpenVPN) readProvider(r reader) error {
var readProvider func(r reader) error
switch settings.Provider.Name {
case "": // custom config
readProvider = func(r reader) error { return nil }
case constants.Cyberghost:
readProvider = settings.Provider.readCyberghost
case constants.Fastestvpn:
readProvider = settings.Provider.readFastestvpn
case constants.HideMyAss:
readProvider = settings.Provider.readHideMyAss
case constants.Ipvanish:
readProvider = settings.Provider.readIpvanish
case constants.Ivpn:
readProvider = settings.Provider.readIvpn
case constants.Mullvad:
@@ -160,6 +177,8 @@ func (settings *OpenVPN) read(r reader) (err error) {
readProvider = settings.Provider.readSurfshark
case constants.Torguard:
readProvider = settings.Provider.readTorguard
case constants.VPNUnlimited:
readProvider = settings.Provider.readVPNUnlimited
case constants.Vyprvpn:
readProvider = settings.Provider.readVyprvpn
case constants.Windscribe:
@@ -167,6 +186,5 @@ func (settings *OpenVPN) read(r reader) (err error) {
default:
return fmt.Errorf("%w: %s", ErrInvalidVPNProvider, settings.Provider.Name)
}
return readProvider(r)
}

View File

@@ -41,7 +41,8 @@ func Test_OpenVPN_JSON(t *testing.T) {
"custom_port": 0,
"numbers": null,
"encryption_preset": "",
"free_only": false
"free_only": false,
"stream_only": false
},
"extra_config": {
"encryption_preset": "",

View File

@@ -36,6 +36,8 @@ func (settings *Provider) lines() (lines []string) {
providerLines = settings.fastestvpnLines()
case "hidemyass":
providerLines = settings.hideMyAssLines()
case "ipvanish":
providerLines = settings.ipvanishLines()
case "ivpn":
providerLines = settings.ivpnLines()
case "mullvad":
@@ -56,6 +58,8 @@ func (settings *Provider) lines() (lines []string) {
providerLines = settings.surfsharkLines()
case "torguard":
providerLines = settings.torguardLines()
case strings.ToLower(constants.VPNUnlimited):
providerLines = settings.vpnUnlimitedLines()
case "vyprvpn":
providerLines = settings.vyprvpnLines()
case "windscribe":

View File

@@ -73,6 +73,23 @@ func Test_Provider_lines(t *testing.T) {
" |--Hostnames: e, f",
},
},
"ipvanish": {
settings: Provider{
Name: constants.Ipvanish,
ServerSelection: ServerSelection{
Countries: []string{"a", "b"},
Cities: []string{"c", "d"},
Hostnames: []string{"e", "f"},
},
},
lines: []string{
"|--Ipvanish settings:",
" |--Network protocol: udp",
" |--Countries: a, b",
" |--Cities: c, d",
" |--Hostnames: e, f",
},
},
"ivpn": {
settings: Provider{
Name: constants.Ivpn,
@@ -249,6 +266,31 @@ func Test_Provider_lines(t *testing.T) {
" |--Hostnames: e",
},
},
constants.VPNUnlimited: {
settings: Provider{
Name: constants.VPNUnlimited,
ServerSelection: ServerSelection{
Countries: []string{"a", "b"},
Cities: []string{"c", "d"},
Hostnames: []string{"e", "f"},
FreeOnly: true,
StreamOnly: true,
},
ExtraConfigOptions: ExtraConfigOptions{
ClientKey: "a",
},
},
lines: []string{
"|--Vpn Unlimited settings:",
" |--Network protocol: udp",
" |--Countries: a, b",
" |--Cities: c, d",
" |--Hostnames: e, f",
" |--Free servers only",
" |--Stream servers only",
" |--Client key is set",
},
},
"vyprvpn": {
settings: Provider{
Name: constants.Vyprvpn,

View File

@@ -15,9 +15,12 @@ type ServerSelection struct { //nolint:maligned
// Cyberghost
Group string `json:"group"`
Countries []string `json:"countries"` // Fastestvpn, HideMyAss, IVPN, Mullvad, PrivateVPN, Protonvpn, PureVPN
Cities []string `json:"cities"` // HideMyAss, IVPN, Mullvad, PrivateVPN, Protonvpn, PureVPN, Windscribe
Hostnames []string `json:"hostnames"` // Fastestvpn, HideMyAss, IVPN, PrivateVPN, Windscribe, Privado, Protonvpn
// Fastestvpn, HideMyAss, IPVanish, IVPN, Mullvad, PrivateVPN, Protonvpn, PureVPN, VPNUnlimited
Countries []string `json:"countries"`
// HideMyAss, IPVanish, IVPN, Mullvad, PrivateVPN, Protonvpn, PureVPN, VPNUnlimited, Windscribe
Cities []string `json:"cities"`
// Fastestvpn, HideMyAss, IPVanish, IVPN, PrivateVPN, Windscribe, Privado, Protonvpn, VPNUnlimited
Hostnames []string `json:"hostnames"`
Names []string `json:"names"` // Protonvpn
// Mullvad
@@ -35,11 +38,14 @@ type ServerSelection struct { //nolint:maligned
// ProtonVPN
FreeOnly bool `json:"free_only"`
// VPNUnlimited
StreamOnly bool `json:"stream_only"`
}
type ExtraConfigOptions struct {
ClientCertificate string `json:"-"` // Cyberghost
ClientKey string `json:"-"` // Cyberghost
ClientKey string `json:"-"` // Cyberghost, VPNUnlimited
EncryptionPreset string `json:"encryption_preset"` // PIA
OpenVPNIPv6 bool `json:"openvpn_ipv6"` // Mullvad
}

View File

@@ -1,6 +1,8 @@
package configuration
import (
"errors"
"fmt"
"strings"
"github.com/qdm12/golibs/logging"
@@ -43,6 +45,18 @@ func (settings *Settings) lines() (lines []string) {
return lines
}
var (
ErrOpenvpn = errors.New("cannot read Openvpn settings")
ErrSystem = errors.New("cannot read System settings")
ErrDNS = errors.New("cannot read DNS settings")
ErrFirewall = errors.New("cannot read firewall settings")
ErrHTTPProxy = errors.New("cannot read HTTP proxy settings")
ErrShadowsocks = errors.New("cannot read Shadowsocks settings")
ErrControlServer = errors.New("cannot read control server settings")
ErrUpdater = errors.New("cannot read Updater settings")
ErrPublicIP = errors.New("cannot read Public IP getter settings")
)
// Read obtains all configuration options for the program and returns an error as soon
// as an error is encountered reading them.
func (settings *Settings) Read(env params.Env, os os.OS, logger logging.Logger) (err error) {
@@ -54,35 +68,35 @@ func (settings *Settings) Read(env params.Env, os os.OS, logger logging.Logger)
}
if err := settings.OpenVPN.read(r); err != nil {
return err
return fmt.Errorf("%w: %s", ErrOpenvpn, err)
}
if err := settings.System.read(r); err != nil {
return err
return fmt.Errorf("%w: %s", ErrSystem, err)
}
if err := settings.DNS.read(r); err != nil {
return err
return fmt.Errorf("%w: %s", ErrDNS, err)
}
if err := settings.Firewall.read(r); err != nil {
return err
return fmt.Errorf("%w: %s", ErrFirewall, err)
}
if err := settings.HTTPProxy.read(r); err != nil {
return err
return fmt.Errorf("%w: %s", ErrHTTPProxy, err)
}
if err := settings.ShadowSocks.read(r); err != nil {
return err
return fmt.Errorf("%w: %s", ErrShadowsocks, err)
}
if err := settings.ControlServer.read(r); err != nil {
return err
return fmt.Errorf("%w: %s", ErrControlServer, err)
}
if err := settings.Updater.read(r); err != nil {
return err
return fmt.Errorf("%w: %s", ErrUpdater, err)
}
if ip := settings.DNS.PlaintextAddress; ip != nil {
@@ -90,7 +104,7 @@ func (settings *Settings) Read(env params.Env, os os.OS, logger logging.Logger)
}
if err := settings.PublicIP.read(r); err != nil {
return err
return fmt.Errorf("%w: %s", ErrPublicIP, err)
}
return nil

View File

@@ -32,13 +32,14 @@ func (settings *System) lines() (lines []string) {
}
func (settings *System) read(r reader) (err error) {
settings.PUID, err = r.env.IntRange("PUID", 0, 65535, params.Default("1000"),
const maxID = 65535
settings.PUID, err = r.env.IntRange("PUID", 0, maxID, params.Default("1000"),
params.RetroKeys([]string{"UID"}, r.onRetroActive))
if err != nil {
return err
}
settings.PGID, err = r.env.IntRange("PGID", 0, 65535, params.Default("1000"),
settings.PGID, err = r.env.IntRange("PGID", 0, maxID, params.Default("1000"),
params.RetroKeys([]string{"GID"}, r.onRetroActive))
if err != nil {
return err

View File

@@ -43,7 +43,7 @@ func (settings *Provider) readTorguard(r reader) (err error) {
return err
}
settings.ServerSelection.Hostnames, err = r.env.CSVInside("SERVER_HOSTNAME", constants.TorguardHostnamesChoices())
settings.ServerSelection.Hostnames, err = r.env.CSVInside("SERVER_HOSTNAME", constants.TorguardHostnameChoices())
if err != nil {
return err
}

View File

@@ -29,19 +29,19 @@ func (settings *DNS) readUnbound(r reader) (err error) {
return err
}
verbosityLevel, err := r.env.IntRange("DOT_VERBOSITY", 0, 5, params.Default("1"))
verbosityLevel, err := r.env.IntRange("DOT_VERBOSITY", 0, 5, params.Default("1")) //nolint:gomnd
if err != nil {
return err
}
settings.Unbound.VerbosityLevel = uint8(verbosityLevel)
verbosityDetailsLevel, err := r.env.IntRange("DOT_VERBOSITY_DETAILS", 0, 4, params.Default("0"))
verbosityDetailsLevel, err := r.env.IntRange("DOT_VERBOSITY_DETAILS", 0, 4, params.Default("0")) //nolint:gomnd
if err != nil {
return err
}
settings.Unbound.VerbosityDetailsLevel = uint8(verbosityDetailsLevel)
validationLogLevel, err := r.env.IntRange("DOT_VALIDATION_LOGLEVEL", 0, 2, params.Default("0"))
validationLogLevel, err := r.env.IntRange("DOT_VALIDATION_LOGLEVEL", 0, 2, params.Default("0")) //nolint:gomnd
if err != nil {
return err
}

View File

@@ -13,6 +13,7 @@ type Updater struct {
Cyberghost bool `json:"cyberghost"`
Fastestvpn bool `json:"fastestvpn"`
HideMyAss bool `json:"hidemyass"`
Ipvanish bool `json:"ipvanish"`
Ivpn bool `json:"ivpn"`
Mullvad bool `json:"mullvad"`
Nordvpn bool `json:"nordvpn"`
@@ -23,6 +24,7 @@ type Updater struct {
Purevpn bool `json:"purevpn"`
Surfshark bool `json:"surfshark"`
Torguard bool `json:"torguard"`
VPNUnlimited bool `json:"vpnunlimited"`
Vyprvpn bool `json:"vyprvpn"`
Windscribe bool `json:"windscribe"`
// The two below should be used in CLI mode only
@@ -49,6 +51,7 @@ func (settings *Updater) lines() (lines []string) {
func (settings *Updater) read(r reader) (err error) {
settings.Cyberghost = true
settings.HideMyAss = true
settings.Ipvanish = true
settings.Ivpn = true
settings.Mullvad = true
settings.Nordvpn = true
@@ -60,6 +63,7 @@ func (settings *Updater) read(r reader) (err error) {
settings.Purevpn = true
settings.Surfshark = true
settings.Torguard = true
settings.VPNUnlimited = true
settings.Vyprvpn = true
settings.Windscribe = true
settings.Stdout = false

View File

@@ -0,0 +1,85 @@
package configuration
import (
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/golibs/params"
)
func (settings *Provider) vpnUnlimitedLines() (lines []string) {
if len(settings.ServerSelection.Countries) > 0 {
lines = append(lines, lastIndent+"Countries: "+commaJoin(settings.ServerSelection.Countries))
}
if len(settings.ServerSelection.Cities) > 0 {
lines = append(lines, lastIndent+"Cities: "+commaJoin(settings.ServerSelection.Cities))
}
if len(settings.ServerSelection.Hostnames) > 0 {
lines = append(lines, lastIndent+"Hostnames: "+commaJoin(settings.ServerSelection.Hostnames))
}
if settings.ServerSelection.FreeOnly {
lines = append(lines, lastIndent+"Free servers only")
}
if settings.ServerSelection.StreamOnly {
lines = append(lines, lastIndent+"Stream servers only")
}
if settings.ExtraConfigOptions.ClientKey != "" {
lines = append(lines, lastIndent+"Client key is set")
}
return lines
}
func (settings *Provider) readVPNUnlimited(r reader) (err error) {
settings.Name = constants.VPNUnlimited
settings.ServerSelection.TCP, err = readProtocol(r.env)
if err != nil {
return err
}
settings.ServerSelection.TargetIP, err = readTargetIP(r.env)
if err != nil {
return err
}
settings.ExtraConfigOptions.ClientKey, err = readClientKey(r)
if err != nil {
return err
}
settings.ExtraConfigOptions.ClientCertificate, err = readClientCertificate(r)
if err != nil {
return err
}
settings.ServerSelection.Countries, err = r.env.CSVInside("COUNTRY", constants.VPNUnlimitedCountryChoices())
if err != nil {
return err
}
settings.ServerSelection.Cities, err = r.env.CSVInside("CITY", constants.VPNUnlimitedCityChoices())
if err != nil {
return err
}
settings.ServerSelection.Hostnames, err = r.env.CSVInside("SERVER_HOSTNAME", constants.VPNUnlimitedHostnameChoices())
if err != nil {
return err
}
settings.ServerSelection.FreeOnly, err = r.env.YesNo("FREE_ONLY", params.Default("no"))
if err != nil {
return err
}
settings.ServerSelection.StreamOnly, err = r.env.YesNo("STREAM_ONLY", params.Default("no"))
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,42 @@
package configuration
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_Provider_vpnUnlimitedLines(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
settings Provider
lines []string
}{
"empty settings": {},
"full settings": {
settings: Provider{
ServerSelection: ServerSelection{
Countries: []string{"A", "B"},
Cities: []string{"C", "D"},
Hostnames: []string{"E", "F"},
},
},
lines: []string{
"|--Countries: A, B",
"|--Cities: C, D",
"|--Hostnames: E, F",
},
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
lines := testCase.settings.vpnUnlimitedLines()
assert.Equal(t, testCase.lines, lines)
})
}
}

View File

@@ -1,5 +1,6 @@
package constants
const (
// HealthcheckAddress is the default listening address for the healthcheck server.
HealthcheckAddress = "127.0.0.1:9999"
)

View File

@@ -136,6 +136,7 @@ func CountryCodes() map[string]string {
"mg": "Madagascar",
"mw": "Malawi",
"my": "Malaysia",
"mys": "Kuala Lumpur",
"mv": "Maldives",
"ml": "Mali",
"mt": "Malta",

View File

@@ -43,134 +43,184 @@ func CyberghostHostnameChoices() (choices []string) {
// of the Cyberghost server.
func CyberghostServers() []models.CyberghostServer {
return []models.CyberghostServer{
{Region: "Albania", Group: "Premium UDP Europe", Hostname: "87-1-al.cg-dialup.net", IPs: []net.IP{{31, 171, 155, 3}, {31, 171, 155, 4}, {31, 171, 155, 5}, {31, 171, 155, 6}, {31, 171, 155, 7}, {31, 171, 155, 8}, {31, 171, 155, 10}, {31, 171, 155, 11}, {31, 171, 155, 13}, {31, 171, 155, 14}}},
{Region: "Algeria", Group: "Premium TCP Europe", Hostname: "97-1-dz.cg-dialup.net", IPs: []net.IP{{176, 125, 228, 131}, {176, 125, 228, 132}, {176, 125, 228, 134}, {176, 125, 228, 135}, {176, 125, 228, 136}, {176, 125, 228, 138}, {176, 125, 228, 141}, {176, 125, 228, 142}, {176, 125, 228, 143}, {176, 125, 228, 144}}},
{Region: "Argentina", Group: "Premium TCP USA", Hostname: "93-1-ar.cg-dialup.net", IPs: []net.IP{{190, 106, 130, 15}, {190, 106, 130, 18}, {190, 106, 130, 20}, {190, 106, 130, 22}, {190, 106, 130, 23}, {190, 106, 130, 36}, {190, 106, 130, 43}, {190, 106, 130, 44}, {190, 106, 130, 45}, {190, 106, 130, 52}}},
{Region: "Argentina", Group: "Premium UDP USA", Hostname: "94-1-ar.cg-dialup.net", IPs: []net.IP{{190, 106, 130, 15}, {190, 106, 130, 19}, {190, 106, 130, 20}, {190, 106, 130, 21}, {190, 106, 130, 34}, {190, 106, 130, 36}, {190, 106, 130, 38}, {190, 106, 130, 42}, {190, 106, 130, 43}, {190, 106, 130, 52}}},
{Region: "Armenia", Group: "Premium TCP Europe", Hostname: "97-1-am.cg-dialup.net", IPs: []net.IP{{185, 253, 160, 131}, {185, 253, 160, 132}, {185, 253, 160, 134}, {185, 253, 160, 138}, {185, 253, 160, 139}, {185, 253, 160, 140}, {185, 253, 160, 141}, {185, 253, 160, 142}, {185, 253, 160, 143}, {185, 253, 160, 144}}},
{Region: "Armenia", Group: "Premium UDP Europe", Hostname: "87-1-am.cg-dialup.net", IPs: []net.IP{{185, 253, 160, 131}, {185, 253, 160, 132}, {185, 253, 160, 134}, {185, 253, 160, 136}, {185, 253, 160, 137}, {185, 253, 160, 138}, {185, 253, 160, 139}, {185, 253, 160, 140}, {185, 253, 160, 141}, {185, 253, 160, 143}}},
{Region: "Australia", Group: "Premium TCP Asia", Hostname: "96-1-au.cg-dialup.net", IPs: []net.IP{{43, 242, 68, 108}, {202, 60, 80, 5}, {202, 60, 80, 41}, {202, 60, 80, 58}, {202, 60, 91, 204}, {202, 60, 91, 213}, {202, 60, 91, 221}, {202, 60, 91, 222}, {202, 60, 91, 225}, {202, 60, 91, 234}}},
{Region: "Australia", Group: "Premium UDP Asia", Hostname: "95-1-au.cg-dialup.net", IPs: []net.IP{{43, 242, 68, 77}, {43, 242, 68, 95}, {43, 242, 68, 108}, {202, 60, 80, 20}, {202, 60, 80, 31}, {202, 60, 80, 47}, {202, 60, 91, 199}, {202, 60, 91, 222}, {202, 60, 91, 226}, {202, 60, 91, 253}}},
{Region: "Austria", Group: "Premium UDP Europe", Hostname: "87-1-at.cg-dialup.net", IPs: []net.IP{{37, 19, 223, 112}, {37, 19, 223, 119}, {37, 120, 155, 100}, {37, 120, 155, 102}, {37, 120, 155, 104}, {37, 120, 155, 110}, {89, 187, 168, 166}, {89, 187, 168, 174}, {89, 187, 168, 175}, {89, 187, 168, 177}}},
{Region: "Bahamas", Group: "Premium TCP USA", Hostname: "93-1-bs.cg-dialup.net", IPs: []net.IP{{95, 181, 238, 132}, {95, 181, 238, 133}, {95, 181, 238, 137}, {95, 181, 238, 139}, {95, 181, 238, 142}, {95, 181, 238, 144}, {95, 181, 238, 145}, {95, 181, 238, 147}, {95, 181, 238, 148}, {95, 181, 238, 153}}},
{Region: "Bangladesh", Group: "Premium TCP Asia", Hostname: "96-1-bd.cg-dialup.net", IPs: []net.IP{{84, 252, 93, 131}, {84, 252, 93, 132}, {84, 252, 93, 133}, {84, 252, 93, 135}, {84, 252, 93, 138}, {84, 252, 93, 140}, {84, 252, 93, 142}, {84, 252, 93, 143}, {84, 252, 93, 144}, {84, 252, 93, 145}}},
{Region: "Bangladesh", Group: "Premium UDP Asia", Hostname: "95-1-bd.cg-dialup.net", IPs: []net.IP{{84, 252, 93, 131}, {84, 252, 93, 132}, {84, 252, 93, 133}, {84, 252, 93, 134}, {84, 252, 93, 135}, {84, 252, 93, 137}, {84, 252, 93, 139}, {84, 252, 93, 141}, {84, 252, 93, 143}, {84, 252, 93, 145}}},
{Region: "Belarus", Group: "Premium UDP Europe", Hostname: "87-1-by.cg-dialup.net", IPs: []net.IP{{45, 132, 194, 7}, {45, 132, 194, 25}, {45, 132, 194, 33}, {45, 132, 194, 36}, {45, 132, 194, 38}, {45, 132, 194, 43}, {45, 132, 194, 44}, {45, 132, 194, 45}, {45, 132, 194, 48}, {45, 132, 194, 49}}},
{Region: "Belgium", Group: "Premium TCP Europe", Hostname: "97-1-be.cg-dialup.net", IPs: []net.IP{{5, 253, 205, 26}, {37, 120, 143, 54}, {37, 120, 143, 57}, {185, 210, 217, 52}, {185, 232, 21, 115}, {193, 9, 114, 212}, {193, 9, 114, 227}, {193, 9, 114, 230}, {193, 9, 114, 249}, {194, 110, 115, 233}}},
{Region: "Albania", Group: "Premium TCP Europe", Hostname: "97-1-al.cg-dialup.net", IPs: []net.IP{{31, 171, 155, 3}, {31, 171, 155, 4}, {31, 171, 155, 7}, {31, 171, 155, 8}, {31, 171, 155, 9}, {31, 171, 155, 10}, {31, 171, 155, 11}, {31, 171, 155, 12}, {31, 171, 155, 13}, {31, 171, 155, 14}}},
{Region: "Albania", Group: "Premium UDP Europe", Hostname: "87-1-al.cg-dialup.net", IPs: []net.IP{{31, 171, 155, 4}, {31, 171, 155, 5}, {31, 171, 155, 6}, {31, 171, 155, 7}, {31, 171, 155, 8}, {31, 171, 155, 9}, {31, 171, 155, 10}, {31, 171, 155, 11}, {31, 171, 155, 13}, {31, 171, 155, 14}}},
{Region: "Algeria", Group: "Premium TCP Europe", Hostname: "97-1-dz.cg-dialup.net", IPs: []net.IP{{176, 125, 228, 132}, {176, 125, 228, 134}, {176, 125, 228, 135}, {176, 125, 228, 136}, {176, 125, 228, 137}, {176, 125, 228, 138}, {176, 125, 228, 139}, {176, 125, 228, 140}, {176, 125, 228, 141}, {176, 125, 228, 142}}},
{Region: "Algeria", Group: "Premium UDP Europe", Hostname: "87-1-dz.cg-dialup.net", IPs: []net.IP{{176, 125, 228, 131}, {176, 125, 228, 133}, {176, 125, 228, 134}, {176, 125, 228, 136}, {176, 125, 228, 137}, {176, 125, 228, 139}, {176, 125, 228, 140}, {176, 125, 228, 141}, {176, 125, 228, 142}, {176, 125, 228, 143}}},
{Region: "Andorra", Group: "Premium TCP Europe", Hostname: "97-1-ad.cg-dialup.net", IPs: []net.IP{{188, 241, 82, 137}, {188, 241, 82, 138}, {188, 241, 82, 140}, {188, 241, 82, 142}, {188, 241, 82, 147}, {188, 241, 82, 155}, {188, 241, 82, 159}, {188, 241, 82, 160}, {188, 241, 82, 161}, {188, 241, 82, 166}}},
{Region: "Andorra", Group: "Premium UDP Europe", Hostname: "87-1-ad.cg-dialup.net", IPs: []net.IP{{188, 241, 82, 133}, {188, 241, 82, 134}, {188, 241, 82, 136}, {188, 241, 82, 137}, {188, 241, 82, 146}, {188, 241, 82, 153}, {188, 241, 82, 155}, {188, 241, 82, 160}, {188, 241, 82, 164}, {188, 241, 82, 168}}},
{Region: "Argentina", Group: "Premium TCP USA", Hostname: "93-1-ar.cg-dialup.net", IPs: []net.IP{{146, 70, 39, 4}, {146, 70, 39, 9}, {146, 70, 39, 15}, {146, 70, 39, 19}, {146, 70, 39, 135}, {146, 70, 39, 136}, {146, 70, 39, 139}, {146, 70, 39, 142}, {146, 70, 39, 143}, {146, 70, 39, 145}}},
{Region: "Argentina", Group: "Premium UDP USA", Hostname: "94-1-ar.cg-dialup.net", IPs: []net.IP{{146, 70, 39, 3}, {146, 70, 39, 5}, {146, 70, 39, 6}, {146, 70, 39, 8}, {146, 70, 39, 11}, {146, 70, 39, 12}, {146, 70, 39, 131}, {146, 70, 39, 134}, {146, 70, 39, 142}, {146, 70, 39, 143}}},
{Region: "Armenia", Group: "Premium TCP Europe", Hostname: "97-1-am.cg-dialup.net", IPs: []net.IP{{185, 253, 160, 131}, {185, 253, 160, 134}, {185, 253, 160, 136}, {185, 253, 160, 137}, {185, 253, 160, 138}, {185, 253, 160, 139}, {185, 253, 160, 140}, {185, 253, 160, 141}, {185, 253, 160, 142}, {185, 253, 160, 143}}},
{Region: "Armenia", Group: "Premium UDP Europe", Hostname: "87-1-am.cg-dialup.net", IPs: []net.IP{{185, 253, 160, 131}, {185, 253, 160, 132}, {185, 253, 160, 133}, {185, 253, 160, 134}, {185, 253, 160, 135}, {185, 253, 160, 136}, {185, 253, 160, 137}, {185, 253, 160, 141}, {185, 253, 160, 142}, {185, 253, 160, 144}}},
{Region: "Australia", Group: "Premium TCP Asia", Hostname: "96-1-au.cg-dialup.net", IPs: []net.IP{{154, 16, 81, 22}, {181, 214, 215, 7}, {181, 214, 215, 15}, {181, 214, 215, 18}, {191, 101, 210, 15}, {191, 101, 210, 50}, {191, 101, 210, 60}, {202, 60, 80, 78}, {202, 60, 80, 82}, {202, 60, 80, 102}}},
{Region: "Australia", Group: "Premium UDP Asia", Hostname: "95-1-au.cg-dialup.net", IPs: []net.IP{{181, 214, 215, 4}, {181, 214, 215, 16}, {191, 101, 210, 18}, {191, 101, 210, 21}, {191, 101, 210, 36}, {191, 101, 210, 58}, {191, 101, 210, 60}, {202, 60, 80, 74}, {202, 60, 80, 106}, {202, 60, 80, 124}}},
{Region: "Austria", Group: "Premium TCP Europe", Hostname: "97-1-at.cg-dialup.net", IPs: []net.IP{{37, 19, 223, 9}, {37, 19, 223, 16}, {37, 19, 223, 113}, {37, 19, 223, 205}, {37, 19, 223, 211}, {37, 19, 223, 218}, {37, 19, 223, 223}, {37, 19, 223, 245}, {37, 120, 155, 104}, {89, 187, 168, 174}}},
{Region: "Austria", Group: "Premium UDP Europe", Hostname: "87-1-at.cg-dialup.net", IPs: []net.IP{{37, 19, 223, 202}, {37, 19, 223, 205}, {37, 19, 223, 229}, {37, 19, 223, 239}, {37, 19, 223, 241}, {37, 19, 223, 243}, {37, 120, 155, 103}, {89, 187, 168, 160}, {89, 187, 168, 174}, {89, 187, 168, 181}}},
{Region: "Bahamas", Group: "Premium TCP USA", Hostname: "93-1-bs.cg-dialup.net", IPs: []net.IP{{95, 181, 238, 131}, {95, 181, 238, 136}, {95, 181, 238, 142}, {95, 181, 238, 144}, {95, 181, 238, 146}, {95, 181, 238, 147}, {95, 181, 238, 148}, {95, 181, 238, 152}, {95, 181, 238, 153}, {95, 181, 238, 155}}},
{Region: "Bahamas", Group: "Premium UDP USA", Hostname: "94-1-bs.cg-dialup.net", IPs: []net.IP{{95, 181, 238, 131}, {95, 181, 238, 138}, {95, 181, 238, 140}, {95, 181, 238, 141}, {95, 181, 238, 146}, {95, 181, 238, 147}, {95, 181, 238, 148}, {95, 181, 238, 151}, {95, 181, 238, 153}, {95, 181, 238, 155}}},
{Region: "Bangladesh", Group: "Premium TCP Asia", Hostname: "96-1-bd.cg-dialup.net", IPs: []net.IP{{84, 252, 93, 132}, {84, 252, 93, 133}, {84, 252, 93, 135}, {84, 252, 93, 138}, {84, 252, 93, 139}, {84, 252, 93, 141}, {84, 252, 93, 142}, {84, 252, 93, 143}, {84, 252, 93, 144}, {84, 252, 93, 145}}},
{Region: "Bangladesh", Group: "Premium UDP Asia", Hostname: "95-1-bd.cg-dialup.net", IPs: []net.IP{{84, 252, 93, 131}, {84, 252, 93, 133}, {84, 252, 93, 134}, {84, 252, 93, 135}, {84, 252, 93, 136}, {84, 252, 93, 139}, {84, 252, 93, 140}, {84, 252, 93, 141}, {84, 252, 93, 143}, {84, 252, 93, 145}}},
{Region: "Belarus", Group: "Premium TCP Europe", Hostname: "97-1-by.cg-dialup.net", IPs: []net.IP{{45, 132, 194, 5}, {45, 132, 194, 6}, {45, 132, 194, 23}, {45, 132, 194, 24}, {45, 132, 194, 25}, {45, 132, 194, 27}, {45, 132, 194, 30}, {45, 132, 194, 35}, {45, 132, 194, 44}, {45, 132, 194, 49}}},
{Region: "Belarus", Group: "Premium UDP Europe", Hostname: "87-1-by.cg-dialup.net", IPs: []net.IP{{45, 132, 194, 6}, {45, 132, 194, 8}, {45, 132, 194, 9}, {45, 132, 194, 11}, {45, 132, 194, 15}, {45, 132, 194, 19}, {45, 132, 194, 20}, {45, 132, 194, 23}, {45, 132, 194, 24}, {45, 132, 194, 26}}},
{Region: "Belgium", Group: "Premium TCP Europe", Hostname: "97-1-be.cg-dialup.net", IPs: []net.IP{{37, 120, 143, 165}, {37, 120, 143, 166}, {185, 210, 217, 10}, {185, 210, 217, 248}, {193, 9, 114, 211}, {193, 9, 114, 220}, {194, 110, 115, 195}, {194, 110, 115, 199}, {194, 110, 115, 205}, {194, 110, 115, 238}}},
{Region: "Belgium", Group: "Premium UDP Europe", Hostname: "87-1-be.cg-dialup.net", IPs: []net.IP{{37, 120, 143, 163}, {37, 120, 143, 167}, {185, 210, 217, 9}, {185, 210, 217, 13}, {185, 210, 217, 55}, {185, 210, 217, 251}, {185, 232, 21, 120}, {194, 110, 115, 214}, {194, 110, 115, 218}, {194, 110, 115, 236}}},
{Region: "Bosnia and Herzegovina", Group: "Premium TCP Europe", Hostname: "97-1-ba.cg-dialup.net", IPs: []net.IP{{185, 99, 3, 57}, {185, 99, 3, 58}, {185, 99, 3, 72}, {185, 99, 3, 73}, {185, 99, 3, 74}, {185, 99, 3, 130}, {185, 99, 3, 131}, {185, 99, 3, 134}, {185, 99, 3, 135}, {185, 99, 3, 136}}},
{Region: "Bosnia and Herzegovina", Group: "Premium UDP Europe", Hostname: "87-1-ba.cg-dialup.net", IPs: []net.IP{{185, 99, 3, 57}, {185, 99, 3, 58}, {185, 99, 3, 72}, {185, 99, 3, 73}, {185, 99, 3, 74}, {185, 99, 3, 130}, {185, 99, 3, 131}, {185, 99, 3, 134}, {185, 99, 3, 135}, {185, 99, 3, 136}}},
{Region: "Brazil", Group: "Premium UDP USA", Hostname: "94-1-br.cg-dialup.net", IPs: []net.IP{{188, 241, 177, 11}, {188, 241, 177, 13}, {188, 241, 177, 19}, {188, 241, 177, 20}, {188, 241, 177, 21}, {188, 241, 177, 29}, {188, 241, 177, 30}, {188, 241, 177, 46}, {188, 241, 177, 147}, {188, 241, 177, 156}}},
{Region: "Bulgaria", Group: "Premium TCP Europe", Hostname: "97-1-bg.cg-dialup.net", IPs: []net.IP{{37, 120, 152, 99}, {37, 120, 152, 100}, {37, 120, 152, 101}, {37, 120, 152, 102}, {37, 120, 152, 104}, {37, 120, 152, 105}, {37, 120, 152, 106}, {37, 120, 152, 108}, {37, 120, 152, 109}, {37, 120, 152, 110}}},
{Region: "Bulgaria", Group: "Premium UDP Europe", Hostname: "87-1-bg.cg-dialup.net", IPs: []net.IP{{37, 120, 152, 99}, {37, 120, 152, 100}, {37, 120, 152, 101}, {37, 120, 152, 103}, {37, 120, 152, 104}, {37, 120, 152, 106}, {37, 120, 152, 107}, {37, 120, 152, 108}, {37, 120, 152, 109}, {37, 120, 152, 110}}},
{Region: "Cambodia", Group: "Premium TCP Asia", Hostname: "96-1-kh.cg-dialup.net", IPs: []net.IP{{188, 215, 235, 38}, {188, 215, 235, 41}, {188, 215, 235, 42}, {188, 215, 235, 47}, {188, 215, 235, 48}, {188, 215, 235, 51}, {188, 215, 235, 52}, {188, 215, 235, 54}, {188, 215, 235, 56}, {188, 215, 235, 57}}},
{Region: "Canada", Group: "Premium TCP USA", Hostname: "93-1-ca.cg-dialup.net", IPs: []net.IP{{104, 200, 151, 17}, {104, 200, 151, 47}, {104, 200, 151, 74}, {104, 200, 151, 89}, {104, 200, 151, 163}, {172, 98, 89, 147}, {172, 98, 89, 148}, {172, 98, 89, 164}, {172, 98, 89, 171}, {172, 98, 89, 182}}},
{Region: "Canada", Group: "Premium UDP USA", Hostname: "94-1-ca.cg-dialup.net", IPs: []net.IP{{66, 115, 142, 190}, {104, 200, 151, 86}, {104, 200, 151, 103}, {104, 200, 151, 127}, {104, 200, 151, 128}, {104, 200, 151, 139}, {172, 98, 89, 143}, {172, 98, 89, 150}, {172, 98, 89, 156}, {172, 98, 89, 180}}},
{Region: "Chile", Group: "Premium TCP USA", Hostname: "93-1-cl.cg-dialup.net", IPs: []net.IP{{146, 70, 11, 3}, {146, 70, 11, 4}, {146, 70, 11, 5}, {146, 70, 11, 6}, {146, 70, 11, 8}, {146, 70, 11, 9}, {146, 70, 11, 11}, {146, 70, 11, 12}, {146, 70, 11, 13}, {146, 70, 11, 14}}},
{Region: "Chile", Group: "Premium UDP USA", Hostname: "94-1-cl.cg-dialup.net", IPs: []net.IP{{146, 70, 11, 3}, {146, 70, 11, 4}, {146, 70, 11, 7}, {146, 70, 11, 8}, {146, 70, 11, 9}, {146, 70, 11, 10}, {146, 70, 11, 11}, {146, 70, 11, 12}, {146, 70, 11, 13}, {146, 70, 11, 14}}},
{Region: "China", Group: "Premium TCP Asia", Hostname: "96-1-cn.cg-dialup.net", IPs: []net.IP{{188, 241, 80, 131}, {188, 241, 80, 132}, {188, 241, 80, 133}, {188, 241, 80, 134}, {188, 241, 80, 135}, {188, 241, 80, 136}, {188, 241, 80, 137}, {188, 241, 80, 138}, {188, 241, 80, 140}, {188, 241, 80, 141}}},
{Region: "Colombia", Group: "Premium UDP USA", Hostname: "94-1-co.cg-dialup.net", IPs: []net.IP{{146, 70, 9, 3}, {146, 70, 9, 4}, {146, 70, 9, 5}, {146, 70, 9, 6}, {146, 70, 9, 7}, {146, 70, 9, 8}, {146, 70, 9, 9}, {146, 70, 9, 10}, {146, 70, 9, 11}, {146, 70, 9, 14}}},
{Region: "Costa Rica", Group: "Premium TCP USA", Hostname: "93-1-cr.cg-dialup.net", IPs: []net.IP{{146, 70, 10, 3}, {146, 70, 10, 4}, {146, 70, 10, 5}, {146, 70, 10, 6}, {146, 70, 10, 7}, {146, 70, 10, 8}, {146, 70, 10, 9}, {146, 70, 10, 11}, {146, 70, 10, 12}, {146, 70, 10, 14}}},
{Region: "Costa Rica", Group: "Premium UDP USA", Hostname: "94-1-cr.cg-dialup.net", IPs: []net.IP{{146, 70, 10, 3}, {146, 70, 10, 4}, {146, 70, 10, 5}, {146, 70, 10, 7}, {146, 70, 10, 8}, {146, 70, 10, 9}, {146, 70, 10, 11}, {146, 70, 10, 12}, {146, 70, 10, 13}, {146, 70, 10, 14}}},
{Region: "Croatia", Group: "Premium TCP Europe", Hostname: "97-1-hr.cg-dialup.net", IPs: []net.IP{{146, 70, 8, 3}, {146, 70, 8, 4}, {146, 70, 8, 5}, {146, 70, 8, 7}, {146, 70, 8, 8}, {146, 70, 8, 11}, {146, 70, 8, 12}, {146, 70, 8, 13}, {146, 70, 8, 14}, {146, 70, 8, 16}}},
{Region: "Croatia", Group: "Premium UDP Europe", Hostname: "87-1-hr.cg-dialup.net", IPs: []net.IP{{146, 70, 8, 3}, {146, 70, 8, 4}, {146, 70, 8, 5}, {146, 70, 8, 6}, {146, 70, 8, 8}, {146, 70, 8, 10}, {146, 70, 8, 11}, {146, 70, 8, 12}, {146, 70, 8, 15}, {146, 70, 8, 16}}},
{Region: "Cyprus", Group: "Premium TCP Europe", Hostname: "97-1-cy.cg-dialup.net", IPs: []net.IP{{185, 253, 162, 131}, {185, 253, 162, 132}, {185, 253, 162, 133}, {185, 253, 162, 134}, {185, 253, 162, 135}, {185, 253, 162, 137}, {185, 253, 162, 141}, {185, 253, 162, 142}, {185, 253, 162, 143}, {185, 253, 162, 144}}},
{Region: "Cyprus", Group: "Premium UDP Europe", Hostname: "87-1-cy.cg-dialup.net", IPs: []net.IP{{185, 253, 162, 131}, {185, 253, 162, 132}, {185, 253, 162, 133}, {185, 253, 162, 134}, {185, 253, 162, 135}, {185, 253, 162, 137}, {185, 253, 162, 138}, {185, 253, 162, 139}, {185, 253, 162, 141}, {185, 253, 162, 143}}},
{Region: "Czech Republic", Group: "Premium UDP Europe", Hostname: "87-1-cz.cg-dialup.net", IPs: []net.IP{{195, 181, 161, 3}, {195, 181, 161, 4}, {195, 181, 161, 7}, {195, 181, 161, 9}, {195, 181, 161, 11}, {195, 181, 161, 19}, {195, 181, 161, 20}, {195, 181, 161, 21}, {195, 181, 161, 22}, {195, 181, 161, 24}}},
{Region: "Denmark", Group: "Premium TCP Europe", Hostname: "97-1-dk.cg-dialup.net", IPs: []net.IP{{37, 120, 145, 89}, {37, 120, 145, 90}, {37, 120, 194, 42}, {37, 120, 194, 45}, {37, 120, 194, 55}, {95, 174, 65, 163}, {95, 174, 65, 166}, {185, 206, 224, 229}, {185, 206, 224, 234}, {185, 206, 224, 254}}},
{Region: "Egypt", Group: "Premium TCP Europe", Hostname: "97-1-eg.cg-dialup.net", IPs: []net.IP{{188, 214, 122, 35}, {188, 214, 122, 42}, {188, 214, 122, 48}, {188, 214, 122, 49}, {188, 214, 122, 58}, {188, 214, 122, 61}, {188, 214, 122, 62}, {188, 214, 122, 68}, {188, 214, 122, 73}, {188, 214, 122, 76}}},
{Region: "Egypt", Group: "Premium UDP Europe", Hostname: "87-1-eg.cg-dialup.net", IPs: []net.IP{{188, 214, 122, 35}, {188, 214, 122, 36}, {188, 214, 122, 42}, {188, 214, 122, 47}, {188, 214, 122, 51}, {188, 214, 122, 52}, {188, 214, 122, 58}, {188, 214, 122, 62}, {188, 214, 122, 69}, {188, 214, 122, 78}}},
{Region: "Estonia", Group: "Premium TCP Europe", Hostname: "97-1-ee.cg-dialup.net", IPs: []net.IP{{95, 153, 32, 83}, {95, 153, 32, 84}, {95, 153, 32, 86}, {95, 153, 32, 87}, {95, 153, 32, 88}, {95, 153, 32, 89}, {95, 153, 32, 90}, {95, 153, 32, 91}, {95, 153, 32, 92}, {95, 153, 32, 94}}},
{Region: "Finland", Group: "Premium UDP Europe", Hostname: "87-1-fi.cg-dialup.net", IPs: []net.IP{{188, 126, 89, 102}, {188, 126, 89, 107}, {188, 126, 89, 108}, {188, 126, 89, 109}, {188, 126, 89, 114}, {188, 126, 89, 125}, {188, 126, 89, 136}, {188, 126, 89, 147}, {188, 126, 89, 153}, {188, 126, 89, 156}}},
{Region: "France", Group: "Premium TCP Europe", Hostname: "97-1-fr.cg-dialup.net", IPs: []net.IP{{84, 17, 60, 53}, {84, 17, 60, 55}, {84, 17, 60, 83}, {151, 106, 8, 41}, {151, 106, 11, 189}, {191, 101, 31, 156}, {191, 101, 31, 223}, {191, 101, 217, 61}, {191, 101, 217, 94}, {191, 101, 217, 209}}},
{Region: "France", Group: "Premium UDP Europe", Hostname: "87-1-fr.cg-dialup.net", IPs: []net.IP{{84, 17, 60, 102}, {92, 204, 174, 92}, {151, 106, 10, 132}, {191, 101, 31, 121}, {191, 101, 31, 167}, {191, 101, 31, 175}, {191, 101, 31, 196}, {191, 101, 217, 86}, {191, 101, 217, 87}, {191, 101, 217, 100}}},
{Region: "Georgia", Group: "Premium UDP Europe", Hostname: "87-1-ge.cg-dialup.net", IPs: []net.IP{{95, 181, 236, 132}, {95, 181, 236, 134}, {95, 181, 236, 135}, {95, 181, 236, 136}, {95, 181, 236, 137}, {95, 181, 236, 138}, {95, 181, 236, 140}, {95, 181, 236, 141}, {95, 181, 236, 142}, {95, 181, 236, 143}}},
{Region: "Germany", Group: "Premium TCP Europe", Hostname: "97-1-de.cg-dialup.net", IPs: []net.IP{{84, 17, 48, 110}, {84, 17, 48, 133}, {84, 17, 48, 190}, {84, 17, 49, 84}, {84, 17, 49, 143}, {84, 17, 49, 205}, {154, 13, 1, 175}, {154, 28, 188, 51}, {154, 28, 188, 71}, {154, 28, 188, 80}}},
{Region: "Germany", Group: "Premium UDP Europe", Hostname: "87-1-de.cg-dialup.net", IPs: []net.IP{{84, 17, 48, 35}, {84, 17, 48, 168}, {84, 17, 49, 2}, {84, 17, 49, 6}, {84, 17, 49, 19}, {84, 17, 49, 186}, {89, 163, 151, 73}, {154, 13, 1, 176}, {154, 28, 188, 79}, {154, 28, 188, 96}}},
{Region: "Greece", Group: "Premium TCP Europe", Hostname: "97-1-gr.cg-dialup.net", IPs: []net.IP{{185, 51, 134, 163}, {185, 51, 134, 166}, {185, 51, 134, 171}, {185, 51, 134, 243}, {185, 51, 134, 246}, {185, 51, 134, 247}, {185, 51, 134, 249}, {185, 51, 134, 251}, {185, 51, 134, 252}, {185, 51, 134, 253}}},
{Region: "Greece", Group: "Premium UDP Europe", Hostname: "87-1-gr.cg-dialup.net", IPs: []net.IP{{185, 51, 134, 165}, {185, 51, 134, 166}, {185, 51, 134, 168}, {185, 51, 134, 169}, {185, 51, 134, 174}, {185, 51, 134, 246}, {185, 51, 134, 250}, {185, 51, 134, 251}, {185, 51, 134, 252}, {185, 51, 134, 254}}},
{Region: "Greenland", Group: "Premium TCP Europe", Hostname: "97-1-gl.cg-dialup.net", IPs: []net.IP{{91, 90, 120, 3}, {91, 90, 120, 4}, {91, 90, 120, 5}, {91, 90, 120, 6}, {91, 90, 120, 8}, {91, 90, 120, 10}, {91, 90, 120, 11}, {91, 90, 120, 12}, {91, 90, 120, 14}, {91, 90, 120, 15}}},
{Region: "Greenland", Group: "Premium UDP Europe", Hostname: "87-1-gl.cg-dialup.net", IPs: []net.IP{{91, 90, 120, 3}, {91, 90, 120, 4}, {91, 90, 120, 6}, {91, 90, 120, 7}, {91, 90, 120, 9}, {91, 90, 120, 10}, {91, 90, 120, 12}, {91, 90, 120, 13}, {91, 90, 120, 16}, {91, 90, 120, 17}}},
{Region: "Hong Kong", Group: "Premium TCP Asia", Hostname: "96-1-hk.cg-dialup.net", IPs: []net.IP{{84, 17, 56, 132}, {84, 17, 56, 134}, {84, 17, 56, 135}, {84, 17, 56, 139}, {84, 17, 56, 143}, {84, 17, 56, 162}, {84, 17, 56, 164}, {84, 17, 56, 174}, {84, 17, 56, 182}, {84, 17, 56, 183}}},
{Region: "Hungary", Group: "Premium TCP Europe", Hostname: "97-1-hu.cg-dialup.net", IPs: []net.IP{{86, 106, 74, 243}, {86, 106, 74, 244}, {86, 106, 74, 246}, {86, 106, 74, 247}, {86, 106, 74, 249}, {185, 189, 114, 115}, {185, 189, 114, 120}, {185, 189, 114, 122}, {185, 189, 114, 123}, {185, 189, 114, 126}}},
{Region: "Hungary", Group: "Premium UDP Europe", Hostname: "87-1-hu.cg-dialup.net", IPs: []net.IP{{86, 106, 74, 243}, {86, 106, 74, 244}, {86, 106, 74, 247}, {86, 106, 74, 250}, {86, 106, 74, 251}, {86, 106, 74, 253}, {185, 189, 114, 117}, {185, 189, 114, 120}, {185, 189, 114, 124}, {185, 189, 114, 126}}},
{Region: "Iceland", Group: "Premium TCP Europe", Hostname: "97-1-is.cg-dialup.net", IPs: []net.IP{{45, 133, 193, 3}, {45, 133, 193, 5}, {45, 133, 193, 6}, {45, 133, 193, 7}, {45, 133, 193, 9}, {45, 133, 193, 10}, {45, 133, 193, 11}, {45, 133, 193, 12}, {45, 133, 193, 13}, {45, 133, 193, 14}}},
{Region: "India", Group: "Premium TCP Europe", Hostname: "97-1-in.cg-dialup.net", IPs: []net.IP{{103, 13, 112, 50}, {103, 13, 112, 52}, {103, 13, 112, 59}, {103, 13, 112, 61}, {103, 13, 112, 67}, {103, 13, 112, 68}, {103, 13, 112, 74}, {103, 13, 112, 78}, {103, 13, 112, 80}, {103, 13, 112, 81}}},
{Region: "India", Group: "Premium UDP Europe", Hostname: "87-1-in.cg-dialup.net", IPs: []net.IP{{103, 13, 112, 50}, {103, 13, 112, 51}, {103, 13, 112, 52}, {103, 13, 112, 54}, {103, 13, 112, 59}, {103, 13, 112, 60}, {103, 13, 112, 66}, {103, 13, 112, 67}, {103, 13, 112, 71}, {103, 13, 112, 79}}},
{Region: "Indonesia", Group: "Premium TCP Asia", Hostname: "96-1-id.cg-dialup.net", IPs: []net.IP{{146, 70, 14, 3}, {146, 70, 14, 5}, {146, 70, 14, 7}, {146, 70, 14, 9}, {146, 70, 14, 10}, {146, 70, 14, 11}, {146, 70, 14, 12}, {146, 70, 14, 13}, {146, 70, 14, 15}, {146, 70, 14, 16}}},
{Region: "Indonesia", Group: "Premium UDP Asia", Hostname: "95-1-id.cg-dialup.net", IPs: []net.IP{{146, 70, 14, 3}, {146, 70, 14, 5}, {146, 70, 14, 7}, {146, 70, 14, 10}, {146, 70, 14, 11}, {146, 70, 14, 12}, {146, 70, 14, 13}, {146, 70, 14, 14}, {146, 70, 14, 15}, {146, 70, 14, 16}}},
{Region: "Iran", Group: "Premium TCP Asia", Hostname: "96-1-ir.cg-dialup.net", IPs: []net.IP{{62, 133, 46, 3}, {62, 133, 46, 4}, {62, 133, 46, 5}, {62, 133, 46, 7}, {62, 133, 46, 8}, {62, 133, 46, 9}, {62, 133, 46, 10}, {62, 133, 46, 12}, {62, 133, 46, 14}, {62, 133, 46, 16}}},
{Region: "Ireland", Group: "Premium UDP Europe", Hostname: "87-1-ie.cg-dialup.net", IPs: []net.IP{{37, 120, 235, 147}, {37, 120, 235, 158}, {37, 120, 235, 165}, {37, 120, 235, 166}, {84, 247, 48, 5}, {84, 247, 48, 6}, {84, 247, 48, 9}, {84, 247, 48, 23}, {84, 247, 48, 27}, {84, 247, 48, 29}}},
{Region: "Isle of Man", Group: "Premium TCP Europe", Hostname: "97-1-im.cg-dialup.net", IPs: []net.IP{{91, 90, 124, 147}, {91, 90, 124, 149}, {91, 90, 124, 150}, {91, 90, 124, 151}, {91, 90, 124, 153}, {91, 90, 124, 154}, {91, 90, 124, 155}, {91, 90, 124, 157}, {91, 90, 124, 158}, {91, 90, 124, 159}}},
{Region: "Isle of Man", Group: "Premium UDP Europe", Hostname: "87-1-im.cg-dialup.net", IPs: []net.IP{{91, 90, 124, 147}, {91, 90, 124, 148}, {91, 90, 124, 150}, {91, 90, 124, 151}, {91, 90, 124, 152}, {91, 90, 124, 153}, {91, 90, 124, 154}, {91, 90, 124, 156}, {91, 90, 124, 157}, {91, 90, 124, 158}}},
{Region: "Israel", Group: "Premium UDP Europe", Hostname: "87-1-il.cg-dialup.net", IPs: []net.IP{{160, 116, 0, 169}, {160, 116, 0, 170}, {160, 116, 0, 171}, {160, 116, 0, 172}, {185, 77, 248, 114}, {185, 77, 248, 117}, {185, 77, 248, 119}, {185, 77, 248, 121}, {185, 77, 248, 123}, {185, 77, 248, 129}}},
{Region: "Italy", Group: "Premium TCP Europe", Hostname: "97-1-it.cg-dialup.net", IPs: []net.IP{{84, 17, 58, 12}, {84, 17, 58, 94}, {84, 17, 58, 96}, {84, 17, 58, 98}, {84, 17, 58, 100}, {84, 17, 58, 105}, {185, 217, 71, 132}, {212, 102, 55, 103}, {212, 102, 55, 109}, {212, 102, 55, 113}}},
{Region: "Italy", Group: "Premium UDP Europe", Hostname: "87-1-it.cg-dialup.net", IPs: []net.IP{{84, 17, 58, 10}, {84, 17, 58, 20}, {84, 17, 58, 104}, {84, 17, 58, 105}, {87, 101, 94, 67}, {87, 101, 94, 120}, {87, 101, 94, 123}, {185, 217, 71, 153}, {212, 102, 55, 111}, {212, 102, 55, 122}}},
{Region: "Japan", Group: "Premium UDP Asia", Hostname: "95-1-jp.cg-dialup.net", IPs: []net.IP{{156, 146, 35, 10}, {156, 146, 35, 14}, {156, 146, 35, 17}, {156, 146, 35, 18}, {156, 146, 35, 23}, {156, 146, 35, 25}, {156, 146, 35, 30}, {156, 146, 35, 44}, {156, 146, 35, 46}, {156, 146, 35, 48}}},
{Region: "Kazakhstan", Group: "Premium TCP Europe", Hostname: "97-1-kz.cg-dialup.net", IPs: []net.IP{{62, 133, 47, 131}, {62, 133, 47, 132}, {62, 133, 47, 134}, {62, 133, 47, 135}, {62, 133, 47, 136}, {62, 133, 47, 137}, {62, 133, 47, 138}, {62, 133, 47, 139}, {62, 133, 47, 140}, {62, 133, 47, 142}}},
{Region: "Kazakhstan", Group: "Premium UDP Europe", Hostname: "87-1-kz.cg-dialup.net", IPs: []net.IP{{62, 133, 47, 131}, {62, 133, 47, 132}, {62, 133, 47, 133}, {62, 133, 47, 134}, {62, 133, 47, 135}, {62, 133, 47, 137}, {62, 133, 47, 141}, {62, 133, 47, 142}, {62, 133, 47, 143}, {62, 133, 47, 144}}},
{Region: "Brazil", Group: "Premium TCP USA", Hostname: "93-1-br.cg-dialup.net", IPs: []net.IP{{188, 241, 177, 5}, {188, 241, 177, 11}, {188, 241, 177, 38}, {188, 241, 177, 45}, {188, 241, 177, 132}, {188, 241, 177, 135}, {188, 241, 177, 136}, {188, 241, 177, 152}, {188, 241, 177, 153}, {188, 241, 177, 156}}},
{Region: "Brazil", Group: "Premium UDP USA", Hostname: "94-1-br.cg-dialup.net", IPs: []net.IP{{188, 241, 177, 8}, {188, 241, 177, 37}, {188, 241, 177, 40}, {188, 241, 177, 42}, {188, 241, 177, 45}, {188, 241, 177, 135}, {188, 241, 177, 139}, {188, 241, 177, 149}, {188, 241, 177, 152}, {188, 241, 177, 154}}},
{Region: "Bulgaria", Group: "Premium TCP Europe", Hostname: "97-1-bg.cg-dialup.net", IPs: []net.IP{{37, 120, 152, 99}, {37, 120, 152, 101}, {37, 120, 152, 103}, {37, 120, 152, 104}, {37, 120, 152, 105}, {37, 120, 152, 106}, {37, 120, 152, 107}, {37, 120, 152, 108}, {37, 120, 152, 109}, {37, 120, 152, 110}}},
{Region: "Bulgaria", Group: "Premium UDP Europe", Hostname: "87-1-bg.cg-dialup.net", IPs: []net.IP{{37, 120, 152, 99}, {37, 120, 152, 100}, {37, 120, 152, 101}, {37, 120, 152, 102}, {37, 120, 152, 103}, {37, 120, 152, 105}, {37, 120, 152, 106}, {37, 120, 152, 107}, {37, 120, 152, 108}, {37, 120, 152, 109}}},
{Region: "Cambodia", Group: "Premium TCP Asia", Hostname: "96-1-kh.cg-dialup.net", IPs: []net.IP{{188, 215, 235, 35}, {188, 215, 235, 36}, {188, 215, 235, 38}, {188, 215, 235, 39}, {188, 215, 235, 45}, {188, 215, 235, 49}, {188, 215, 235, 51}, {188, 215, 235, 53}, {188, 215, 235, 54}, {188, 215, 235, 57}}},
{Region: "Cambodia", Group: "Premium UDP Asia", Hostname: "95-1-kh.cg-dialup.net", IPs: []net.IP{{188, 215, 235, 36}, {188, 215, 235, 40}, {188, 215, 235, 42}, {188, 215, 235, 44}, {188, 215, 235, 46}, {188, 215, 235, 47}, {188, 215, 235, 48}, {188, 215, 235, 50}, {188, 215, 235, 55}, {188, 215, 235, 57}}},
{Region: "Canada", Group: "Premium TCP USA", Hostname: "93-1-ca.cg-dialup.net", IPs: []net.IP{{66, 115, 142, 136}, {66, 115, 142, 139}, {66, 115, 142, 156}, {66, 115, 142, 162}, {66, 115, 142, 172}, {104, 200, 151, 99}, {104, 200, 151, 111}, {104, 200, 151, 153}, {104, 200, 151, 164}, {172, 98, 89, 137}}},
{Region: "Canada", Group: "Premium UDP USA", Hostname: "94-1-ca.cg-dialup.net", IPs: []net.IP{{66, 115, 142, 135}, {66, 115, 142, 154}, {66, 115, 142, 165}, {104, 200, 151, 32}, {104, 200, 151, 57}, {104, 200, 151, 85}, {104, 200, 151, 86}, {104, 200, 151, 147}, {172, 98, 89, 144}, {172, 98, 89, 173}}},
{Region: "Chile", Group: "Premium TCP USA", Hostname: "93-1-cl.cg-dialup.net", IPs: []net.IP{{146, 70, 11, 3}, {146, 70, 11, 6}, {146, 70, 11, 7}, {146, 70, 11, 8}, {146, 70, 11, 9}, {146, 70, 11, 10}, {146, 70, 11, 11}, {146, 70, 11, 12}, {146, 70, 11, 13}, {146, 70, 11, 14}}},
{Region: "Chile", Group: "Premium UDP USA", Hostname: "94-1-cl.cg-dialup.net", IPs: []net.IP{{146, 70, 11, 3}, {146, 70, 11, 4}, {146, 70, 11, 6}, {146, 70, 11, 7}, {146, 70, 11, 8}, {146, 70, 11, 9}, {146, 70, 11, 10}, {146, 70, 11, 11}, {146, 70, 11, 13}, {146, 70, 11, 14}}},
{Region: "China", Group: "Premium TCP Asia", Hostname: "96-1-cn.cg-dialup.net", IPs: []net.IP{{188, 241, 80, 131}, {188, 241, 80, 132}, {188, 241, 80, 133}, {188, 241, 80, 134}, {188, 241, 80, 135}, {188, 241, 80, 137}, {188, 241, 80, 139}, {188, 241, 80, 140}, {188, 241, 80, 141}, {188, 241, 80, 142}}},
{Region: "China", Group: "Premium UDP Asia", Hostname: "95-1-cn.cg-dialup.net", IPs: []net.IP{{188, 241, 80, 131}, {188, 241, 80, 132}, {188, 241, 80, 133}, {188, 241, 80, 134}, {188, 241, 80, 135}, {188, 241, 80, 136}, {188, 241, 80, 137}, {188, 241, 80, 138}, {188, 241, 80, 139}, {188, 241, 80, 142}}},
{Region: "Colombia", Group: "Premium TCP USA", Hostname: "93-1-co.cg-dialup.net", IPs: []net.IP{{146, 70, 9, 3}, {146, 70, 9, 4}, {146, 70, 9, 5}, {146, 70, 9, 7}, {146, 70, 9, 9}, {146, 70, 9, 10}, {146, 70, 9, 11}, {146, 70, 9, 12}, {146, 70, 9, 13}, {146, 70, 9, 14}}},
{Region: "Colombia", Group: "Premium UDP USA", Hostname: "94-1-co.cg-dialup.net", IPs: []net.IP{{146, 70, 9, 3}, {146, 70, 9, 4}, {146, 70, 9, 5}, {146, 70, 9, 6}, {146, 70, 9, 7}, {146, 70, 9, 8}, {146, 70, 9, 9}, {146, 70, 9, 10}, {146, 70, 9, 11}, {146, 70, 9, 12}}},
{Region: "Costa Rica", Group: "Premium TCP USA", Hostname: "93-1-cr.cg-dialup.net", IPs: []net.IP{{146, 70, 10, 3}, {146, 70, 10, 4}, {146, 70, 10, 5}, {146, 70, 10, 6}, {146, 70, 10, 7}, {146, 70, 10, 8}, {146, 70, 10, 10}, {146, 70, 10, 11}, {146, 70, 10, 12}, {146, 70, 10, 13}}},
{Region: "Costa Rica", Group: "Premium UDP USA", Hostname: "94-1-cr.cg-dialup.net", IPs: []net.IP{{146, 70, 10, 3}, {146, 70, 10, 4}, {146, 70, 10, 5}, {146, 70, 10, 6}, {146, 70, 10, 7}, {146, 70, 10, 8}, {146, 70, 10, 9}, {146, 70, 10, 11}, {146, 70, 10, 12}, {146, 70, 10, 14}}},
{Region: "Croatia", Group: "Premium TCP Europe", Hostname: "97-1-hr.cg-dialup.net", IPs: []net.IP{{146, 70, 8, 5}, {146, 70, 8, 8}, {146, 70, 8, 9}, {146, 70, 8, 10}, {146, 70, 8, 11}, {146, 70, 8, 12}, {146, 70, 8, 13}, {146, 70, 8, 14}, {146, 70, 8, 15}, {146, 70, 8, 16}}},
{Region: "Croatia", Group: "Premium UDP Europe", Hostname: "87-1-hr.cg-dialup.net", IPs: []net.IP{{146, 70, 8, 3}, {146, 70, 8, 4}, {146, 70, 8, 5}, {146, 70, 8, 6}, {146, 70, 8, 7}, {146, 70, 8, 9}, {146, 70, 8, 11}, {146, 70, 8, 13}, {146, 70, 8, 14}, {146, 70, 8, 16}}},
{Region: "Cyprus", Group: "Premium TCP Europe", Hostname: "97-1-cy.cg-dialup.net", IPs: []net.IP{{185, 253, 162, 131}, {185, 253, 162, 133}, {185, 253, 162, 135}, {185, 253, 162, 136}, {185, 253, 162, 137}, {185, 253, 162, 139}, {185, 253, 162, 140}, {185, 253, 162, 142}, {185, 253, 162, 143}, {185, 253, 162, 144}}},
{Region: "Cyprus", Group: "Premium UDP Europe", Hostname: "87-1-cy.cg-dialup.net", IPs: []net.IP{{185, 253, 162, 131}, {185, 253, 162, 132}, {185, 253, 162, 134}, {185, 253, 162, 135}, {185, 253, 162, 137}, {185, 253, 162, 138}, {185, 253, 162, 140}, {185, 253, 162, 142}, {185, 253, 162, 143}, {185, 253, 162, 144}}},
{Region: "Czech Republic", Group: "Premium TCP Europe", Hostname: "97-1-cz.cg-dialup.net", IPs: []net.IP{{138, 199, 56, 235}, {138, 199, 56, 236}, {138, 199, 56, 237}, {138, 199, 56, 245}, {138, 199, 56, 246}, {138, 199, 56, 249}, {195, 181, 161, 12}, {195, 181, 161, 16}, {195, 181, 161, 20}, {195, 181, 161, 23}}},
{Region: "Czech Republic", Group: "Premium UDP Europe", Hostname: "87-1-cz.cg-dialup.net", IPs: []net.IP{{138, 199, 56, 227}, {138, 199, 56, 229}, {138, 199, 56, 231}, {138, 199, 56, 235}, {138, 199, 56, 241}, {138, 199, 56, 247}, {195, 181, 161, 10}, {195, 181, 161, 16}, {195, 181, 161, 18}, {195, 181, 161, 22}}},
{Region: "Denmark", Group: "Premium TCP Europe", Hostname: "97-1-dk.cg-dialup.net", IPs: []net.IP{{37, 120, 145, 83}, {37, 120, 145, 88}, {37, 120, 145, 93}, {37, 120, 194, 36}, {37, 120, 194, 56}, {37, 120, 194, 57}, {95, 174, 65, 163}, {95, 174, 65, 174}, {185, 206, 224, 238}, {185, 206, 224, 243}}},
{Region: "Denmark", Group: "Premium UDP Europe", Hostname: "87-1-dk.cg-dialup.net", IPs: []net.IP{{37, 120, 194, 39}, {95, 174, 65, 167}, {95, 174, 65, 170}, {185, 206, 224, 227}, {185, 206, 224, 230}, {185, 206, 224, 236}, {185, 206, 224, 238}, {185, 206, 224, 245}, {185, 206, 224, 250}, {185, 206, 224, 254}}},
{Region: "Egypt", Group: "Premium TCP Europe", Hostname: "97-1-eg.cg-dialup.net", IPs: []net.IP{{188, 214, 122, 40}, {188, 214, 122, 42}, {188, 214, 122, 43}, {188, 214, 122, 45}, {188, 214, 122, 48}, {188, 214, 122, 50}, {188, 214, 122, 52}, {188, 214, 122, 60}, {188, 214, 122, 70}, {188, 214, 122, 73}}},
{Region: "Egypt", Group: "Premium UDP Europe", Hostname: "87-1-eg.cg-dialup.net", IPs: []net.IP{{188, 214, 122, 37}, {188, 214, 122, 38}, {188, 214, 122, 44}, {188, 214, 122, 54}, {188, 214, 122, 57}, {188, 214, 122, 59}, {188, 214, 122, 60}, {188, 214, 122, 61}, {188, 214, 122, 67}, {188, 214, 122, 69}}},
{Region: "Estonia", Group: "Premium TCP Europe", Hostname: "97-1-ee.cg-dialup.net", IPs: []net.IP{{95, 153, 32, 83}, {95, 153, 32, 84}, {95, 153, 32, 86}, {95, 153, 32, 88}, {95, 153, 32, 89}, {95, 153, 32, 90}, {95, 153, 32, 91}, {95, 153, 32, 92}, {95, 153, 32, 93}, {95, 153, 32, 94}}},
{Region: "Estonia", Group: "Premium UDP Europe", Hostname: "87-1-ee.cg-dialup.net", IPs: []net.IP{{95, 153, 32, 83}, {95, 153, 32, 84}, {95, 153, 32, 85}, {95, 153, 32, 87}, {95, 153, 32, 88}, {95, 153, 32, 89}, {95, 153, 32, 90}, {95, 153, 32, 91}, {95, 153, 32, 92}, {95, 153, 32, 94}}},
{Region: "Finland", Group: "Premium TCP Europe", Hostname: "97-1-fi.cg-dialup.net", IPs: []net.IP{{188, 126, 89, 99}, {188, 126, 89, 102}, {188, 126, 89, 105}, {188, 126, 89, 107}, {188, 126, 89, 108}, {188, 126, 89, 110}, {188, 126, 89, 112}, {188, 126, 89, 115}, {188, 126, 89, 116}, {188, 126, 89, 119}}},
{Region: "Finland", Group: "Premium UDP Europe", Hostname: "87-1-fi.cg-dialup.net", IPs: []net.IP{{188, 126, 89, 101}, {188, 126, 89, 104}, {188, 126, 89, 109}, {188, 126, 89, 110}, {188, 126, 89, 111}, {188, 126, 89, 113}, {188, 126, 89, 114}, {188, 126, 89, 115}, {188, 126, 89, 122}, {188, 126, 89, 124}}},
{Region: "France", Group: "Premium TCP Europe", Hostname: "97-1-fr.cg-dialup.net", IPs: []net.IP{{84, 17, 43, 167}, {84, 17, 60, 147}, {84, 17, 60, 155}, {151, 106, 8, 108}, {191, 101, 31, 202}, {191, 101, 31, 254}, {191, 101, 217, 45}, {191, 101, 217, 159}, {191, 101, 217, 211}, {191, 101, 217, 240}}},
{Region: "France", Group: "Premium UDP Europe", Hostname: "87-1-fr.cg-dialup.net", IPs: []net.IP{{84, 17, 60, 59}, {84, 17, 60, 121}, {191, 101, 31, 81}, {191, 101, 31, 84}, {191, 101, 31, 126}, {191, 101, 31, 127}, {191, 101, 217, 140}, {191, 101, 217, 201}, {191, 101, 217, 206}, {191, 101, 217, 211}}},
{Region: "Georgia", Group: "Premium TCP Europe", Hostname: "97-1-ge.cg-dialup.net", IPs: []net.IP{{95, 181, 236, 131}, {95, 181, 236, 132}, {95, 181, 236, 133}, {95, 181, 236, 134}, {95, 181, 236, 135}, {95, 181, 236, 136}, {95, 181, 236, 138}, {95, 181, 236, 139}, {95, 181, 236, 142}, {95, 181, 236, 144}}},
{Region: "Georgia", Group: "Premium UDP Europe", Hostname: "87-1-ge.cg-dialup.net", IPs: []net.IP{{95, 181, 236, 132}, {95, 181, 236, 133}, {95, 181, 236, 134}, {95, 181, 236, 136}, {95, 181, 236, 137}, {95, 181, 236, 139}, {95, 181, 236, 141}, {95, 181, 236, 142}, {95, 181, 236, 143}, {95, 181, 236, 144}}},
{Region: "Germany", Group: "Premium TCP Europe", Hostname: "97-1-de.cg-dialup.net", IPs: []net.IP{{84, 17, 48, 39}, {84, 17, 48, 234}, {84, 17, 49, 106}, {84, 17, 49, 112}, {84, 17, 49, 218}, {154, 28, 188, 35}, {154, 28, 188, 66}, {154, 28, 188, 133}, {154, 28, 188, 144}, {154, 28, 188, 145}}},
{Region: "Germany", Group: "Premium UDP Europe", Hostname: "87-1-de.cg-dialup.net", IPs: []net.IP{{84, 17, 48, 41}, {84, 17, 48, 224}, {84, 17, 49, 95}, {84, 17, 49, 236}, {84, 17, 49, 241}, {138, 199, 36, 151}, {154, 13, 1, 177}, {154, 28, 188, 73}, {154, 28, 188, 76}, {154, 28, 188, 93}}},
{Region: "Greece", Group: "Premium TCP Europe", Hostname: "97-1-gr.cg-dialup.net", IPs: []net.IP{{185, 51, 134, 163}, {185, 51, 134, 165}, {185, 51, 134, 171}, {185, 51, 134, 172}, {185, 51, 134, 245}, {185, 51, 134, 246}, {185, 51, 134, 247}, {185, 51, 134, 249}, {185, 51, 134, 251}, {185, 51, 134, 254}}},
{Region: "Greece", Group: "Premium UDP Europe", Hostname: "87-1-gr.cg-dialup.net", IPs: []net.IP{{185, 51, 134, 163}, {185, 51, 134, 166}, {185, 51, 134, 173}, {185, 51, 134, 174}, {185, 51, 134, 244}, {185, 51, 134, 246}, {185, 51, 134, 247}, {185, 51, 134, 251}, {185, 51, 134, 252}, {185, 51, 134, 253}}},
{Region: "Greenland", Group: "Premium TCP Europe", Hostname: "97-1-gl.cg-dialup.net", IPs: []net.IP{{91, 90, 120, 3}, {91, 90, 120, 4}, {91, 90, 120, 5}, {91, 90, 120, 7}, {91, 90, 120, 8}, {91, 90, 120, 10}, {91, 90, 120, 12}, {91, 90, 120, 13}, {91, 90, 120, 14}, {91, 90, 120, 17}}},
{Region: "Greenland", Group: "Premium UDP Europe", Hostname: "87-1-gl.cg-dialup.net", IPs: []net.IP{{91, 90, 120, 3}, {91, 90, 120, 4}, {91, 90, 120, 5}, {91, 90, 120, 7}, {91, 90, 120, 9}, {91, 90, 120, 10}, {91, 90, 120, 12}, {91, 90, 120, 14}, {91, 90, 120, 15}, {91, 90, 120, 16}}},
{Region: "Hong Kong", Group: "Premium TCP Asia", Hostname: "96-1-hk.cg-dialup.net", IPs: []net.IP{{84, 17, 56, 144}, {84, 17, 56, 148}, {84, 17, 56, 153}, {84, 17, 56, 162}, {84, 17, 56, 163}, {84, 17, 56, 169}, {84, 17, 56, 170}, {84, 17, 56, 179}, {84, 17, 56, 180}, {84, 17, 56, 181}}},
{Region: "Hong Kong", Group: "Premium UDP Asia", Hostname: "95-1-hk.cg-dialup.net", IPs: []net.IP{{84, 17, 56, 143}, {84, 17, 56, 147}, {84, 17, 56, 150}, {84, 17, 56, 152}, {84, 17, 56, 161}, {84, 17, 56, 164}, {84, 17, 56, 168}, {84, 17, 56, 179}, {84, 17, 56, 180}, {84, 17, 56, 183}}},
{Region: "Hungary", Group: "Premium TCP Europe", Hostname: "97-1-hu.cg-dialup.net", IPs: []net.IP{{86, 106, 74, 247}, {86, 106, 74, 251}, {86, 106, 74, 253}, {185, 189, 114, 117}, {185, 189, 114, 118}, {185, 189, 114, 119}, {185, 189, 114, 121}, {185, 189, 114, 123}, {185, 189, 114, 125}, {185, 189, 114, 126}}},
{Region: "Hungary", Group: "Premium UDP Europe", Hostname: "87-1-hu.cg-dialup.net", IPs: []net.IP{{86, 106, 74, 245}, {86, 106, 74, 247}, {86, 106, 74, 248}, {86, 106, 74, 249}, {86, 106, 74, 250}, {86, 106, 74, 252}, {86, 106, 74, 253}, {185, 189, 114, 120}, {185, 189, 114, 121}, {185, 189, 114, 122}}},
{Region: "Iceland", Group: "Premium TCP Europe", Hostname: "97-1-is.cg-dialup.net", IPs: []net.IP{{45, 133, 193, 3}, {45, 133, 193, 4}, {45, 133, 193, 6}, {45, 133, 193, 7}, {45, 133, 193, 8}, {45, 133, 193, 10}, {45, 133, 193, 11}, {45, 133, 193, 12}, {45, 133, 193, 13}, {45, 133, 193, 14}}},
{Region: "Iceland", Group: "Premium UDP Europe", Hostname: "87-1-is.cg-dialup.net", IPs: []net.IP{{45, 133, 193, 3}, {45, 133, 193, 5}, {45, 133, 193, 6}, {45, 133, 193, 7}, {45, 133, 193, 8}, {45, 133, 193, 9}, {45, 133, 193, 10}, {45, 133, 193, 11}, {45, 133, 193, 13}, {45, 133, 193, 14}}},
{Region: "India", Group: "Premium TCP Europe", Hostname: "97-1-in.cg-dialup.net", IPs: []net.IP{{103, 13, 112, 68}, {103, 13, 112, 70}, {103, 13, 112, 72}, {103, 13, 112, 74}, {103, 13, 112, 75}, {103, 13, 113, 74}, {103, 13, 113, 79}, {103, 13, 113, 82}, {103, 13, 113, 83}, {103, 13, 113, 84}}},
{Region: "India", Group: "Premium UDP Europe", Hostname: "87-1-in.cg-dialup.net", IPs: []net.IP{{103, 13, 112, 67}, {103, 13, 112, 70}, {103, 13, 112, 71}, {103, 13, 112, 77}, {103, 13, 112, 80}, {103, 13, 113, 72}, {103, 13, 113, 74}, {103, 13, 113, 75}, {103, 13, 113, 77}, {103, 13, 113, 85}}},
{Region: "Indonesia", Group: "Premium TCP Asia", Hostname: "96-1-id.cg-dialup.net", IPs: []net.IP{{146, 70, 14, 3}, {146, 70, 14, 4}, {146, 70, 14, 5}, {146, 70, 14, 6}, {146, 70, 14, 7}, {146, 70, 14, 10}, {146, 70, 14, 12}, {146, 70, 14, 13}, {146, 70, 14, 15}, {146, 70, 14, 16}}},
{Region: "Indonesia", Group: "Premium UDP Asia", Hostname: "95-1-id.cg-dialup.net", IPs: []net.IP{{146, 70, 14, 3}, {146, 70, 14, 5}, {146, 70, 14, 8}, {146, 70, 14, 9}, {146, 70, 14, 10}, {146, 70, 14, 12}, {146, 70, 14, 13}, {146, 70, 14, 14}, {146, 70, 14, 15}, {146, 70, 14, 16}}},
{Region: "Iran", Group: "Premium TCP Asia", Hostname: "96-1-ir.cg-dialup.net", IPs: []net.IP{{62, 133, 46, 3}, {62, 133, 46, 4}, {62, 133, 46, 5}, {62, 133, 46, 6}, {62, 133, 46, 7}, {62, 133, 46, 8}, {62, 133, 46, 9}, {62, 133, 46, 10}, {62, 133, 46, 14}, {62, 133, 46, 15}}},
{Region: "Iran", Group: "Premium UDP Asia", Hostname: "95-1-ir.cg-dialup.net", IPs: []net.IP{{62, 133, 46, 3}, {62, 133, 46, 4}, {62, 133, 46, 7}, {62, 133, 46, 8}, {62, 133, 46, 11}, {62, 133, 46, 12}, {62, 133, 46, 13}, {62, 133, 46, 14}, {62, 133, 46, 15}, {62, 133, 46, 16}}},
{Region: "Ireland", Group: "Premium TCP Europe", Hostname: "97-1-ie.cg-dialup.net", IPs: []net.IP{{37, 120, 235, 154}, {37, 120, 235, 166}, {37, 120, 235, 174}, {77, 81, 139, 35}, {84, 247, 48, 6}, {84, 247, 48, 19}, {84, 247, 48, 22}, {84, 247, 48, 23}, {84, 247, 48, 25}, {84, 247, 48, 26}}},
{Region: "Ireland", Group: "Premium UDP Europe", Hostname: "87-1-ie.cg-dialup.net", IPs: []net.IP{{37, 120, 235, 147}, {37, 120, 235, 148}, {37, 120, 235, 153}, {37, 120, 235, 158}, {37, 120, 235, 169}, {37, 120, 235, 174}, {84, 247, 48, 8}, {84, 247, 48, 11}, {84, 247, 48, 20}, {84, 247, 48, 23}}},
{Region: "Isle of Man", Group: "Premium TCP Europe", Hostname: "97-1-im.cg-dialup.net", IPs: []net.IP{{91, 90, 124, 147}, {91, 90, 124, 149}, {91, 90, 124, 150}, {91, 90, 124, 151}, {91, 90, 124, 152}, {91, 90, 124, 153}, {91, 90, 124, 154}, {91, 90, 124, 156}, {91, 90, 124, 157}, {91, 90, 124, 158}}},
{Region: "Isle of Man", Group: "Premium UDP Europe", Hostname: "87-1-im.cg-dialup.net", IPs: []net.IP{{91, 90, 124, 147}, {91, 90, 124, 149}, {91, 90, 124, 150}, {91, 90, 124, 151}, {91, 90, 124, 152}, {91, 90, 124, 153}, {91, 90, 124, 154}, {91, 90, 124, 155}, {91, 90, 124, 156}, {91, 90, 124, 157}}},
{Region: "Israel", Group: "Premium TCP Europe", Hostname: "97-1-il.cg-dialup.net", IPs: []net.IP{{160, 116, 0, 174}, {185, 77, 248, 103}, {185, 77, 248, 111}, {185, 77, 248, 113}, {185, 77, 248, 114}, {185, 77, 248, 124}, {185, 77, 248, 125}, {185, 77, 248, 127}, {185, 77, 248, 128}, {185, 77, 248, 129}}},
{Region: "Israel", Group: "Premium UDP Europe", Hostname: "87-1-il.cg-dialup.net", IPs: []net.IP{{160, 116, 0, 163}, {160, 116, 0, 165}, {160, 116, 0, 172}, {185, 77, 248, 103}, {185, 77, 248, 106}, {185, 77, 248, 114}, {185, 77, 248, 117}, {185, 77, 248, 118}, {185, 77, 248, 126}, {185, 77, 248, 129}}},
{Region: "Italy", Group: "Premium TCP Europe", Hostname: "97-1-it.cg-dialup.net", IPs: []net.IP{{84, 17, 58, 21}, {84, 17, 58, 100}, {84, 17, 58, 106}, {84, 17, 58, 111}, {84, 17, 58, 117}, {87, 101, 94, 122}, {212, 102, 55, 100}, {212, 102, 55, 106}, {212, 102, 55, 110}, {212, 102, 55, 122}}},
{Region: "Italy", Group: "Premium UDP Europe", Hostname: "87-1-it.cg-dialup.net", IPs: []net.IP{{84, 17, 58, 19}, {84, 17, 58, 95}, {84, 17, 58, 105}, {84, 17, 58, 119}, {84, 17, 58, 120}, {87, 101, 94, 116}, {185, 217, 71, 137}, {185, 217, 71, 138}, {185, 217, 71, 153}, {212, 102, 55, 108}}},
{Region: "Japan", Group: "Premium TCP Asia", Hostname: "96-1-jp.cg-dialup.net", IPs: []net.IP{{156, 146, 35, 6}, {156, 146, 35, 10}, {156, 146, 35, 15}, {156, 146, 35, 22}, {156, 146, 35, 37}, {156, 146, 35, 39}, {156, 146, 35, 40}, {156, 146, 35, 41}, {156, 146, 35, 44}, {156, 146, 35, 50}}},
{Region: "Japan", Group: "Premium UDP Asia", Hostname: "95-1-jp.cg-dialup.net", IPs: []net.IP{{156, 146, 35, 4}, {156, 146, 35, 14}, {156, 146, 35, 15}, {156, 146, 35, 18}, {156, 146, 35, 25}, {156, 146, 35, 34}, {156, 146, 35, 36}, {156, 146, 35, 46}, {156, 146, 35, 49}, {156, 146, 35, 50}}},
{Region: "Kazakhstan", Group: "Premium TCP Europe", Hostname: "97-1-kz.cg-dialup.net", IPs: []net.IP{{62, 133, 47, 131}, {62, 133, 47, 132}, {62, 133, 47, 134}, {62, 133, 47, 136}, {62, 133, 47, 138}, {62, 133, 47, 139}, {62, 133, 47, 140}, {62, 133, 47, 142}, {62, 133, 47, 143}, {62, 133, 47, 144}}},
{Region: "Kazakhstan", Group: "Premium UDP Europe", Hostname: "87-1-kz.cg-dialup.net", IPs: []net.IP{{62, 133, 47, 131}, {62, 133, 47, 132}, {62, 133, 47, 133}, {62, 133, 47, 134}, {62, 133, 47, 135}, {62, 133, 47, 138}, {62, 133, 47, 139}, {62, 133, 47, 140}, {62, 133, 47, 142}, {62, 133, 47, 143}}},
{Region: "Kenya", Group: "Premium TCP Asia", Hostname: "96-1-ke.cg-dialup.net", IPs: []net.IP{{62, 12, 118, 195}, {62, 12, 118, 196}, {62, 12, 118, 197}, {62, 12, 118, 198}, {62, 12, 118, 199}, {62, 12, 118, 200}, {62, 12, 118, 201}, {62, 12, 118, 202}, {62, 12, 118, 203}, {62, 12, 118, 204}}},
{Region: "Kenya", Group: "Premium UDP Asia", Hostname: "95-1-ke.cg-dialup.net", IPs: []net.IP{{62, 12, 118, 195}, {62, 12, 118, 196}, {62, 12, 118, 197}, {62, 12, 118, 198}, {62, 12, 118, 199}, {62, 12, 118, 200}, {62, 12, 118, 201}, {62, 12, 118, 202}, {62, 12, 118, 203}, {62, 12, 118, 204}}},
{Region: "Korea", Group: "Premium TCP Asia", Hostname: "96-1-kr.cg-dialup.net", IPs: []net.IP{{79, 110, 55, 131}, {79, 110, 55, 135}, {79, 110, 55, 137}, {79, 110, 55, 142}, {79, 110, 55, 147}, {79, 110, 55, 148}, {79, 110, 55, 149}, {79, 110, 55, 154}, {79, 110, 55, 155}, {79, 110, 55, 158}}},
{Region: "Korea", Group: "Premium UDP Asia", Hostname: "95-1-kr.cg-dialup.net", IPs: []net.IP{{79, 110, 55, 131}, {79, 110, 55, 132}, {79, 110, 55, 133}, {79, 110, 55, 141}, {79, 110, 55, 147}, {79, 110, 55, 148}, {79, 110, 55, 150}, {79, 110, 55, 154}, {79, 110, 55, 157}, {79, 110, 55, 158}}},
{Region: "Liechtenstein", Group: "Premium TCP Europe", Hostname: "97-1-li.cg-dialup.net", IPs: []net.IP{{91, 90, 122, 133}, {91, 90, 122, 134}, {91, 90, 122, 135}, {91, 90, 122, 137}, {91, 90, 122, 138}, {91, 90, 122, 139}, {91, 90, 122, 140}, {91, 90, 122, 142}, {91, 90, 122, 143}, {91, 90, 122, 144}}},
{Region: "Liechtenstein", Group: "Premium UDP Europe", Hostname: "87-1-li.cg-dialup.net", IPs: []net.IP{{91, 90, 122, 131}, {91, 90, 122, 132}, {91, 90, 122, 133}, {91, 90, 122, 134}, {91, 90, 122, 138}, {91, 90, 122, 139}, {91, 90, 122, 140}, {91, 90, 122, 142}, {91, 90, 122, 143}, {91, 90, 122, 145}}},
{Region: "Lithuania", Group: "Premium TCP Europe", Hostname: "97-1-lt.cg-dialup.net", IPs: []net.IP{{85, 206, 162, 209}, {85, 206, 162, 215}, {85, 206, 162, 218}, {85, 206, 162, 221}, {85, 206, 162, 222}, {85, 206, 165, 18}, {85, 206, 165, 20}, {85, 206, 165, 23}, {85, 206, 165, 26}, {85, 206, 165, 31}}},
{Region: "Lithuania", Group: "Premium UDP Europe", Hostname: "87-1-lt.cg-dialup.net", IPs: []net.IP{{85, 206, 162, 209}, {85, 206, 162, 210}, {85, 206, 162, 211}, {85, 206, 162, 212}, {85, 206, 162, 218}, {85, 206, 162, 221}, {85, 206, 165, 17}, {85, 206, 165, 23}, {85, 206, 165, 24}, {85, 206, 165, 30}}},
{Region: "Luxembourg", Group: "Premium TCP Europe", Hostname: "97-1-lu.cg-dialup.net", IPs: []net.IP{{5, 253, 204, 3}, {5, 253, 204, 14}, {5, 253, 204, 22}, {5, 253, 204, 25}, {5, 253, 204, 26}, {5, 253, 204, 28}, {5, 253, 204, 30}, {5, 253, 204, 41}, {5, 253, 204, 43}, {5, 253, 204, 45}}},
{Region: "Luxembourg", Group: "Premium UDP Europe", Hostname: "87-1-lu.cg-dialup.net", IPs: []net.IP{{5, 253, 204, 6}, {5, 253, 204, 12}, {5, 253, 204, 13}, {5, 253, 204, 26}, {5, 253, 204, 27}, {5, 253, 204, 36}, {5, 253, 204, 39}, {5, 253, 204, 41}, {5, 253, 204, 43}, {5, 253, 204, 46}}},
{Region: "Macao", Group: "Premium TCP Asia", Hostname: "96-1-mo.cg-dialup.net", IPs: []net.IP{{84, 252, 92, 131}, {84, 252, 92, 132}, {84, 252, 92, 134}, {84, 252, 92, 136}, {84, 252, 92, 138}, {84, 252, 92, 140}, {84, 252, 92, 141}, {84, 252, 92, 142}, {84, 252, 92, 143}, {84, 252, 92, 145}}},
{Region: "Macao", Group: "Premium UDP Asia", Hostname: "95-1-mo.cg-dialup.net", IPs: []net.IP{{84, 252, 92, 132}, {84, 252, 92, 134}, {84, 252, 92, 135}, {84, 252, 92, 136}, {84, 252, 92, 137}, {84, 252, 92, 138}, {84, 252, 92, 140}, {84, 252, 92, 141}, {84, 252, 92, 143}, {84, 252, 92, 144}}},
{Region: "Korea", Group: "Premium TCP Asia", Hostname: "96-1-kr.cg-dialup.net", IPs: []net.IP{{79, 110, 55, 131}, {79, 110, 55, 134}, {79, 110, 55, 141}, {79, 110, 55, 147}, {79, 110, 55, 148}, {79, 110, 55, 151}, {79, 110, 55, 152}, {79, 110, 55, 153}, {79, 110, 55, 155}, {79, 110, 55, 157}}},
{Region: "Korea", Group: "Premium UDP Asia", Hostname: "95-1-kr.cg-dialup.net", IPs: []net.IP{{79, 110, 55, 131}, {79, 110, 55, 133}, {79, 110, 55, 134}, {79, 110, 55, 136}, {79, 110, 55, 138}, {79, 110, 55, 140}, {79, 110, 55, 149}, {79, 110, 55, 151}, {79, 110, 55, 152}, {79, 110, 55, 157}}},
{Region: "Latvia", Group: "Premium TCP Europe", Hostname: "97-1-lv.cg-dialup.net", IPs: []net.IP{{109, 248, 148, 244}, {109, 248, 148, 245}, {109, 248, 148, 246}, {109, 248, 148, 247}, {109, 248, 148, 249}, {109, 248, 148, 250}, {109, 248, 148, 253}, {109, 248, 149, 22}, {109, 248, 149, 24}, {109, 248, 149, 25}}},
{Region: "Latvia", Group: "Premium UDP Europe", Hostname: "87-1-lv.cg-dialup.net", IPs: []net.IP{{109, 248, 148, 248}, {109, 248, 148, 250}, {109, 248, 148, 254}, {109, 248, 149, 19}, {109, 248, 149, 20}, {109, 248, 149, 22}, {109, 248, 149, 24}, {109, 248, 149, 26}, {109, 248, 149, 28}, {109, 248, 149, 30}}},
{Region: "Liechtenstein", Group: "Premium UDP Europe", Hostname: "87-1-li.cg-dialup.net", IPs: []net.IP{{91, 90, 122, 131}, {91, 90, 122, 134}, {91, 90, 122, 137}, {91, 90, 122, 138}, {91, 90, 122, 139}, {91, 90, 122, 140}, {91, 90, 122, 141}, {91, 90, 122, 142}, {91, 90, 122, 144}, {91, 90, 122, 145}}},
{Region: "Lithuania", Group: "Premium TCP Europe", Hostname: "97-1-lt.cg-dialup.net", IPs: []net.IP{{85, 206, 162, 212}, {85, 206, 162, 215}, {85, 206, 162, 219}, {85, 206, 162, 222}, {85, 206, 165, 17}, {85, 206, 165, 23}, {85, 206, 165, 25}, {85, 206, 165, 26}, {85, 206, 165, 30}, {85, 206, 165, 31}}},
{Region: "Lithuania", Group: "Premium UDP Europe", Hostname: "87-1-lt.cg-dialup.net", IPs: []net.IP{{85, 206, 162, 209}, {85, 206, 162, 210}, {85, 206, 162, 211}, {85, 206, 162, 213}, {85, 206, 162, 214}, {85, 206, 162, 217}, {85, 206, 162, 218}, {85, 206, 162, 220}, {85, 206, 165, 26}, {85, 206, 165, 30}}},
{Region: "Luxembourg", Group: "Premium UDP Europe", Hostname: "87-1-lu.cg-dialup.net", IPs: []net.IP{{5, 253, 204, 7}, {5, 253, 204, 10}, {5, 253, 204, 12}, {5, 253, 204, 23}, {5, 253, 204, 26}, {5, 253, 204, 30}, {5, 253, 204, 37}, {5, 253, 204, 39}, {5, 253, 204, 44}, {5, 253, 204, 45}}},
{Region: "Macao", Group: "Premium TCP Asia", Hostname: "96-1-mo.cg-dialup.net", IPs: []net.IP{{84, 252, 92, 131}, {84, 252, 92, 133}, {84, 252, 92, 135}, {84, 252, 92, 137}, {84, 252, 92, 138}, {84, 252, 92, 139}, {84, 252, 92, 141}, {84, 252, 92, 142}, {84, 252, 92, 144}, {84, 252, 92, 145}}},
{Region: "Macao", Group: "Premium UDP Asia", Hostname: "95-1-mo.cg-dialup.net", IPs: []net.IP{{84, 252, 92, 132}, {84, 252, 92, 134}, {84, 252, 92, 135}, {84, 252, 92, 136}, {84, 252, 92, 137}, {84, 252, 92, 139}, {84, 252, 92, 141}, {84, 252, 92, 143}, {84, 252, 92, 144}, {84, 252, 92, 145}}},
{Region: "Macedonia", Group: "Premium TCP Europe", Hostname: "97-1-mk.cg-dialup.net", IPs: []net.IP{{185, 225, 28, 3}, {185, 225, 28, 4}, {185, 225, 28, 5}, {185, 225, 28, 6}, {185, 225, 28, 7}, {185, 225, 28, 8}, {185, 225, 28, 9}, {185, 225, 28, 10}, {185, 225, 28, 11}, {185, 225, 28, 12}}},
{Region: "Macedonia", Group: "Premium UDP Europe", Hostname: "87-1-mk.cg-dialup.net", IPs: []net.IP{{185, 225, 28, 3}, {185, 225, 28, 4}, {185, 225, 28, 5}, {185, 225, 28, 6}, {185, 225, 28, 7}, {185, 225, 28, 8}, {185, 225, 28, 9}, {185, 225, 28, 10}, {185, 225, 28, 11}, {185, 225, 28, 12}}},
{Region: "Malaysia", Group: "Premium TCP Asia", Hostname: "96-1-my.cg-dialup.net", IPs: []net.IP{{146, 70, 15, 3}, {146, 70, 15, 4}, {146, 70, 15, 5}, {146, 70, 15, 6}, {146, 70, 15, 7}, {146, 70, 15, 10}, {146, 70, 15, 11}, {146, 70, 15, 13}, {146, 70, 15, 15}, {146, 70, 15, 16}}},
{Region: "Malta", Group: "Premium TCP Europe", Hostname: "97-1-mt.cg-dialup.net", IPs: []net.IP{{176, 125, 230, 131}, {176, 125, 230, 132}, {176, 125, 230, 134}, {176, 125, 230, 136}, {176, 125, 230, 137}, {176, 125, 230, 140}, {176, 125, 230, 141}, {176, 125, 230, 142}, {176, 125, 230, 144}, {176, 125, 230, 145}}},
{Region: "Malta", Group: "Premium UDP Europe", Hostname: "87-1-mt.cg-dialup.net", IPs: []net.IP{{176, 125, 230, 131}, {176, 125, 230, 134}, {176, 125, 230, 135}, {176, 125, 230, 138}, {176, 125, 230, 139}, {176, 125, 230, 140}, {176, 125, 230, 142}, {176, 125, 230, 143}, {176, 125, 230, 144}, {176, 125, 230, 145}}},
{Region: "Mexico", Group: "Premium TCP USA", Hostname: "93-1-mx.cg-dialup.net", IPs: []net.IP{{77, 81, 142, 130}, {77, 81, 142, 136}, {77, 81, 142, 146}, {77, 81, 142, 148}, {77, 81, 142, 150}, {77, 81, 142, 151}, {77, 81, 142, 152}, {77, 81, 142, 153}, {77, 81, 142, 154}, {77, 81, 142, 155}}},
{Region: "Mexico", Group: "Premium UDP USA", Hostname: "94-1-mx.cg-dialup.net", IPs: []net.IP{{77, 81, 142, 130}, {77, 81, 142, 136}, {77, 81, 142, 144}, {77, 81, 142, 146}, {77, 81, 142, 147}, {77, 81, 142, 150}, {77, 81, 142, 151}, {77, 81, 142, 153}, {77, 81, 142, 154}, {77, 81, 142, 155}}},
{Region: "Monaco", Group: "Premium TCP Europe", Hostname: "97-1-mc.cg-dialup.net", IPs: []net.IP{{95, 181, 233, 131}, {95, 181, 233, 132}, {95, 181, 233, 133}, {95, 181, 233, 135}, {95, 181, 233, 136}, {95, 181, 233, 137}, {95, 181, 233, 140}, {95, 181, 233, 141}, {95, 181, 233, 143}, {95, 181, 233, 144}}},
{Region: "Monaco", Group: "Premium UDP Europe", Hostname: "87-1-mc.cg-dialup.net", IPs: []net.IP{{95, 181, 233, 131}, {95, 181, 233, 132}, {95, 181, 233, 135}, {95, 181, 233, 136}, {95, 181, 233, 138}, {95, 181, 233, 139}, {95, 181, 233, 140}, {95, 181, 233, 142}, {95, 181, 233, 143}, {95, 181, 233, 144}}},
{Region: "Mongolia", Group: "Premium TCP Asia", Hostname: "96-1-mn.cg-dialup.net", IPs: []net.IP{{185, 253, 163, 131}, {185, 253, 163, 132}, {185, 253, 163, 133}, {185, 253, 163, 134}, {185, 253, 163, 136}, {185, 253, 163, 138}, {185, 253, 163, 139}, {185, 253, 163, 141}, {185, 253, 163, 142}, {185, 253, 163, 145}}},
{Region: "Mongolia", Group: "Premium UDP Asia", Hostname: "95-1-mn.cg-dialup.net", IPs: []net.IP{{185, 253, 163, 131}, {185, 253, 163, 132}, {185, 253, 163, 133}, {185, 253, 163, 134}, {185, 253, 163, 135}, {185, 253, 163, 136}, {185, 253, 163, 142}, {185, 253, 163, 143}, {185, 253, 163, 144}, {185, 253, 163, 145}}},
{Region: "Montenegro", Group: "Premium TCP Europe", Hostname: "97-1-me.cg-dialup.net", IPs: []net.IP{{176, 125, 229, 131}, {176, 125, 229, 133}, {176, 125, 229, 134}, {176, 125, 229, 135}, {176, 125, 229, 136}, {176, 125, 229, 138}, {176, 125, 229, 139}, {176, 125, 229, 141}, {176, 125, 229, 144}, {176, 125, 229, 145}}},
{Region: "Morocco", Group: "Premium UDP Europe", Hostname: "87-1-ma.cg-dialup.net", IPs: []net.IP{{95, 181, 232, 131}, {95, 181, 232, 132}, {95, 181, 232, 133}, {95, 181, 232, 134}, {95, 181, 232, 135}, {95, 181, 232, 136}, {95, 181, 232, 137}, {95, 181, 232, 139}, {95, 181, 232, 140}, {95, 181, 232, 143}}},
{Region: "Netherlands", Group: "Premium TCP Europe", Hostname: "97-1-nl.cg-dialup.net", IPs: []net.IP{{181, 214, 206, 26}, {181, 214, 206, 27}, {191, 96, 168, 57}, {191, 96, 168, 147}, {195, 78, 54, 20}, {195, 78, 54, 26}, {195, 78, 54, 28}, {195, 78, 54, 50}, {195, 78, 54, 109}, {195, 78, 54, 159}}},
{Region: "New Zealand", Group: "Premium UDP Asia", Hostname: "95-1-nz.cg-dialup.net", IPs: []net.IP{{114, 141, 194, 2}, {114, 141, 194, 3}, {114, 141, 194, 4}, {114, 141, 194, 5}, {114, 141, 194, 6}, {114, 141, 194, 7}, {114, 141, 194, 9}, {114, 141, 194, 11}, {114, 141, 194, 12}, {114, 141, 194, 13}}},
{Region: "Nigeria", Group: "Premium TCP Europe", Hostname: "97-1-ng.cg-dialup.net", IPs: []net.IP{{102, 165, 25, 68}, {102, 165, 25, 69}, {102, 165, 25, 70}, {102, 165, 25, 71}, {102, 165, 25, 72}, {102, 165, 25, 73}, {102, 165, 25, 74}, {102, 165, 25, 75}, {102, 165, 25, 76}, {102, 165, 25, 77}}},
{Region: "Nigeria", Group: "Premium UDP Europe", Hostname: "87-1-ng.cg-dialup.net", IPs: []net.IP{{102, 165, 25, 68}, {102, 165, 25, 69}, {102, 165, 25, 70}, {102, 165, 25, 71}, {102, 165, 25, 72}, {102, 165, 25, 73}, {102, 165, 25, 74}, {102, 165, 25, 76}, {102, 165, 25, 77}, {102, 165, 25, 78}}},
{Region: "Norway", Group: "Premium TCP Europe", Hostname: "97-1-no.cg-dialup.net", IPs: []net.IP{{45, 12, 223, 139}, {82, 102, 27, 91}, {82, 102, 27, 92}, {185, 206, 225, 229}, {185, 206, 225, 231}, {185, 206, 225, 236}, {185, 253, 97, 235}, {185, 253, 97, 245}, {185, 253, 97, 249}, {185, 253, 97, 251}}},
{Region: "Norway", Group: "Premium UDP Europe", Hostname: "87-1-no.cg-dialup.net", IPs: []net.IP{{45, 12, 223, 133}, {45, 12, 223, 137}, {45, 12, 223, 139}, {45, 12, 223, 140}, {185, 206, 225, 27}, {185, 206, 225, 28}, {185, 206, 225, 29}, {185, 206, 225, 230}, {185, 253, 97, 250}, {185, 253, 97, 251}}},
{Region: "Philippines", Group: "Premium TCP Asia", Hostname: "96-1-ph.cg-dialup.net", IPs: []net.IP{{188, 214, 125, 36}, {188, 214, 125, 38}, {188, 214, 125, 40}, {188, 214, 125, 41}, {188, 214, 125, 47}, {188, 214, 125, 49}, {188, 214, 125, 51}, {188, 214, 125, 53}, {188, 214, 125, 54}, {188, 214, 125, 61}}},
{Region: "Poland", Group: "Premium UDP Europe", Hostname: "87-1-pl.cg-dialup.net", IPs: []net.IP{{37, 120, 156, 4}, {37, 120, 156, 9}, {37, 120, 156, 10}, {37, 120, 156, 20}, {37, 120, 156, 21}, {37, 120, 156, 23}, {37, 120, 156, 26}, {51, 75, 56, 36}, {51, 75, 56, 37}, {51, 75, 56, 43}}},
{Region: "Qatar", Group: "Premium TCP Europe", Hostname: "97-1-qa.cg-dialup.net", IPs: []net.IP{{95, 181, 234, 131}, {95, 181, 234, 132}, {95, 181, 234, 134}, {95, 181, 234, 135}, {95, 181, 234, 136}, {95, 181, 234, 137}, {95, 181, 234, 138}, {95, 181, 234, 140}, {95, 181, 234, 142}, {95, 181, 234, 143}}},
{Region: "Qatar", Group: "Premium UDP Europe", Hostname: "87-1-qa.cg-dialup.net", IPs: []net.IP{{95, 181, 234, 132}, {95, 181, 234, 134}, {95, 181, 234, 135}, {95, 181, 234, 138}, {95, 181, 234, 139}, {95, 181, 234, 140}, {95, 181, 234, 141}, {95, 181, 234, 142}, {95, 181, 234, 143}, {95, 181, 234, 144}}},
{Region: "Russian Federation", Group: "Premium UDP Europe", Hostname: "87-1-ru.cg-dialup.net", IPs: []net.IP{{5, 8, 16, 69}, {5, 8, 16, 87}, {5, 8, 16, 88}, {5, 8, 16, 92}, {5, 8, 16, 109}, {5, 8, 16, 116}, {5, 8, 16, 118}, {5, 8, 16, 134}, {5, 8, 16, 136}, {5, 8, 16, 141}}},
{Region: "Saudi Arabia", Group: "Premium TCP Europe", Hostname: "97-1-sa.cg-dialup.net", IPs: []net.IP{{95, 181, 235, 132}, {95, 181, 235, 133}, {95, 181, 235, 134}, {95, 181, 235, 136}, {95, 181, 235, 137}, {95, 181, 235, 138}, {95, 181, 235, 139}, {95, 181, 235, 140}, {95, 181, 235, 141}, {95, 181, 235, 142}}},
{Region: "Serbia", Group: "Premium UDP Europe", Hostname: "87-1-rs.cg-dialup.net", IPs: []net.IP{{37, 120, 193, 179}, {37, 120, 193, 183}, {37, 120, 193, 187}, {37, 120, 193, 190}, {141, 98, 103, 37}, {141, 98, 103, 38}, {141, 98, 103, 39}, {141, 98, 103, 40}, {141, 98, 103, 43}, {141, 98, 103, 46}}},
{Region: "Malaysia", Group: "Premium TCP Asia", Hostname: "96-1-my.cg-dialup.net", IPs: []net.IP{{146, 70, 15, 4}, {146, 70, 15, 6}, {146, 70, 15, 8}, {146, 70, 15, 9}, {146, 70, 15, 10}, {146, 70, 15, 11}, {146, 70, 15, 12}, {146, 70, 15, 13}, {146, 70, 15, 15}, {146, 70, 15, 16}}},
{Region: "Malaysia", Group: "Premium UDP Asia", Hostname: "95-1-my.cg-dialup.net", IPs: []net.IP{{146, 70, 15, 3}, {146, 70, 15, 4}, {146, 70, 15, 5}, {146, 70, 15, 6}, {146, 70, 15, 7}, {146, 70, 15, 8}, {146, 70, 15, 10}, {146, 70, 15, 12}, {146, 70, 15, 15}, {146, 70, 15, 16}}},
{Region: "Malta", Group: "Premium TCP Europe", Hostname: "97-1-mt.cg-dialup.net", IPs: []net.IP{{176, 125, 230, 133}, {176, 125, 230, 135}, {176, 125, 230, 136}, {176, 125, 230, 137}, {176, 125, 230, 138}, {176, 125, 230, 140}, {176, 125, 230, 142}, {176, 125, 230, 143}, {176, 125, 230, 144}, {176, 125, 230, 145}}},
{Region: "Malta", Group: "Premium UDP Europe", Hostname: "87-1-mt.cg-dialup.net", IPs: []net.IP{{176, 125, 230, 131}, {176, 125, 230, 133}, {176, 125, 230, 134}, {176, 125, 230, 136}, {176, 125, 230, 137}, {176, 125, 230, 138}, {176, 125, 230, 139}, {176, 125, 230, 140}, {176, 125, 230, 144}, {176, 125, 230, 145}}},
{Region: "Mexico", Group: "Premium TCP USA", Hostname: "93-1-mx.cg-dialup.net", IPs: []net.IP{{77, 81, 142, 132}, {77, 81, 142, 134}, {77, 81, 142, 136}, {77, 81, 142, 139}, {77, 81, 142, 142}, {77, 81, 142, 154}, {77, 81, 142, 155}, {77, 81, 142, 157}, {77, 81, 142, 158}, {77, 81, 142, 159}}},
{Region: "Mexico", Group: "Premium UDP USA", Hostname: "94-1-mx.cg-dialup.net", IPs: []net.IP{{77, 81, 142, 130}, {77, 81, 142, 131}, {77, 81, 142, 132}, {77, 81, 142, 139}, {77, 81, 142, 141}, {77, 81, 142, 142}, {77, 81, 142, 146}, {77, 81, 142, 147}, {77, 81, 142, 154}, {77, 81, 142, 159}}},
{Region: "Moldova", Group: "Premium TCP Europe", Hostname: "97-1-md.cg-dialup.net", IPs: []net.IP{{178, 175, 130, 243}, {178, 175, 130, 244}, {178, 175, 130, 245}, {178, 175, 130, 246}, {178, 175, 130, 251}, {178, 175, 130, 254}, {178, 175, 142, 131}, {178, 175, 142, 132}, {178, 175, 142, 133}, {178, 175, 142, 134}}},
{Region: "Moldova", Group: "Premium UDP Europe", Hostname: "87-1-md.cg-dialup.net", IPs: []net.IP{{178, 175, 130, 243}, {178, 175, 130, 244}, {178, 175, 130, 246}, {178, 175, 130, 250}, {178, 175, 130, 251}, {178, 175, 130, 253}, {178, 175, 130, 254}, {178, 175, 142, 132}, {178, 175, 142, 133}, {178, 175, 142, 134}}},
{Region: "Monaco", Group: "Premium TCP Europe", Hostname: "97-1-mc.cg-dialup.net", IPs: []net.IP{{95, 181, 233, 131}, {95, 181, 233, 132}, {95, 181, 233, 133}, {95, 181, 233, 137}, {95, 181, 233, 138}, {95, 181, 233, 139}, {95, 181, 233, 140}, {95, 181, 233, 141}, {95, 181, 233, 143}, {95, 181, 233, 144}}},
{Region: "Monaco", Group: "Premium UDP Europe", Hostname: "87-1-mc.cg-dialup.net", IPs: []net.IP{{95, 181, 233, 132}, {95, 181, 233, 135}, {95, 181, 233, 136}, {95, 181, 233, 137}, {95, 181, 233, 138}, {95, 181, 233, 139}, {95, 181, 233, 141}, {95, 181, 233, 142}, {95, 181, 233, 143}, {95, 181, 233, 144}}},
{Region: "Mongolia", Group: "Premium TCP Asia", Hostname: "96-1-mn.cg-dialup.net", IPs: []net.IP{{185, 253, 163, 132}, {185, 253, 163, 133}, {185, 253, 163, 135}, {185, 253, 163, 136}, {185, 253, 163, 139}, {185, 253, 163, 140}, {185, 253, 163, 141}, {185, 253, 163, 142}, {185, 253, 163, 143}, {185, 253, 163, 144}}},
{Region: "Mongolia", Group: "Premium UDP Asia", Hostname: "95-1-mn.cg-dialup.net", IPs: []net.IP{{185, 253, 163, 131}, {185, 253, 163, 133}, {185, 253, 163, 134}, {185, 253, 163, 137}, {185, 253, 163, 138}, {185, 253, 163, 139}, {185, 253, 163, 140}, {185, 253, 163, 141}, {185, 253, 163, 142}, {185, 253, 163, 144}}},
{Region: "Montenegro", Group: "Premium TCP Europe", Hostname: "97-1-me.cg-dialup.net", IPs: []net.IP{{176, 125, 229, 131}, {176, 125, 229, 135}, {176, 125, 229, 137}, {176, 125, 229, 138}, {176, 125, 229, 140}, {176, 125, 229, 141}, {176, 125, 229, 142}, {176, 125, 229, 143}, {176, 125, 229, 144}, {176, 125, 229, 145}}},
{Region: "Montenegro", Group: "Premium UDP Europe", Hostname: "87-1-me.cg-dialup.net", IPs: []net.IP{{176, 125, 229, 131}, {176, 125, 229, 134}, {176, 125, 229, 136}, {176, 125, 229, 137}, {176, 125, 229, 138}, {176, 125, 229, 139}, {176, 125, 229, 140}, {176, 125, 229, 141}, {176, 125, 229, 143}, {176, 125, 229, 144}}},
{Region: "Morocco", Group: "Premium TCP Europe", Hostname: "97-1-ma.cg-dialup.net", IPs: []net.IP{{95, 181, 232, 132}, {95, 181, 232, 133}, {95, 181, 232, 134}, {95, 181, 232, 136}, {95, 181, 232, 137}, {95, 181, 232, 138}, {95, 181, 232, 139}, {95, 181, 232, 140}, {95, 181, 232, 141}, {95, 181, 232, 144}}},
{Region: "Morocco", Group: "Premium UDP Europe", Hostname: "87-1-ma.cg-dialup.net", IPs: []net.IP{{95, 181, 232, 131}, {95, 181, 232, 132}, {95, 181, 232, 133}, {95, 181, 232, 135}, {95, 181, 232, 137}, {95, 181, 232, 139}, {95, 181, 232, 140}, {95, 181, 232, 141}, {95, 181, 232, 142}, {95, 181, 232, 143}}},
{Region: "Netherlands", Group: "Premium TCP Europe", Hostname: "97-1-nl.cg-dialup.net", IPs: []net.IP{{84, 17, 47, 98}, {181, 214, 206, 22}, {181, 214, 206, 27}, {181, 214, 206, 36}, {195, 78, 54, 10}, {195, 78, 54, 20}, {195, 78, 54, 43}, {195, 78, 54, 50}, {195, 78, 54, 119}, {195, 181, 172, 78}}},
{Region: "Netherlands", Group: "Premium UDP Europe", Hostname: "87-1-nl.cg-dialup.net", IPs: []net.IP{{84, 17, 47, 110}, {181, 214, 206, 29}, {181, 214, 206, 42}, {195, 78, 54, 8}, {195, 78, 54, 19}, {195, 78, 54, 47}, {195, 78, 54, 110}, {195, 78, 54, 141}, {195, 78, 54, 143}, {195, 78, 54, 157}}},
{Region: "New Zealand", Group: "Premium TCP Asia", Hostname: "96-1-nz.cg-dialup.net", IPs: []net.IP{{43, 250, 207, 98}, {43, 250, 207, 99}, {43, 250, 207, 100}, {43, 250, 207, 101}, {43, 250, 207, 102}, {43, 250, 207, 103}, {43, 250, 207, 105}, {43, 250, 207, 106}, {43, 250, 207, 108}, {43, 250, 207, 109}}},
{Region: "New Zealand", Group: "Premium UDP Asia", Hostname: "95-1-nz.cg-dialup.net", IPs: []net.IP{{43, 250, 207, 98}, {43, 250, 207, 99}, {43, 250, 207, 102}, {43, 250, 207, 104}, {43, 250, 207, 105}, {43, 250, 207, 106}, {43, 250, 207, 107}, {43, 250, 207, 108}, {43, 250, 207, 109}, {43, 250, 207, 110}}},
{Region: "Nigeria", Group: "Premium TCP Europe", Hostname: "97-1-ng.cg-dialup.net", IPs: []net.IP{{102, 165, 25, 68}, {102, 165, 25, 69}, {102, 165, 25, 70}, {102, 165, 25, 71}, {102, 165, 25, 72}, {102, 165, 25, 73}, {102, 165, 25, 75}, {102, 165, 25, 76}, {102, 165, 25, 77}, {102, 165, 25, 78}}},
{Region: "Nigeria", Group: "Premium UDP Europe", Hostname: "87-1-ng.cg-dialup.net", IPs: []net.IP{{102, 165, 25, 68}, {102, 165, 25, 69}, {102, 165, 25, 70}, {102, 165, 25, 71}, {102, 165, 25, 72}, {102, 165, 25, 74}, {102, 165, 25, 75}, {102, 165, 25, 76}, {102, 165, 25, 77}, {102, 165, 25, 78}}},
{Region: "Norway", Group: "Premium TCP Europe", Hostname: "97-1-no.cg-dialup.net", IPs: []net.IP{{45, 12, 223, 137}, {45, 12, 223, 140}, {185, 206, 225, 29}, {185, 206, 225, 231}, {185, 253, 97, 234}, {185, 253, 97, 236}, {185, 253, 97, 238}, {185, 253, 97, 244}, {185, 253, 97, 250}, {185, 253, 97, 254}}},
{Region: "Norway", Group: "Premium UDP Europe", Hostname: "87-1-no.cg-dialup.net", IPs: []net.IP{{45, 12, 223, 133}, {45, 12, 223, 134}, {45, 12, 223, 142}, {185, 206, 225, 227}, {185, 206, 225, 228}, {185, 206, 225, 231}, {185, 206, 225, 235}, {185, 253, 97, 237}, {185, 253, 97, 246}, {185, 253, 97, 254}}},
{Region: "Pakistan", Group: "Premium TCP Asia", Hostname: "96-1-pk.cg-dialup.net", IPs: []net.IP{{146, 70, 12, 3}, {146, 70, 12, 4}, {146, 70, 12, 6}, {146, 70, 12, 8}, {146, 70, 12, 9}, {146, 70, 12, 10}, {146, 70, 12, 11}, {146, 70, 12, 12}, {146, 70, 12, 13}, {146, 70, 12, 14}}},
{Region: "Pakistan", Group: "Premium UDP Asia", Hostname: "95-1-pk.cg-dialup.net", IPs: []net.IP{{146, 70, 12, 4}, {146, 70, 12, 5}, {146, 70, 12, 6}, {146, 70, 12, 7}, {146, 70, 12, 8}, {146, 70, 12, 10}, {146, 70, 12, 11}, {146, 70, 12, 12}, {146, 70, 12, 13}, {146, 70, 12, 14}}},
{Region: "Panama", Group: "Premium TCP Europe", Hostname: "97-1-pa.cg-dialup.net", IPs: []net.IP{{91, 90, 126, 131}, {91, 90, 126, 132}, {91, 90, 126, 133}, {91, 90, 126, 134}, {91, 90, 126, 136}, {91, 90, 126, 138}, {91, 90, 126, 139}, {91, 90, 126, 141}, {91, 90, 126, 142}, {91, 90, 126, 145}}},
{Region: "Panama", Group: "Premium UDP Europe", Hostname: "87-1-pa.cg-dialup.net", IPs: []net.IP{{91, 90, 126, 131}, {91, 90, 126, 133}, {91, 90, 126, 134}, {91, 90, 126, 135}, {91, 90, 126, 136}, {91, 90, 126, 138}, {91, 90, 126, 140}, {91, 90, 126, 141}, {91, 90, 126, 142}, {91, 90, 126, 145}}},
{Region: "Philippines", Group: "Premium TCP Asia", Hostname: "96-1-ph.cg-dialup.net", IPs: []net.IP{{188, 214, 125, 37}, {188, 214, 125, 38}, {188, 214, 125, 40}, {188, 214, 125, 43}, {188, 214, 125, 44}, {188, 214, 125, 45}, {188, 214, 125, 52}, {188, 214, 125, 55}, {188, 214, 125, 61}, {188, 214, 125, 62}}},
{Region: "Philippines", Group: "Premium UDP Asia", Hostname: "95-1-ph.cg-dialup.net", IPs: []net.IP{{188, 214, 125, 37}, {188, 214, 125, 40}, {188, 214, 125, 46}, {188, 214, 125, 49}, {188, 214, 125, 52}, {188, 214, 125, 54}, {188, 214, 125, 57}, {188, 214, 125, 58}, {188, 214, 125, 61}, {188, 214, 125, 62}}},
{Region: "Poland", Group: "Premium TCP Europe", Hostname: "97-1-pl.cg-dialup.net", IPs: []net.IP{{138, 199, 59, 132}, {138, 199, 59, 136}, {138, 199, 59, 137}, {138, 199, 59, 143}, {138, 199, 59, 144}, {138, 199, 59, 152}, {138, 199, 59, 153}, {138, 199, 59, 166}, {138, 199, 59, 174}, {138, 199, 59, 175}}},
{Region: "Poland", Group: "Premium UDP Europe", Hostname: "87-1-pl.cg-dialup.net", IPs: []net.IP{{138, 199, 59, 130}, {138, 199, 59, 136}, {138, 199, 59, 148}, {138, 199, 59, 149}, {138, 199, 59, 153}, {138, 199, 59, 156}, {138, 199, 59, 157}, {138, 199, 59, 164}, {138, 199, 59, 171}, {138, 199, 59, 173}}},
{Region: "Portugal", Group: "Premium TCP Europe", Hostname: "97-1-pt.cg-dialup.net", IPs: []net.IP{{89, 26, 243, 112}, {89, 26, 243, 115}, {89, 26, 243, 195}, {89, 26, 243, 216}, {89, 26, 243, 218}, {89, 26, 243, 220}, {89, 26, 243, 222}, {89, 26, 243, 223}, {89, 26, 243, 225}, {89, 26, 243, 228}}},
{Region: "Portugal", Group: "Premium UDP Europe", Hostname: "87-1-pt.cg-dialup.net", IPs: []net.IP{{89, 26, 243, 99}, {89, 26, 243, 113}, {89, 26, 243, 115}, {89, 26, 243, 195}, {89, 26, 243, 199}, {89, 26, 243, 216}, {89, 26, 243, 219}, {89, 26, 243, 225}, {89, 26, 243, 226}, {89, 26, 243, 227}}},
{Region: "Qatar", Group: "Premium TCP Europe", Hostname: "97-1-qa.cg-dialup.net", IPs: []net.IP{{95, 181, 234, 133}, {95, 181, 234, 135}, {95, 181, 234, 136}, {95, 181, 234, 137}, {95, 181, 234, 138}, {95, 181, 234, 139}, {95, 181, 234, 140}, {95, 181, 234, 141}, {95, 181, 234, 142}, {95, 181, 234, 143}}},
{Region: "Qatar", Group: "Premium UDP Europe", Hostname: "87-1-qa.cg-dialup.net", IPs: []net.IP{{95, 181, 234, 131}, {95, 181, 234, 132}, {95, 181, 234, 133}, {95, 181, 234, 134}, {95, 181, 234, 135}, {95, 181, 234, 137}, {95, 181, 234, 138}, {95, 181, 234, 139}, {95, 181, 234, 142}, {95, 181, 234, 143}}},
{Region: "Russian Federation", Group: "Premium TCP Europe", Hostname: "97-1-ru.cg-dialup.net", IPs: []net.IP{{5, 8, 16, 72}, {5, 8, 16, 74}, {5, 8, 16, 84}, {5, 8, 16, 85}, {5, 8, 16, 123}, {5, 8, 16, 124}, {5, 8, 16, 132}, {146, 70, 52, 35}, {146, 70, 52, 44}, {146, 70, 52, 54}}},
{Region: "Russian Federation", Group: "Premium UDP Europe", Hostname: "87-1-ru.cg-dialup.net", IPs: []net.IP{{5, 8, 16, 75}, {5, 8, 16, 87}, {5, 8, 16, 99}, {5, 8, 16, 110}, {5, 8, 16, 138}, {146, 70, 52, 29}, {146, 70, 52, 52}, {146, 70, 52, 58}, {146, 70, 52, 59}, {146, 70, 52, 67}}},
{Region: "Saudi Arabia", Group: "Premium TCP Europe", Hostname: "97-1-sa.cg-dialup.net", IPs: []net.IP{{95, 181, 235, 131}, {95, 181, 235, 133}, {95, 181, 235, 134}, {95, 181, 235, 135}, {95, 181, 235, 137}, {95, 181, 235, 138}, {95, 181, 235, 139}, {95, 181, 235, 140}, {95, 181, 235, 141}, {95, 181, 235, 142}}},
{Region: "Saudi Arabia", Group: "Premium UDP Europe", Hostname: "87-1-sa.cg-dialup.net", IPs: []net.IP{{95, 181, 235, 131}, {95, 181, 235, 132}, {95, 181, 235, 134}, {95, 181, 235, 135}, {95, 181, 235, 136}, {95, 181, 235, 137}, {95, 181, 235, 138}, {95, 181, 235, 139}, {95, 181, 235, 141}, {95, 181, 235, 144}}},
{Region: "Serbia", Group: "Premium TCP Europe", Hostname: "97-1-rs.cg-dialup.net", IPs: []net.IP{{37, 120, 193, 179}, {37, 120, 193, 186}, {37, 120, 193, 188}, {37, 120, 193, 190}, {141, 98, 103, 36}, {141, 98, 103, 38}, {141, 98, 103, 39}, {141, 98, 103, 43}, {141, 98, 103, 44}, {141, 98, 103, 46}}},
{Region: "Serbia", Group: "Premium UDP Europe", Hostname: "87-1-rs.cg-dialup.net", IPs: []net.IP{{37, 120, 193, 180}, {37, 120, 193, 186}, {37, 120, 193, 187}, {37, 120, 193, 188}, {37, 120, 193, 189}, {37, 120, 193, 190}, {141, 98, 103, 35}, {141, 98, 103, 36}, {141, 98, 103, 39}, {141, 98, 103, 41}}},
{Region: "Singapore", Group: "Premium TCP Asia", Hostname: "96-1-sg.cg-dialup.net", IPs: []net.IP{{84, 17, 39, 162}, {84, 17, 39, 165}, {84, 17, 39, 168}, {84, 17, 39, 171}, {84, 17, 39, 175}, {84, 17, 39, 177}, {84, 17, 39, 178}, {84, 17, 39, 181}, {84, 17, 39, 183}, {84, 17, 39, 185}}},
{Region: "Singapore", Group: "Premium UDP Asia", Hostname: "95-1-sg.cg-dialup.net", IPs: []net.IP{{84, 17, 39, 162}, {84, 17, 39, 165}, {84, 17, 39, 166}, {84, 17, 39, 167}, {84, 17, 39, 171}, {84, 17, 39, 174}, {84, 17, 39, 175}, {84, 17, 39, 178}, {84, 17, 39, 180}, {84, 17, 39, 185}}},
{Region: "Slovakia", Group: "Premium TCP Europe", Hostname: "97-1-sk.cg-dialup.net", IPs: []net.IP{{185, 245, 85, 227}, {185, 245, 85, 228}, {185, 245, 85, 229}, {185, 245, 85, 230}, {185, 245, 85, 231}, {185, 245, 85, 232}, {185, 245, 85, 233}, {185, 245, 85, 234}, {185, 245, 85, 235}, {185, 245, 85, 236}}},
{Region: "Slovakia", Group: "Premium UDP Europe", Hostname: "87-1-sk.cg-dialup.net", IPs: []net.IP{{185, 245, 85, 227}, {185, 245, 85, 228}, {185, 245, 85, 229}, {185, 245, 85, 230}, {185, 245, 85, 231}, {185, 245, 85, 232}, {185, 245, 85, 233}, {185, 245, 85, 234}, {185, 245, 85, 235}, {185, 245, 85, 236}}},
{Region: "Slovenia", Group: "Premium TCP Europe", Hostname: "97-1-si.cg-dialup.net", IPs: []net.IP{{195, 80, 150, 211}, {195, 80, 150, 212}, {195, 80, 150, 213}, {195, 80, 150, 214}, {195, 80, 150, 215}, {195, 80, 150, 216}, {195, 80, 150, 219}, {195, 80, 150, 220}, {195, 80, 150, 221}, {195, 80, 150, 222}}},
{Region: "Slovenia", Group: "Premium UDP Europe", Hostname: "87-1-si.cg-dialup.net", IPs: []net.IP{{195, 80, 150, 211}, {195, 80, 150, 212}, {195, 80, 150, 213}, {195, 80, 150, 215}, {195, 80, 150, 216}, {195, 80, 150, 217}, {195, 80, 150, 218}, {195, 80, 150, 219}, {195, 80, 150, 220}, {195, 80, 150, 221}}},
{Region: "South Africa", Group: "Premium TCP Asia", Hostname: "96-1-za.cg-dialup.net", IPs: []net.IP{{154, 127, 50, 215}, {154, 127, 50, 216}, {154, 127, 50, 217}, {154, 127, 50, 220}, {154, 127, 50, 222}, {154, 127, 60, 194}, {154, 127, 60, 196}, {154, 127, 60, 198}, {154, 127, 60, 199}, {154, 127, 60, 202}}},
{Region: "Slovenia", Group: "Premium TCP Europe", Hostname: "97-1-si.cg-dialup.net", IPs: []net.IP{{195, 80, 150, 211}, {195, 80, 150, 212}, {195, 80, 150, 214}, {195, 80, 150, 215}, {195, 80, 150, 216}, {195, 80, 150, 217}, {195, 80, 150, 218}, {195, 80, 150, 219}, {195, 80, 150, 221}, {195, 80, 150, 222}}},
{Region: "Slovenia", Group: "Premium UDP Europe", Hostname: "87-1-si.cg-dialup.net", IPs: []net.IP{{195, 80, 150, 211}, {195, 80, 150, 212}, {195, 80, 150, 214}, {195, 80, 150, 215}, {195, 80, 150, 216}, {195, 80, 150, 217}, {195, 80, 150, 219}, {195, 80, 150, 220}, {195, 80, 150, 221}, {195, 80, 150, 222}}},
{Region: "South Africa", Group: "Premium TCP Asia", Hostname: "96-1-za.cg-dialup.net", IPs: []net.IP{{154, 127, 50, 212}, {154, 127, 50, 215}, {154, 127, 50, 217}, {154, 127, 50, 219}, {154, 127, 50, 220}, {154, 127, 50, 222}, {154, 127, 60, 196}, {154, 127, 60, 198}, {154, 127, 60, 199}, {154, 127, 60, 200}}},
{Region: "South Africa", Group: "Premium TCP Europe", Hostname: "97-1-za.cg-dialup.net", IPs: []net.IP{{197, 85, 7, 26}, {197, 85, 7, 27}, {197, 85, 7, 28}, {197, 85, 7, 29}, {197, 85, 7, 30}, {197, 85, 7, 31}, {197, 85, 7, 131}, {197, 85, 7, 132}, {197, 85, 7, 133}, {197, 85, 7, 134}}},
{Region: "South Africa", Group: "Premium UDP Asia", Hostname: "95-1-za.cg-dialup.net", IPs: []net.IP{{154, 127, 50, 210}, {154, 127, 50, 214}, {154, 127, 50, 218}, {154, 127, 50, 219}, {154, 127, 50, 220}, {154, 127, 50, 221}, {154, 127, 50, 222}, {154, 127, 60, 195}, {154, 127, 60, 199}, {154, 127, 60, 206}}},
{Region: "South Africa", Group: "Premium UDP Europe", Hostname: "87-1-za.cg-dialup.net", IPs: []net.IP{{197, 85, 7, 26}, {197, 85, 7, 27}, {197, 85, 7, 28}, {197, 85, 7, 29}, {197, 85, 7, 30}, {197, 85, 7, 31}, {197, 85, 7, 131}, {197, 85, 7, 132}, {197, 85, 7, 133}, {197, 85, 7, 134}}},
{Region: "Spain", Group: "Premium TCP Europe", Hostname: "97-1-es.cg-dialup.net", IPs: []net.IP{{37, 120, 142, 166}, {37, 120, 142, 171}, {82, 102, 26, 197}, {82, 102, 26, 199}, {82, 102, 26, 204}, {84, 17, 62, 135}, {84, 17, 62, 146}, {84, 17, 62, 153}, {185, 93, 3, 106}, {185, 253, 99, 203}}},
{Region: "Spain", Group: "Premium UDP Europe", Hostname: "87-1-es.cg-dialup.net", IPs: []net.IP{{37, 120, 142, 45}, {37, 120, 142, 53}, {37, 120, 142, 150}, {37, 120, 142, 151}, {82, 102, 26, 215}, {82, 102, 26, 221}, {84, 17, 62, 131}, {84, 17, 62, 153}, {185, 93, 3, 105}, {185, 93, 3, 112}}},
{Region: "Sri Lanka", Group: "Premium TCP Europe", Hostname: "97-1-lk.cg-dialup.net", IPs: []net.IP{{95, 181, 239, 131}, {95, 181, 239, 132}, {95, 181, 239, 134}, {95, 181, 239, 135}, {95, 181, 239, 136}, {95, 181, 239, 137}, {95, 181, 239, 139}, {95, 181, 239, 140}, {95, 181, 239, 142}, {95, 181, 239, 144}}},
{Region: "Sri Lanka", Group: "Premium UDP Europe", Hostname: "87-1-lk.cg-dialup.net", IPs: []net.IP{{95, 181, 239, 133}, {95, 181, 239, 134}, {95, 181, 239, 135}, {95, 181, 239, 138}, {95, 181, 239, 139}, {95, 181, 239, 140}, {95, 181, 239, 141}, {95, 181, 239, 142}, {95, 181, 239, 143}, {95, 181, 239, 144}}},
{Region: "Sweden", Group: "Premium TCP Europe", Hostname: "97-1-se.cg-dialup.net", IPs: []net.IP{{188, 126, 73, 198}, {188, 126, 79, 5}, {188, 126, 79, 6}, {188, 126, 79, 11}, {188, 126, 79, 15}, {195, 246, 120, 144}, {195, 246, 120, 148}, {195, 246, 120, 156}, {195, 246, 120, 158}, {195, 246, 120, 165}}},
{Region: "Sweden", Group: "Premium UDP Europe", Hostname: "87-1-se.cg-dialup.net", IPs: []net.IP{{188, 126, 73, 208}, {188, 126, 73, 219}, {188, 126, 73, 222}, {188, 126, 79, 5}, {188, 126, 79, 9}, {188, 126, 79, 17}, {188, 126, 79, 24}, {188, 126, 79, 25}, {195, 246, 120, 148}, {195, 246, 120, 154}}},
{Region: "Switzerland", Group: "Premium TCP Europe", Hostname: "97-1-ch.cg-dialup.net", IPs: []net.IP{{84, 17, 52, 8}, {84, 17, 52, 33}, {84, 17, 52, 35}, {84, 17, 52, 47}, {84, 17, 52, 66}, {84, 17, 52, 72}, {185, 32, 222, 10}, {185, 32, 222, 11}, {185, 32, 222, 13}, {185, 32, 222, 113}}},
{Region: "Taiwan", Group: "Premium TCP Asia", Hostname: "96-1-tw.cg-dialup.net", IPs: []net.IP{{45, 133, 181, 99}, {45, 133, 181, 100}, {45, 133, 181, 105}, {45, 133, 181, 106}, {45, 133, 181, 114}, {45, 133, 181, 119}, {45, 133, 181, 120}, {45, 133, 181, 121}, {45, 133, 181, 123}, {45, 133, 181, 126}}},
{Region: "Thailand", Group: "Premium TCP Asia", Hostname: "96-1-th.cg-dialup.net", IPs: []net.IP{{146, 70, 13, 5}, {146, 70, 13, 6}, {146, 70, 13, 7}, {146, 70, 13, 8}, {146, 70, 13, 10}, {146, 70, 13, 11}, {146, 70, 13, 12}, {146, 70, 13, 13}, {146, 70, 13, 15}, {146, 70, 13, 16}}},
{Region: "Thailand", Group: "Premium UDP Asia", Hostname: "95-1-th.cg-dialup.net", IPs: []net.IP{{146, 70, 13, 3}, {146, 70, 13, 4}, {146, 70, 13, 5}, {146, 70, 13, 6}, {146, 70, 13, 7}, {146, 70, 13, 8}, {146, 70, 13, 11}, {146, 70, 13, 13}, {146, 70, 13, 15}, {146, 70, 13, 16}}},
{Region: "Turkey", Group: "Premium TCP Europe", Hostname: "97-1-tr.cg-dialup.net", IPs: []net.IP{{188, 213, 34, 5}, {188, 213, 34, 8}, {188, 213, 34, 10}, {188, 213, 34, 12}, {188, 213, 34, 29}, {188, 213, 34, 35}, {188, 213, 34, 39}, {188, 213, 34, 40}, {188, 213, 34, 41}, {188, 213, 34, 44}}},
{Region: "Turkey", Group: "Premium UDP Europe", Hostname: "87-1-tr.cg-dialup.net", IPs: []net.IP{{188, 213, 34, 5}, {188, 213, 34, 13}, {188, 213, 34, 14}, {188, 213, 34, 17}, {188, 213, 34, 19}, {188, 213, 34, 27}, {188, 213, 34, 44}, {188, 213, 34, 101}, {188, 213, 34, 103}, {188, 213, 34, 108}}},
{Region: "Ukraine", Group: "Premium TCP Europe", Hostname: "97-1-ua.cg-dialup.net", IPs: []net.IP{{31, 28, 163, 39}, {31, 28, 163, 44}, {31, 28, 163, 50}, {62, 149, 7, 162}, {62, 149, 7, 169}, {62, 149, 29, 37}, {62, 149, 29, 41}, {62, 149, 29, 45}, {62, 149, 29, 50}, {62, 149, 29, 57}}},
{Region: "United Arab Emirates", Group: "Premium TCP Europe", Hostname: "97-1-ae.cg-dialup.net", IPs: []net.IP{{217, 138, 193, 179}, {217, 138, 193, 180}, {217, 138, 193, 181}, {217, 138, 193, 182}, {217, 138, 193, 185}, {217, 138, 193, 186}, {217, 138, 193, 187}, {217, 138, 193, 188}, {217, 138, 193, 189}, {217, 138, 193, 190}}},
{Region: "United Kingdom", Group: "Premium TCP Europe", Hostname: "97-1-gb.cg-dialup.net", IPs: []net.IP{{45, 133, 172, 115}, {45, 133, 172, 137}, {95, 154, 200, 175}, {181, 215, 176, 248}, {191, 101, 209, 84}, {191, 101, 209, 111}, {191, 101, 209, 119}, {191, 101, 209, 136}, {194, 110, 13, 137}, {194, 110, 13, 149}}},
{Region: "United States", Group: "Premium UDP USA", Hostname: "94-1-us.cg-dialup.net", IPs: []net.IP{{89, 187, 182, 22}, {108, 59, 0, 154}, {154, 21, 208, 153}, {154, 21, 208, 175}, {156, 146, 37, 17}, {156, 146, 37, 81}, {156, 146, 49, 145}, {156, 146, 59, 78}, {184, 170, 240, 202}, {199, 115, 119, 247}}},
{Region: "Venezuela", Group: "Premium TCP USA", Hostname: "93-1-ve.cg-dialup.net", IPs: []net.IP{{95, 181, 237, 131}, {95, 181, 237, 133}, {95, 181, 237, 134}, {95, 181, 237, 135}, {95, 181, 237, 136}, {95, 181, 237, 138}, {95, 181, 237, 140}, {95, 181, 237, 141}, {95, 181, 237, 143}, {95, 181, 237, 144}}},
{Region: "Venezuela", Group: "Premium UDP USA", Hostname: "94-1-ve.cg-dialup.net", IPs: []net.IP{{95, 181, 237, 131}, {95, 181, 237, 133}, {95, 181, 237, 134}, {95, 181, 237, 137}, {95, 181, 237, 138}, {95, 181, 237, 139}, {95, 181, 237, 140}, {95, 181, 237, 141}, {95, 181, 237, 142}, {95, 181, 237, 144}}},
{Region: "Vietnam", Group: "Premium TCP Asia", Hostname: "96-1-vn.cg-dialup.net", IPs: []net.IP{{188, 214, 152, 99}, {188, 214, 152, 100}, {188, 214, 152, 101}, {188, 214, 152, 102}, {188, 214, 152, 103}, {188, 214, 152, 104}, {188, 214, 152, 106}, {188, 214, 152, 107}, {188, 214, 152, 108}, {188, 214, 152, 109}}},
{Region: "Vietnam", Group: "Premium UDP Asia", Hostname: "95-1-vn.cg-dialup.net", IPs: []net.IP{{188, 214, 152, 99}, {188, 214, 152, 100}, {188, 214, 152, 101}, {188, 214, 152, 102}, {188, 214, 152, 104}, {188, 214, 152, 105}, {188, 214, 152, 106}, {188, 214, 152, 107}, {188, 214, 152, 109}, {188, 214, 152, 110}}},
{Region: "Spain", Group: "Premium TCP Europe", Hostname: "97-1-es.cg-dialup.net", IPs: []net.IP{{37, 120, 142, 41}, {37, 120, 142, 52}, {37, 120, 142, 55}, {37, 120, 142, 61}, {37, 120, 142, 173}, {84, 17, 62, 131}, {84, 17, 62, 142}, {84, 17, 62, 144}, {185, 93, 3, 108}, {185, 93, 3, 114}}},
{Region: "Sri Lanka", Group: "Premium TCP Europe", Hostname: "97-1-lk.cg-dialup.net", IPs: []net.IP{{95, 181, 239, 131}, {95, 181, 239, 132}, {95, 181, 239, 133}, {95, 181, 239, 134}, {95, 181, 239, 135}, {95, 181, 239, 136}, {95, 181, 239, 137}, {95, 181, 239, 138}, {95, 181, 239, 140}, {95, 181, 239, 144}}},
{Region: "Sri Lanka", Group: "Premium UDP Europe", Hostname: "87-1-lk.cg-dialup.net", IPs: []net.IP{{95, 181, 239, 131}, {95, 181, 239, 132}, {95, 181, 239, 133}, {95, 181, 239, 134}, {95, 181, 239, 135}, {95, 181, 239, 136}, {95, 181, 239, 140}, {95, 181, 239, 141}, {95, 181, 239, 142}, {95, 181, 239, 144}}},
{Region: "Sweden", Group: "Premium TCP Europe", Hostname: "97-1-se.cg-dialup.net", IPs: []net.IP{{188, 126, 73, 207}, {188, 126, 73, 209}, {188, 126, 73, 214}, {188, 126, 73, 219}, {188, 126, 79, 6}, {188, 126, 79, 11}, {188, 126, 79, 19}, {188, 126, 79, 25}, {195, 246, 120, 148}, {195, 246, 120, 161}}},
{Region: "Sweden", Group: "Premium UDP Europe", Hostname: "87-1-se.cg-dialup.net", IPs: []net.IP{{188, 126, 73, 201}, {188, 126, 73, 211}, {188, 126, 73, 213}, {188, 126, 73, 218}, {188, 126, 79, 6}, {188, 126, 79, 8}, {188, 126, 79, 19}, {195, 246, 120, 142}, {195, 246, 120, 144}, {195, 246, 120, 168}}},
{Region: "Switzerland", Group: "Premium TCP Europe", Hostname: "97-1-ch.cg-dialup.net", IPs: []net.IP{{84, 17, 52, 4}, {84, 17, 52, 20}, {84, 17, 52, 44}, {84, 17, 52, 65}, {84, 17, 52, 72}, {84, 17, 52, 80}, {84, 17, 52, 83}, {84, 17, 52, 85}, {185, 32, 222, 112}, {185, 189, 150, 73}}},
{Region: "Switzerland", Group: "Premium UDP Europe", Hostname: "87-1-ch.cg-dialup.net", IPs: []net.IP{{84, 17, 52, 5}, {84, 17, 52, 14}, {84, 17, 52, 24}, {84, 17, 52, 64}, {84, 17, 52, 73}, {84, 17, 52, 85}, {185, 32, 222, 114}, {185, 189, 150, 52}, {185, 189, 150, 57}, {195, 225, 118, 43}}},
{Region: "Taiwan", Group: "Premium TCP Asia", Hostname: "96-1-tw.cg-dialup.net", IPs: []net.IP{{45, 133, 181, 100}, {45, 133, 181, 102}, {45, 133, 181, 103}, {45, 133, 181, 106}, {45, 133, 181, 109}, {45, 133, 181, 113}, {45, 133, 181, 115}, {45, 133, 181, 116}, {45, 133, 181, 123}, {45, 133, 181, 125}}},
{Region: "Taiwan", Group: "Premium UDP Asia", Hostname: "95-1-tw.cg-dialup.net", IPs: []net.IP{{45, 133, 181, 99}, {45, 133, 181, 102}, {45, 133, 181, 107}, {45, 133, 181, 108}, {45, 133, 181, 109}, {45, 133, 181, 114}, {45, 133, 181, 116}, {45, 133, 181, 117}, {45, 133, 181, 123}, {45, 133, 181, 124}}},
{Region: "Thailand", Group: "Premium TCP Asia", Hostname: "96-1-th.cg-dialup.net", IPs: []net.IP{{146, 70, 13, 3}, {146, 70, 13, 4}, {146, 70, 13, 6}, {146, 70, 13, 7}, {146, 70, 13, 8}, {146, 70, 13, 9}, {146, 70, 13, 11}, {146, 70, 13, 13}, {146, 70, 13, 15}, {146, 70, 13, 16}}},
{Region: "Thailand", Group: "Premium UDP Asia", Hostname: "95-1-th.cg-dialup.net", IPs: []net.IP{{146, 70, 13, 3}, {146, 70, 13, 4}, {146, 70, 13, 8}, {146, 70, 13, 9}, {146, 70, 13, 10}, {146, 70, 13, 11}, {146, 70, 13, 12}, {146, 70, 13, 13}, {146, 70, 13, 15}, {146, 70, 13, 16}}},
{Region: "Turkey", Group: "Premium TCP Europe", Hostname: "97-1-tr.cg-dialup.net", IPs: []net.IP{{188, 213, 34, 9}, {188, 213, 34, 11}, {188, 213, 34, 15}, {188, 213, 34, 16}, {188, 213, 34, 23}, {188, 213, 34, 25}, {188, 213, 34, 28}, {188, 213, 34, 41}, {188, 213, 34, 108}, {188, 213, 34, 110}}},
{Region: "Turkey", Group: "Premium UDP Europe", Hostname: "87-1-tr.cg-dialup.net", IPs: []net.IP{{188, 213, 34, 8}, {188, 213, 34, 11}, {188, 213, 34, 14}, {188, 213, 34, 28}, {188, 213, 34, 35}, {188, 213, 34, 42}, {188, 213, 34, 43}, {188, 213, 34, 100}, {188, 213, 34, 103}, {188, 213, 34, 107}}},
{Region: "Ukraine", Group: "Premium TCP Europe", Hostname: "97-1-ua.cg-dialup.net", IPs: []net.IP{{31, 28, 161, 18}, {31, 28, 161, 20}, {31, 28, 161, 27}, {31, 28, 163, 34}, {31, 28, 163, 37}, {31, 28, 163, 44}, {62, 149, 7, 167}, {62, 149, 7, 172}, {62, 149, 29, 45}, {62, 149, 29, 57}}},
{Region: "Ukraine", Group: "Premium UDP Europe", Hostname: "87-1-ua.cg-dialup.net", IPs: []net.IP{{31, 28, 161, 27}, {31, 28, 163, 38}, {31, 28, 163, 42}, {31, 28, 163, 54}, {31, 28, 163, 61}, {62, 149, 7, 162}, {62, 149, 7, 163}, {62, 149, 29, 35}, {62, 149, 29, 38}, {62, 149, 29, 41}}},
{Region: "United Arab Emirates", Group: "Premium TCP Europe", Hostname: "97-1-ae.cg-dialup.net", IPs: []net.IP{{217, 138, 193, 179}, {217, 138, 193, 180}, {217, 138, 193, 181}, {217, 138, 193, 182}, {217, 138, 193, 183}, {217, 138, 193, 184}, {217, 138, 193, 185}, {217, 138, 193, 186}, {217, 138, 193, 188}, {217, 138, 193, 190}}},
{Region: "United Arab Emirates", Group: "Premium UDP Europe", Hostname: "87-1-ae.cg-dialup.net", IPs: []net.IP{{217, 138, 193, 179}, {217, 138, 193, 180}, {217, 138, 193, 181}, {217, 138, 193, 182}, {217, 138, 193, 183}, {217, 138, 193, 186}, {217, 138, 193, 187}, {217, 138, 193, 188}, {217, 138, 193, 189}, {217, 138, 193, 190}}},
{Region: "United Kingdom", Group: "Premium TCP Europe", Hostname: "97-1-gb.cg-dialup.net", IPs: []net.IP{{45, 133, 173, 49}, {45, 133, 173, 56}, {45, 133, 173, 82}, {45, 133, 173, 86}, {95, 154, 200, 153}, {95, 154, 200, 156}, {181, 215, 176, 103}, {181, 215, 176, 246}, {181, 215, 176, 251}, {194, 110, 13, 141}}},
{Region: "United Kingdom", Group: "Premium UDP Europe", Hostname: "87-1-gb.cg-dialup.net", IPs: []net.IP{{45, 133, 172, 100}, {45, 133, 172, 126}, {45, 133, 173, 84}, {95, 154, 200, 174}, {181, 215, 176, 110}, {181, 215, 176, 151}, {181, 215, 176, 158}, {191, 101, 209, 142}, {194, 110, 13, 107}, {194, 110, 13, 128}}},
{Region: "United States", Group: "Premium TCP USA", Hostname: "93-1-us.cg-dialup.net", IPs: []net.IP{{102, 129, 145, 15}, {102, 129, 152, 195}, {102, 129, 152, 248}, {154, 21, 208, 159}, {185, 242, 5, 117}, {185, 242, 5, 123}, {185, 242, 5, 229}, {191, 96, 227, 173}, {191, 96, 227, 196}, {199, 115, 119, 248}}},
{Region: "United States", Group: "Premium UDP USA", Hostname: "94-1-us.cg-dialup.net", IPs: []net.IP{{23, 82, 14, 113}, {23, 105, 177, 122}, {45, 89, 173, 222}, {84, 17, 35, 4}, {89, 187, 171, 132}, {156, 146, 37, 45}, {156, 146, 59, 86}, {184, 170, 240, 231}, {191, 96, 150, 248}, {199, 115, 119, 248}}},
{Region: "Venezuela", Group: "Premium TCP USA", Hostname: "93-1-ve.cg-dialup.net", IPs: []net.IP{{95, 181, 237, 132}, {95, 181, 237, 133}, {95, 181, 237, 134}, {95, 181, 237, 135}, {95, 181, 237, 136}, {95, 181, 237, 138}, {95, 181, 237, 139}, {95, 181, 237, 140}, {95, 181, 237, 141}, {95, 181, 237, 143}}},
{Region: "Venezuela", Group: "Premium UDP USA", Hostname: "94-1-ve.cg-dialup.net", IPs: []net.IP{{95, 181, 237, 131}, {95, 181, 237, 132}, {95, 181, 237, 134}, {95, 181, 237, 135}, {95, 181, 237, 136}, {95, 181, 237, 140}, {95, 181, 237, 141}, {95, 181, 237, 142}, {95, 181, 237, 143}, {95, 181, 237, 144}}},
{Region: "Vietnam", Group: "Premium TCP Asia", Hostname: "96-1-vn.cg-dialup.net", IPs: []net.IP{{188, 214, 152, 99}, {188, 214, 152, 101}, {188, 214, 152, 103}, {188, 214, 152, 104}, {188, 214, 152, 105}, {188, 214, 152, 106}, {188, 214, 152, 107}, {188, 214, 152, 108}, {188, 214, 152, 109}, {188, 214, 152, 110}}},
{Region: "Vietnam", Group: "Premium UDP Asia", Hostname: "95-1-vn.cg-dialup.net", IPs: []net.IP{{188, 214, 152, 99}, {188, 214, 152, 100}, {188, 214, 152, 101}, {188, 214, 152, 102}, {188, 214, 152, 103}, {188, 214, 152, 104}, {188, 214, 152, 105}, {188, 214, 152, 106}, {188, 214, 152, 107}, {188, 214, 152, 109}}},
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -47,6 +47,7 @@ func IvpnServers() []models.IvpnServer {
{Country: "Austria", City: "", Hostname: "at.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{185, 244, 212, 66}}},
{Country: "Belgium", City: "", Hostname: "be.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{194, 187, 251, 10}}},
{Country: "Brazil", City: "", Hostname: "br.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{45, 162, 229, 130}}},
{Country: "Bulgaria", City: "", Hostname: "bg.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{82, 102, 23, 18}}},
{Country: "Canada", City: "Montreal", Hostname: "ca-qc.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{87, 101, 92, 26}}},
{Country: "Canada", City: "Toronto", Hostname: "ca.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{104, 254, 90, 178}}},
{Country: "Czech Republic", City: "", Hostname: "cz.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{195, 181, 160, 167}}},
@@ -69,6 +70,7 @@ func IvpnServers() []models.IvpnServer {
{Country: "Serbia", City: "", Hostname: "rs.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{141, 98, 103, 250}}},
{Country: "Singapore", City: "", Hostname: "sg.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{185, 128, 24, 186}}},
{Country: "Slovakia", City: "", Hostname: "sk.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{185, 245, 85, 250}}},
{Country: "Spain", City: "", Hostname: "es.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{185, 93, 3, 193}}},
{Country: "Sweden", City: "", Hostname: "se.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{80, 67, 10, 138}}},
{Country: "Switzerland", City: "", Hostname: "ch.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{185, 212, 170, 138}}},
{Country: "USA", City: "Atlanta", Hostname: "us-ga.gw.ivpn.net", TCP: false, UDP: true, IPs: []net.IP{{104, 129, 24, 146}}},

View File

@@ -21,10 +21,10 @@ const (
RootHints string = "/etc/unbound/root.hints"
// RootKey is the filepath to the root.key file used by Unbound.
RootKey string = "/etc/unbound/root.key"
// Client key filepath, used by Cyberghost.
// ClientKey is the client key filepath.
ClientKey string = "/gluetun/client.key"
// Client certificate filepath, used by Cyberghost.
// ClientCertificate is the client certificate filepath.
ClientCertificate string = "/gluetun/client.crt"
// Servers information filepath.
// ServersData is the server information filepath.
ServersData = "/gluetun/servers.json"
)

View File

@@ -48,6 +48,7 @@ func PrivadoHostnameChoices() (choices []string) {
}
//nolint:lll
// PrivadoServers returns a slice of all the Privado servers.
func PrivadoServers() []models.PrivadoServer {
return []models.PrivadoServer{
{Country: "Argentina", Region: "Buenos Aires F.D.", City: "Buenos Aires", Hostname: "eze-001.vpn.privado.io", IP: net.IP{168, 205, 93, 211}},

View File

@@ -55,43 +55,39 @@ func PurevpnHostnameChoices() (choices []string) {
func PurevpnServers() []models.PurevpnServer {
return []models.PurevpnServer{
{Country: "Australia", Region: "New South Wales", City: "Sydney", Hostname: "au-sd2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{43, 245, 163, 82}, {46, 243, 245, 4}}},
{Country: "Australia", Region: "New South Wales", City: "Sydney", Hostname: "au-sd2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 245, 161, 80}, {43, 245, 161, 82}, {43, 245, 161, 84}}},
{Country: "Australia", Region: "New South Wales", City: "Sydney", Hostname: "au-sd2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 245, 161, 80}, {43, 245, 161, 81}, {43, 245, 161, 82}, {43, 245, 161, 86}}},
{Country: "Australia", Region: "Western Australia", City: "Perth", Hostname: "au2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{43, 250, 205, 50}}},
{Country: "Australia", Region: "Western Australia", City: "Perth", Hostname: "au2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 250, 205, 53}, {43, 250, 205, 65}}},
{Country: "Australia", Region: "Western Australia", City: "Perth", Hostname: "au2-pe-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{43, 250, 205, 50}}},
{Country: "Australia", Region: "Western Australia", City: "Perth", Hostname: "au2-pe-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 250, 205, 52}, {43, 250, 205, 65}}},
{Country: "Australia", Region: "Western Australia", City: "Perth", Hostname: "au2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 250, 205, 50}, {43, 250, 205, 61}}},
{Country: "Australia", Region: "Western Australia", City: "Perth", Hostname: "au2-pe-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{43, 250, 205, 50}, {43, 250, 205, 51}}},
{Country: "Australia", Region: "Western Australia", City: "Perth", Hostname: "au2-pe-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 250, 205, 34}}},
{Country: "Austria", Region: "Vienna", City: "Vienna", Hostname: "at2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{217, 64, 127, 251}, {217, 64, 127, 252}}},
{Country: "Austria", Region: "Vienna", City: "Vienna", Hostname: "at2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{37, 120, 212, 218}, {37, 120, 212, 220}, {217, 64, 127, 251}}},
{Country: "Belgium", Region: "Flanders", City: "Zaventem", Hostname: "vleu-be2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{217, 138, 211, 85}, {217, 138, 211, 86}, {217, 138, 211, 116}, {217, 138, 221, 114}}},
{Country: "Belgium", Region: "Flanders", City: "Zaventem", Hostname: "vleu-be2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{217, 138, 211, 87}, {217, 138, 211, 88}, {217, 138, 211, 114}}},
{Country: "Austria", Region: "Vienna", City: "Vienna", Hostname: "at2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{37, 120, 212, 219}, {217, 64, 127, 252}}},
{Country: "Belgium", Region: "Flanders", City: "Zaventem", Hostname: "vleu-be2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{217, 138, 211, 87}, {217, 138, 211, 116}, {217, 138, 221, 117}}},
{Country: "Brazil", Region: "São Paulo", City: "São Paulo", Hostname: "br2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{181, 41, 201, 83}, {181, 41, 201, 84}}},
{Country: "Brazil", Region: "São Paulo", City: "São Paulo", Hostname: "br2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{138, 99, 210, 4}, {181, 41, 201, 77}, {181, 41, 201, 83}}},
{Country: "Canada", Region: "British Columbia", City: "Vancouver", Hostname: "cav2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{66, 115, 147, 34}, {66, 115, 147, 35}}},
{Country: "Canada", Region: "British Columbia", City: "Vancouver", Hostname: "cav2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{66, 115, 147, 38}, {66, 115, 147, 39}, {66, 115, 147, 40}}},
{Country: "Canada", Region: "Ontario", City: "Toronto", Hostname: "ca2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 200, 138, 212}, {104, 200, 138, 213}}},
{Country: "Canada", Region: "Ontario", City: "Toronto", Hostname: "ca2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{104, 200, 138, 178}, {104, 200, 138, 212}, {104, 200, 138, 218}, {104, 200, 138, 219}}},
{Country: "Czech Republic", Region: "Hlavní město Praha", City: "Prague", Hostname: "cz2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{185, 156, 174, 35}, {185, 156, 174, 36}}},
{Country: "Czech Republic", Region: "Hlavní město Praha", City: "Prague", Hostname: "cz2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{185, 156, 174, 36}, {217, 138, 199, 252}}},
{Country: "France", Region: "Île-de-France", City: "Paris", Hostname: "fr2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{89, 40, 183, 148}}},
{Country: "France", Region: "Île-de-France", City: "Paris", Hostname: "fr2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 152, 181, 69}, {45, 152, 181, 70}}},
{Country: "Germany", Region: "Hesse", City: "Frankfurt am Main", Hostname: "de2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{5, 254, 88, 171}, {37, 120, 223, 50}}},
{Country: "Germany", Region: "Hesse", City: "Frankfurt am Main", Hostname: "de2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{2, 57, 18, 22}, {217, 138, 194, 195}}},
{Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", Hostname: "hk2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{103, 109, 103, 59}}},
{Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", Hostname: "hk2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{103, 109, 103, 60}, {172, 111, 168, 4}}},
{Country: "Brazil", Region: "São Paulo", City: "São Paulo", Hostname: "br2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{138, 99, 210, 4}, {181, 41, 201, 75}, {181, 41, 201, 82}, {181, 41, 201, 83}}},
{Country: "Bulgaria", Region: "Sofia-Capital", City: "Sofia", Hostname: "vleu-be2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{217, 138, 221, 114}}},
{Country: "Canada", Region: "British Columbia", City: "Vancouver", Hostname: "cav2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{66, 115, 147, 34}}},
{Country: "Canada", Region: "British Columbia", City: "Vancouver", Hostname: "cav2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{66, 115, 147, 34}, {66, 115, 147, 35}, {66, 115, 147, 37}, {66, 115, 147, 38}, {66, 115, 147, 40}, {66, 115, 147, 43}}},
{Country: "Canada", Region: "Ontario", City: "Toronto", Hostname: "ca2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 200, 138, 212}}},
{Country: "Canada", Region: "Ontario", City: "Toronto", Hostname: "ca2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{104, 200, 138, 213}, {104, 200, 138, 214}, {104, 200, 138, 216}}},
{Country: "Czech Republic", Region: "Hlavní město Praha", City: "Prague", Hostname: "cz2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{185, 156, 174, 36}}},
{Country: "Czech Republic", Region: "Hlavní město Praha", City: "Prague", Hostname: "cz2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{185, 156, 174, 38}, {217, 138, 199, 252}}},
{Country: "France", Region: "Île-de-France", City: "Paris", Hostname: "fr2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{45, 152, 181, 68}}},
{Country: "France", Region: "Île-de-France", City: "Paris", Hostname: "fr2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 152, 181, 67}, {45, 152, 181, 70}}},
{Country: "Germany", Region: "Hesse", City: "Frankfurt am Main", Hostname: "de2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{5, 254, 88, 213}}},
{Country: "Germany", Region: "Hesse", City: "Frankfurt am Main", Hostname: "de2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 254, 82, 50}, {5, 254, 82, 52}}},
{Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", Hostname: "hk2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{103, 109, 103, 59}, {103, 109, 103, 60}, {119, 81, 228, 109}}},
{Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", Hostname: "hk2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 111, 168, 4}}},
{Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", Hostname: "vlap-ph2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{36, 255, 97, 3}, {129, 227, 119, 84}}},
{Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", Hostname: "vlap-ph2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{128, 1, 209, 21}}},
{Country: "India", Region: "Tamil Nadu", City: "Tinnanūr", Hostname: "in2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 250, 160, 132}, {178, 170, 141, 6}}},
{Country: "Indonesia", Region: "Aceh", City: "Bireun", Hostname: "in2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{169, 38, 97, 242}, {169, 38, 129, 21}}},
{Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", Hostname: "vlap-ph2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{36, 255, 97, 3}}},
{Country: "Italy", Region: "Lombardy", City: "Milan", Hostname: "it2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{172, 111, 173, 3}}},
{Country: "Italy", Region: "Lombardy", City: "Milan", Hostname: "it2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 111, 173, 3}}},
{Country: "Japan", Region: "Okinawa", City: "Hirara", Hostname: "tw2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{128, 1, 155, 178}}},
{Country: "Japan", Region: "Okinawa", City: "Hirara", Hostname: "tw2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{128, 1, 155, 178}}},
{Country: "Japan", Region: "Tokyo", City: "Tokyo", Hostname: "jp2-ovpn.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{185, 242, 4, 59}}},
{Country: "Korea", Region: "Seoul", City: "Seoul", Hostname: "kr2-ovpn.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 226, 231, 6}}},
{Country: "Malaysia", Region: "Kuala Lumpur", City: "Kuala Lumpur", Hostname: "my2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{103, 28, 90, 32}, {103, 55, 10, 133}}},
{Country: "Malaysia", Region: "Kuala Lumpur", City: "Kuala Lumpur", Hostname: "my2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{103, 55, 10, 4}, {103, 55, 10, 134}}},
{Country: "Netherlands", Region: "North Holland", City: "Amsterdam", Hostname: "nl2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{5, 254, 73, 253}}},
{Country: "Netherlands", Region: "North Holland", City: "Amsterdam", Hostname: "nl2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 254, 73, 172}, {5, 254, 73, 203}}},
{Country: "Korea", Region: "Gangwon-do", City: "Hongchŏn", Hostname: "kr2-ovpn.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 226, 231, 4}, {43, 226, 231, 6}}},
{Country: "Malaysia", Region: "Kuala Lumpur", City: "Kuala Lumpur", Hostname: "my2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{103, 55, 10, 134}}},
{Country: "Malaysia", Region: "Kuala Lumpur", City: "Kuala Lumpur", Hostname: "my2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{103, 28, 90, 32}}},
{Country: "Netherlands", Region: "North Holland", City: "Amsterdam", Hostname: "nl2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{5, 254, 73, 172}, {5, 254, 73, 252}, {92, 119, 179, 195}, {206, 123, 147, 4}}},
{Country: "Netherlands", Region: "North Holland", City: "Amsterdam", Hostname: "nl2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 254, 73, 171}, {5, 254, 73, 202}, {92, 119, 179, 195}, {206, 123, 147, 4}}},
{Country: "Netherlands", Region: "North Holland", City: "Amsterdam", Hostname: "vlap-th2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 37, 6, 4}}},
{Country: "Netherlands", Region: "North Holland", City: "Amsterdam", Hostname: "vlap-th2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{104, 37, 6, 4}}},
{Country: "Norway", Region: "Oslo", City: "Oslo", Hostname: "vleu-no2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{82, 102, 22, 212}}},
@@ -100,51 +96,55 @@ func PurevpnServers() []models.PurevpnServer {
{Country: "Portugal", Region: "Lisbon", City: "Lisbon", Hostname: "Pt2-ovpn.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 154, 174, 3}}},
{Country: "Russian Federation", Region: "St.-Petersburg", City: "Saint Petersburg", Hostname: "ru2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{94, 242, 54, 23}, {206, 123, 139, 4}}},
{Country: "Russian Federation", Region: "St.-Petersburg", City: "Saint Petersburg", Hostname: "ru2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{94, 242, 54, 23}, {206, 123, 139, 4}}},
{Country: "Singapore", Region: "Singapore", City: "Singapore", Hostname: "sg2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{37, 120, 208, 148}, {84, 247, 49, 180}}},
{Country: "Singapore", Region: "Singapore", City: "Singapore", Hostname: "sg2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{84, 247, 49, 181}}},
{Country: "Singapore", Region: "Singapore", City: "Singapore", Hostname: "sg2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{37, 120, 208, 147}, {37, 120, 208, 148}}},
{Country: "Singapore", Region: "Singapore", City: "Singapore", Hostname: "vlap-vn2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{192, 253, 249, 132}}},
{Country: "Singapore", Region: "Singapore", City: "Singapore", Hostname: "vlap-vn2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{192, 253, 249, 132}}},
{Country: "South Africa", Region: "Gauteng", City: "Johannesburg", Hostname: "za2-ovpn.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{102, 165, 3, 34}}},
{Country: "Sweden", Region: "Stockholm", City: "Stockholm", Hostname: "se2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{45, 12, 220, 123}}},
{Country: "Sweden", Region: "Stockholm", City: "Stockholm", Hostname: "se2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{86, 106, 103, 181}, {86, 106, 103, 185}}},
{Country: "South Africa", Region: "Gauteng", City: "Johannesburg", Hostname: "za2-ovpn.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{102, 165, 3, 33}, {102, 165, 3, 34}}},
{Country: "Sweden", Region: "Stockholm", City: "Stockholm", Hostname: "se2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{45, 12, 220, 123}, {86, 106, 103, 178}, {86, 106, 103, 179}}},
{Country: "Sweden", Region: "Stockholm", City: "Stockholm", Hostname: "se2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 12, 220, 125}, {86, 106, 103, 183}}},
{Country: "Switzerland", Region: "Zurich", City: "Zürich", Hostname: "ch2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{45, 12, 222, 98}, {45, 12, 222, 99}}},
{Country: "Switzerland", Region: "Zurich", City: "Zürich", Hostname: "ch2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 12, 222, 100}, {45, 12, 222, 101}, {45, 12, 222, 104}, {45, 12, 222, 107}}},
{Country: "Switzerland", Region: "Zurich", City: "Zürich", Hostname: "ch2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 12, 222, 100}, {45, 12, 222, 102}, {45, 12, 222, 106}, {45, 12, 222, 107}}},
{Country: "Taiwan", Region: "Taiwan", City: "Taipei", Hostname: "tw2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{128, 1, 155, 178}}},
{Country: "Taiwan", Region: "Taiwan", City: "Taipei", Hostname: "tw2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{128, 1, 155, 178}}},
{Country: "United Kingdom", Region: "England", City: "London", Hostname: "ukg2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{45, 74, 0, 4}}},
{Country: "United Kingdom", Region: "England", City: "London", Hostname: "ukg2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{193, 9, 113, 70}}},
{Country: "United Kingdom", Region: "England", City: "London", Hostname: "ukl2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{45, 74, 0, 4}}},
{Country: "United Kingdom", Region: "England", City: "London", Hostname: "ukl2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{89, 238, 165, 146}, {193, 9, 113, 70}}},
{Country: "United Kingdom", Region: "England", City: "Manchester", Hostname: "ukg2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{89, 238, 165, 148}, {89, 238, 165, 149}}},
{Country: "United Kingdom", Region: "England", City: "Manchester", Hostname: "ukl2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{89, 238, 165, 148}, {89, 238, 165, 149}}},
{Country: "United Kingdom", Region: "England", City: "Manchester", Hostname: "ukm2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{188, 72, 89, 4}}},
{Country: "United Kingdom", Region: "England", City: "Manchester", Hostname: "ukm2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{188, 72, 89, 4}}},
{Country: "United States", Region: "California", City: "Los Angeles", Hostname: "usla2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{89, 45, 4, 2}}},
{Country: "United States", Region: "California", City: "Los Angeles", Hostname: "vlus-mx2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 243, 243, 131}}},
{Country: "United States", Region: "California", City: "Los Angeles", Hostname: "vlus-mx2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{104, 243, 243, 131}}},
{Country: "United States", Region: "California", City: "Milpitas", Hostname: "usphx2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{141, 101, 166, 4}, {172, 94, 72, 4}}},
{Country: "United States", Region: "California", City: "Milpitas", Hostname: "ussf2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{141, 101, 166, 4}}},
{Country: "United States", Region: "California", City: "Milpitas", Hostname: "ussf2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{141, 101, 166, 4}}},
{Country: "United States", Region: "Florida", City: "Miami", Hostname: "usfl2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{5, 254, 79, 117}}},
{Country: "United States", Region: "California", City: "San Jose", Hostname: "ussf2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{141, 101, 166, 4}}},
{Country: "United States", Region: "Florida", City: "Miami", Hostname: "usfl2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{5, 254, 79, 100}, {5, 254, 79, 116}}},
{Country: "United States", Region: "Florida", City: "Miami", Hostname: "usfl2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 254, 79, 114}, {5, 254, 79, 115}}},
{Country: "United States", Region: "New Jersey", City: "Harrison", Hostname: "vlus-pa2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{172, 111, 149, 4}}},
{Country: "United States", Region: "New Jersey", City: "Harrison", Hostname: "vlus-pa2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 111, 149, 4}}},
{Country: "United States", Region: "Georgia", City: "Cumming", Hostname: "in2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{169, 38, 69, 12}}},
{Country: "United States", Region: "New Jersey", City: "Piscataway", Hostname: "usny2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{209, 127, 184, 71}, {209, 127, 184, 73}, {209, 127, 184, 74}, {209, 127, 184, 76}}},
{Country: "United States", Region: "New York", City: "New York City", Hostname: "usnj2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{172, 94, 72, 4}}},
{Country: "United States", Region: "New York", City: "New York City", Hostname: "usnj2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 94, 72, 4}}},
{Country: "United States", Region: "New York", City: "New York City", Hostname: "usny2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{141, 101, 153, 4}}},
{Country: "United States", Region: "New York", City: "New York City", Hostname: "usny2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 94, 72, 4}}},
{Country: "United States", Region: "New York", City: "New York City", Hostname: "ussf2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 94, 72, 4}, {172, 94, 86, 4}}},
{Country: "United States", Region: "New York", City: "New York City", Hostname: "uswdc2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 94, 72, 4}, {172, 94, 86, 4}}},
{Country: "United States", Region: "New York", City: "New York City", Hostname: "vlus-pa2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{172, 111, 149, 4}}},
{Country: "United States", Region: "New York", City: "New York City", Hostname: "vlus-pa2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 111, 149, 4}}},
{Country: "United States", Region: "Pennsylvania", City: "Pittsburgh", Hostname: "in2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 250, 160, 132}}},
{Country: "United States", Region: "Texas", City: "Allen", Hostname: "usga2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{172, 94, 108, 4}}},
{Country: "United States", Region: "Texas", City: "Allen", Hostname: "usil2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{172, 94, 108, 4}}},
{Country: "United States", Region: "Texas", City: "Dallas", Hostname: "ukm2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 94, 1, 4}, {172, 94, 72, 4}, {172, 94, 123, 4}}},
{Country: "United States", Region: "Texas", City: "Dallas", Hostname: "ussa2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 94, 1, 4}, {172, 94, 72, 4}}},
{Country: "United States", Region: "Texas", City: "Dallas", Hostname: "ustx2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 217, 255, 178}, {208, 84, 155, 100}}},
{Country: "United States", Region: "Texas", City: "Dallas", Hostname: "ustx2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{104, 217, 255, 179}, {104, 217, 255, 184}, {104, 217, 255, 185}}},
{Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "us2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}}},
{Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "usga2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}, {172, 94, 1, 4}}},
{Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "usil2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}, {46, 243, 249, 4}, {172, 94, 72, 4}}},
{Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "usla2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}, {141, 101, 166, 4}, {172, 94, 1, 4}}},
{Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "usut2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}}},
{Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "uswdc2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}, {141, 101, 166, 4}, {172, 94, 72, 4}}},
{Country: "United States", Region: "Texas", City: "Dallas", Hostname: "ustx2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{208, 84, 155, 100}, {208, 84, 155, 101}}},
{Country: "United States", Region: "Texas", City: "Dallas", Hostname: "ustx2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{104, 217, 255, 185}, {104, 217, 255, 186}}},
{Country: "United States", Region: "Virginia", City: "Centreville", Hostname: "usva2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 254, 109, 115}, {37, 221, 173, 212}}},
{Country: "United States", Region: "Virginia", City: "Reston", Hostname: "usva2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{5, 254, 77, 26}, {5, 254, 77, 27}}},
{Country: "United States", Region: "Virginia", City: "Reston", Hostname: "usva2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 254, 77, 26}, {5, 254, 77, 138}}},
{Country: "United States", Region: "Washington", City: "Seattle", Hostname: "ussa2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 94, 86, 4}}},
{Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "us2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{46, 243, 249, 4}}},
{Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "us2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{141, 101, 169, 4}, {172, 94, 72, 4}, {172, 94, 86, 4}}},
{Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "usga2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{141, 101, 169, 4}, {172, 94, 86, 4}}},
{Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "usil2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{141, 101, 169, 4}, {172, 94, 72, 4}, {172, 94, 86, 4}}},
{Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "usla2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{141, 101, 169, 4}, {172, 94, 72, 4}}},
{Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "usphx2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{141, 101, 169, 4}}},
{Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "ussa2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{46, 243, 249, 4}}},
{Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "usut2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{46, 243, 249, 4}}},
{Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "usut2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{141, 101, 169, 4}, {172, 94, 72, 4}, {172, 94, 86, 4}}},
{Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "uswdc2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{46, 243, 249, 4}}},
{Country: "Vietnam", Region: "Hanoi", City: "Hanoi", Hostname: "vlap-vn2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{192, 253, 249, 132}}},
{Country: "Vietnam", Region: "Hanoi", City: "Hanoi", Hostname: "vlap-vn2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{192, 253, 249, 132}}},
}
}

View File

@@ -8,7 +8,7 @@ func GetAllServers() (allServers models.AllServers) {
Version: 1, // used for migration of the top level scheme
Cyberghost: models.CyberghostServers{
Version: 2, // model version
Timestamp: 1620491290, // latest takes precedence
Timestamp: 1624307338, // latest takes precedence
Servers: CyberghostServers(),
},
Fastestvpn: models.FastestvpnServers{
@@ -21,9 +21,14 @@ func GetAllServers() (allServers models.AllServers) {
Timestamp: 1620435633,
Servers: HideMyAssServers(),
},
Ipvanish: models.IpvanishServers{
Version: 1,
Timestamp: 1622430497,
Servers: IpvanishServers(),
},
Ivpn: models.IvpnServers{
Version: 1,
Timestamp: 1622421364,
Timestamp: 1624120443,
Servers: IvpnServers(),
},
Mullvad: models.MullvadServers{
@@ -58,7 +63,7 @@ func GetAllServers() (allServers models.AllServers) {
},
Purevpn: models.PurevpnServers{
Version: 2,
Timestamp: 1620606921,
Timestamp: 1622644308,
Servers: PurevpnServers(),
},
Surfshark: models.SurfsharkServers{
@@ -71,6 +76,11 @@ func GetAllServers() (allServers models.AllServers) {
Timestamp: 1620611129,
Servers: TorguardServers(),
},
VPNUnlimited: models.VPNUnlimitedServers{
Version: 1,
Timestamp: 1623950304,
Servers: VPNUnlimitedServers(),
},
Vyprvpn: models.VyprvpnServers{
Version: 2,
Timestamp: 1620612506,

View File

@@ -50,6 +50,11 @@ func Test_versions(t *testing.T) {
version: allServers.HideMyAss.Version,
digest: "a93b4057",
},
"Ipvanish": {
model: models.IpvanishServer{},
version: allServers.Ipvanish.Version,
digest: "2eb80d28",
},
"Ivpn": {
model: models.IvpnServer{},
version: allServers.Ivpn.Version,
@@ -100,6 +105,11 @@ func Test_versions(t *testing.T) {
version: allServers.Torguard.Version,
digest: "6eb9028e",
},
"VPN Unlimited": {
model: models.VPNUnlimitedServer{},
version: allServers.VPNUnlimited.Version,
digest: "5cb51319",
},
"Vyprvpn": {
model: models.VyprvpnServer{},
version: allServers.Vyprvpn.Version,
@@ -150,7 +160,7 @@ func Test_timestamps(t *testing.T) {
"Cyberghost": {
servers: allServers.Cyberghost.Servers,
timestamp: allServers.Cyberghost.Timestamp,
digest: "1de7ee68",
digest: "b3ca3118",
},
"Fastestvpn": {
servers: allServers.Fastestvpn.Version,
@@ -162,10 +172,15 @@ func Test_timestamps(t *testing.T) {
timestamp: allServers.HideMyAss.Timestamp,
digest: "8f872ac4",
},
"Ipvanish": {
servers: allServers.Ipvanish.Servers,
timestamp: allServers.Ipvanish.Timestamp,
digest: "c62dcf98",
},
"Ivpn": {
servers: allServers.Ivpn.Servers,
timestamp: allServers.Ivpn.Timestamp,
digest: "158630c0",
digest: "42f92754",
},
"Mullvad": {
servers: allServers.Mullvad.Servers,
@@ -200,7 +215,7 @@ func Test_timestamps(t *testing.T) {
"Purevpn": {
servers: allServers.Purevpn.Servers,
timestamp: allServers.Purevpn.Timestamp,
digest: "e48aa76d",
digest: "9263cfdb",
},
"Surfshark": {
servers: allServers.Surfshark.Servers,
@@ -212,6 +227,11 @@ func Test_timestamps(t *testing.T) {
timestamp: allServers.Torguard.Timestamp,
digest: "af54b9e8",
},
"VPN Unlimited": {
servers: allServers.VPNUnlimited.Servers,
timestamp: allServers.VPNUnlimited.Timestamp,
digest: "f6ddb84c",
},
"Vyprvpn": {
servers: allServers.Vyprvpn.Servers,
timestamp: allServers.Vyprvpn.Timestamp,

View File

@@ -30,7 +30,7 @@ func TorguardCityChoices() (choices []string) {
return makeUnique(choices)
}
func TorguardHostnamesChoices() (choices []string) {
func TorguardHostnameChoices() (choices []string) {
servers := TorguardServers()
choices = make([]string, len(servers))
for i := range servers {

View File

@@ -7,11 +7,13 @@ const (
Fastestvpn = "fastestvpn"
// HideMyAss is a VPN provider.
HideMyAss = "hidemyass"
// Ipvanish is a VPN provider.
Ipvanish = "ipvanish"
// Ivpn is a VPN provider.
Ivpn = "ivpn"
// Mullvad is a VPN provider.
Mullvad = "mullvad"
// NordVPN is a VPN provider.
// Nordvpn is a VPN provider.
Nordvpn = "nordvpn"
// Privado is a VPN provider.
Privado = "privado"
@@ -21,12 +23,14 @@ const (
Privatevpn = "privatevpn"
// Protonvpn is a VPN provider.
Protonvpn = "protonvpn"
// PureVPN is a VPN provider.
// Purevpn is a VPN provider.
Purevpn = "purevpn"
// Surfshark is a VPN provider.
Surfshark = "surfshark"
// Torguard is a VPN provider.
Torguard = "torguard"
// VPNUnlimited is a VPN provider.
VPNUnlimited = "vpn unlimited"
// Vyprvpn is a VPN provider.
Vyprvpn = "vyprvpn"
// Windscribe is a VPN provider.

View File

@@ -0,0 +1,124 @@
package constants
import (
"net"
"github.com/qdm12/gluetun/internal/models"
)
//nolint:lll
const (
VPNUnlimitedCertificateAuthority = "MIIEjjCCA/egAwIBAgIJAKsVbHBdakXuMA0GCSqGSIb3DQEBBQUAMIHgMQswCQYDVQQGEwJVUzELMAkGA1UECBMCTlkxETAPBgNVBAcTCE5ldyBZb3JrMR8wHQYDVQQKExZTaW1wbGV4IFNvbHV0aW9ucyBJbmMuMRYwFAYDVQQLEw1WcG4gVW5saW1pdGVkMSMwIQYDVQQDExpzZXJ2ZXIudnBudW5saW1pdGVkYXBwLmNvbTEjMCEGA1UEKRMac2VydmVyLnZwbnVubGltaXRlZGFwcC5jb20xLjAsBgkqhkiG9w0BCQEWH3N1cHBvcnRAc2ltcGxleHNvbHV0aW9uc2luYy5jb20wHhcNMTMxMjE2MTM1OTQ0WhcNMjMxMjE0MTM1OTQ0WjCB4DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk5ZMREwDwYDVQQHEwhOZXcgWW9yazEfMB0GA1UEChMWU2ltcGxleCBTb2x1dGlvbnMgSW5jLjEWMBQGA1UECxMNVnBuIFVubGltaXRlZDEjMCEGA1UEAxMac2VydmVyLnZwbnVubGltaXRlZGFwcC5jb20xIzAhBgNVBCkTGnNlcnZlci52cG51bmxpbWl0ZWRhcHAuY29tMS4wLAYJKoZIhvcNAQkBFh9zdXBwb3J0QHNpbXBsZXhzb2x1dGlvbnNpbmMuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDADUzS8QWGvdhLFKsEzAiq5+b0ukKjBza0k6/dmCeYTvCVqGKg/h1IAtQdVVLAkmEp0zvGH7PuOhXm7zZrCouBr/RiG4tEcoRHwc6AJmowkYERlY7+xGx3OuNrD00QceNTsan0bn78jwt0zhFNmHdoTtFjgK3oqmQYSAtbEVWYgwIDAQABo4IBTDCCAUgwHQYDVR0OBBYEFKClmYP+tMNgWagUJCCHjtaui2k+MIIBFwYDVR0jBIIBDjCCAQqAFKClmYP+tMNgWagUJCCHjtaui2k+oYHmpIHjMIHgMQswCQYDVQQGEwJVUzELMAkGA1UECBMCTlkxETAPBgNVBAcTCE5ldyBZb3JrMR8wHQYDVQQKExZTaW1wbGV4IFNvbHV0aW9ucyBJbmMuMRYwFAYDVQQLEw1WcG4gVW5saW1pdGVkMSMwIQYDVQQDExpzZXJ2ZXIudnBudW5saW1pdGVkYXBwLmNvbTEjMCEGA1UEKRMac2VydmVyLnZwbnVubGltaXRlZGFwcC5jb20xLjAsBgkqhkiG9w0BCQEWH3N1cHBvcnRAc2ltcGxleHNvbHV0aW9uc2luYy5jb22CCQCrFWxwXWpF7jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBALkWhfw7SSV7it+ZYZmT+cQbExjlYgQ40zae2J2CqIYACRcfsDHvh7Q+fiwSocevv2NE0dWi6WB2H6SiudYjvDvubAX/QbzfBxtbxCCoAIlfPCm8xOnWFN7TUJAzWwHJkKgEnu29GZHu2x8J+7VeDbKH5RTMHHe8FkSxh6Zz/BMN"
)
func VPNUnlimitedCountryChoices() (choices []string) {
servers := VPNUnlimitedServers()
choices = make([]string, len(servers))
for i := range servers {
choices[i] = servers[i].Country
}
return makeUnique(choices)
}
func VPNUnlimitedCityChoices() (choices []string) {
servers := VPNUnlimitedServers()
choices = make([]string, len(servers))
for i := range servers {
choices[i] = servers[i].City
}
return makeUnique(choices)
}
func VPNUnlimitedHostnameChoices() (choices []string) {
servers := VPNUnlimitedServers()
choices = make([]string, len(servers))
for i := range servers {
choices[i] = servers[i].Hostname
}
return makeUnique(choices)
}
//nolint:lll
// VPNUnlimitedServers returns a slice of all the server information for VPNUnlimited.
func VPNUnlimitedServers() []models.VPNUnlimitedServer {
return []models.VPNUnlimitedServer{
{Country: "Argentina", City: "", Hostname: "ar.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{131, 255, 4, 187}, {131, 255, 4, 235}}},
{Country: "Australia", City: "Sydney", Hostname: "au-syd.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{139, 99, 131, 38}, {139, 99, 130, 220}}},
{Country: "Austria", City: "", Hostname: "at.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{50, 7, 115, 19}, {185, 210, 219, 194}, {185, 210, 219, 198}}},
{Country: "Belarus", City: "", Hostname: "by.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 66, 68, 23}, {185, 66, 71, 108}, {185, 66, 71, 115}, {185, 66, 68, 84}, {185, 66, 71, 22}, {185, 66, 71, 122}, {185, 66, 71, 8}, {185, 66, 68, 18}}},
{Country: "Belgium", City: "", Hostname: "be.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{37, 120, 143, 178}, {82, 102, 19, 110}}},
{Country: "Bosnia and Herzegovina", City: "", Hostname: "ba.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 164, 35, 37}}},
{Country: "Brazil", City: "", Hostname: "br.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{66, 90, 70, 7}, {177, 67, 82, 222}, {177, 67, 82, 218}, {177, 67, 82, 228}, {177, 67, 82, 221}, {177, 67, 82, 219}, {177, 67, 82, 210}, {177, 67, 82, 223}}},
{Country: "Bulgaria", City: "", Hostname: "bg.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{37, 120, 152, 26}}},
{Country: "Canada", City: "", Hostname: "ca.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{192, 99, 7, 170}, {192, 99, 6, 164}, {192, 99, 14, 158}, {192, 99, 37, 199}, {192, 99, 6, 166}}},
{Country: "Canada", City: "Toronto", Hostname: "ca-tr.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{184, 75, 213, 154}, {162, 253, 131, 106}, {162, 219, 176, 163}, {104, 254, 90, 58}, {104, 254, 92, 42}, {184, 75, 213, 194}, {204, 187, 100, 82}, {104, 254, 90, 34}}},
{Country: "Canada", City: "Vancouver", Hostname: "ca-vn.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{162, 221, 202, 138}, {162, 221, 202, 134}, {162, 221, 202, 17}}},
{Country: "Costa Rica", City: "", Hostname: "cr.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{138, 59, 19, 8}}},
{Country: "Croatia", City: "", Hostname: "hr.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{85, 10, 56, 3}, {85, 10, 56, 100}, {85, 10, 51, 3}, {85, 10, 56, 4}}},
{Country: "Cyprus", City: "", Hostname: "cy.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{194, 30, 136, 123}, {194, 30, 136, 102}}},
{Country: "Czech Republic", City: "", Hostname: "cz.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 216, 35, 46}}},
{Country: "Denmark", City: "", Hostname: "dk.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{37, 120, 194, 174}, {89, 45, 7, 90}}},
{Country: "Estonia", City: "", Hostname: "ee.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 155, 96, 132}}},
{Country: "Finland", City: "", Hostname: "fi.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 112, 82, 26}, {91, 233, 116, 44}}},
{Country: "France", City: "", Hostname: "fr.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{195, 154, 189, 85}, {195, 154, 204, 36}, {195, 154, 211, 84}, {62, 210, 38, 83}, {195, 154, 169, 66}, {195, 154, 166, 20}, {62, 210, 204, 161}, {62, 210, 205, 16}, {62, 210, 139, 124}, {195, 154, 221, 54}, {195, 154, 199, 175}, {195, 154, 189, 212}, {195, 154, 180, 96}, {195, 154, 199, 155}, {195, 154, 209, 149}, {195, 154, 222, 168}}},
{Country: "France", City: "Roubaix", Hostname: "fr-rbx.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{151, 80, 27, 199}, {51, 255, 71, 16}, {147, 135, 137, 107}}},
{Country: "Germany", City: "", Hostname: "de.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{84, 16, 236, 168}, {178, 162, 205, 77}, {178, 162, 205, 115}, {178, 162, 205, 82}, {84, 16, 238, 220}}},
{Country: "Germany", City: "Düsseldorf", Hostname: "de-dus.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{146, 0, 42, 77}, {146, 0, 32, 121}, {85, 14, 243, 42}}},
{Country: "Greece", City: "", Hostname: "gr.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{154, 57, 3, 36}}},
{Country: "Hungary", City: "", Hostname: "hu.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{91, 219, 238, 174}}},
{Country: "Iceland", City: "", Hostname: "is.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{37, 235, 49, 75}, {151, 236, 24, 114}, {37, 235, 49, 42}, {37, 235, 49, 244}, {37, 235, 49, 70}, {37, 235, 49, 15}, {151, 236, 24, 142}}},
{Country: "India", City: "", Hostname: "in.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{103, 26, 204, 46}, {103, 26, 204, 84}}},
{Country: "India", City: "Karnataka", Hostname: "in-ka.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{139, 59, 67, 224}, {139, 59, 65, 136}, {139, 59, 24, 197}, {139, 59, 24, 198}, {139, 59, 24, 199}, {139, 59, 24, 191}, {139, 59, 16, 78}}},
{Country: "Ireland", City: "Dublin", Hostname: "ie-dub.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{188, 241, 178, 118}}},
{Country: "Isle of Man", City: "", Hostname: "im.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{192, 71, 211, 15}, {37, 235, 55, 62}, {37, 235, 55, 68}, {37, 235, 55, 14}, {37, 235, 55, 45}}},
{Country: "Israel", City: "", Hostname: "il.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{193, 182, 144, 170}, {193, 182, 144, 151}, {193, 182, 144, 23}}},
{Country: "Italy", City: "Milan", Hostname: "it-mil.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{91, 193, 5, 50}}},
{Country: "Japan", City: "", Hostname: "jp.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{172, 104, 67, 80}, {172, 104, 75, 121}, {161, 202, 97, 109}, {172, 104, 71, 35}, {172, 104, 126, 64}, {172, 104, 64, 213}, {85, 208, 110, 122}, {172, 104, 78, 67}, {172, 104, 83, 34}, {172, 104, 99, 172}, {161, 202, 97, 101}, {172, 104, 83, 13}, {172, 104, 87, 163}, {172, 104, 99, 14}}},
{Country: "Korea", City: "", Hostname: "kr.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{160, 202, 162, 60}, {160, 202, 163, 122}}},
{Country: "Kuala Lumpur", City: "", Hostname: "mys.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{111, 90, 141, 34}, {111, 90, 158, 159}}},
{Country: "Latvia", City: "", Hostname: "lv.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{195, 123, 213, 172}, {195, 123, 209, 168}}},
{Country: "Libya", City: "", Hostname: "ly.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{41, 208, 71, 39}}},
{Country: "Lithuania", City: "", Hostname: "lt.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 64, 105, 93}, {185, 64, 104, 142}, {185, 25, 48, 81}}},
{Country: "Luxembourg", City: "", Hostname: "lu.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{94, 242, 246, 45}, {94, 242, 246, 46}, {94, 242, 246, 77}, {94, 242, 246, 38}, {94, 242, 246, 47}}},
{Country: "Mexico", City: "", Hostname: "mx.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{169, 57, 35, 104}}},
{Country: "Moldova", City: "", Hostname: "md.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 163, 46, 141}}},
{Country: "Netherlands", City: "", Hostname: "nl.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{190, 2, 132, 115}, {190, 2, 132, 16}, {190, 2, 132, 52}}},
{Country: "New Zealand", City: "", Hostname: "nz.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{103, 75, 119, 109}, {103, 75, 119, 107}, {103, 75, 119, 105}, {103, 75, 119, 102}, {103, 75, 119, 103}, {103, 75, 119, 104}, {103, 75, 119, 106}, {103, 75, 119, 108}, {103, 75, 119, 101}, {103, 75, 119, 11}}},
{Country: "Norway", City: "", Hostname: "no.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 90, 61, 21}, {185, 90, 61, 74}}},
{Country: "Oman", City: "", Hostname: "om.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 226, 124, 110}}},
{Country: "Poland", City: "", Hostname: "pl.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{37, 120, 156, 234}}},
{Country: "Portugal", City: "", Hostname: "pt.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 31, 159, 110}}},
{Country: "Romania", City: "", Hostname: "ro.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 144, 83, 11}, {93, 115, 92, 207}, {185, 144, 83, 13}, {77, 81, 98, 70}, {93, 115, 92, 208}}},
{Country: "Serbia", City: "", Hostname: "rs.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{152, 89, 160, 142}}},
{Country: "Singapore", City: "", Hostname: "sg-free.vpnunlimitedapp.com", Free: true, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{178, 128, 48, 177}, {188, 166, 177, 236}, {206, 189, 80, 158}, {178, 128, 117, 139}}},
{Country: "Singapore", City: "", Hostname: "sg.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{50, 7, 60, 52}, {117, 20, 41, 9}, {117, 20, 41, 10}, {139, 99, 62, 61}}},
{Country: "Slovakia", City: "", Hostname: "sk.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{46, 29, 2, 131}}},
{Country: "Slovenia", City: "", Hostname: "si.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{192, 71, 244, 38}, {192, 71, 244, 28}}},
{Country: "South Africa", City: "", Hostname: "za.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{129, 232, 130, 187}, {129, 232, 219, 196}, {129, 232, 133, 41}, {129, 232, 129, 157}, {129, 232, 219, 195}, {129, 232, 134, 122}, {129, 232, 130, 186}, {129, 232, 130, 179}}},
{Country: "Spain", City: "", Hostname: "es.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{194, 99, 104, 58}, {195, 206, 107, 134}}},
{Country: "Sweden", City: "", Hostname: "se.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{91, 132, 138, 174}}},
{Country: "Switzerland", City: "", Hostname: "ch.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{152, 89, 162, 90}, {152, 89, 162, 86}}},
{Country: "Thailand", City: "", Hostname: "th.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{103, 159, 3, 121}}},
{Country: "Turkey", City: "", Hostname: "tr.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 17, 115, 62}, {185, 73, 202, 218}}},
{Country: "United Arab Emirates", City: "", Hostname: "ae.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{45, 9, 249, 201}, {45, 9, 249, 209}, {45, 9, 250, 147}, {45, 9, 250, 249}, {45, 9, 250, 138}, {45, 9, 249, 211}, {45, 9, 250, 144}, {45, 9, 249, 216}, {45, 9, 250, 145}, {45, 9, 250, 143}, {45, 9, 250, 134}, {45, 9, 250, 146}, {45, 9, 249, 202}}},
{Country: "United Kingdom", City: "", Hostname: "uk.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{176, 227, 198, 122}, {77, 245, 65, 2}, {109, 73, 77, 18}, {5, 152, 213, 186}, {88, 150, 224, 74}, {88, 150, 180, 82}}},
{Country: "United Kingdom", City: "London", Hostname: "uk-cv.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{5, 101, 169, 146}, {5, 101, 143, 66}, {178, 159, 10, 78}}},
{Country: "United Kingdom", City: "London", Hostname: "uk-lon.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{78, 110, 160, 6}, {50, 7, 114, 220}, {5, 101, 136, 154}, {23, 106, 33, 89}}},
{Country: "United States", City: "", Hostname: "us-stream.vpnunlimitedapp.com", Free: false, Stream: true, TCP: false, UDP: true, IPs: []net.IP{{167, 99, 96, 113}, {198, 199, 114, 155}, {192, 241, 194, 208}, {165, 227, 49, 171}, {159, 89, 128, 183}, {138, 197, 203, 142}, {64, 227, 111, 143}, {143, 110, 225, 79}, {164, 90, 144, 44}, {198, 199, 103, 243}, {198, 199, 96, 52}, {128, 199, 9, 51}, {143, 110, 156, 9}, {178, 128, 79, 75}, {198, 199, 97, 247}, {198, 199, 105, 87}, {198, 199, 103, 88}, {206, 189, 211, 205}, {206, 189, 165, 44}, {161, 35, 236, 242}}},
{Country: "United States", City: "", Hostname: "us.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{199, 115, 117, 81}, {199, 115, 115, 139}, {207, 244, 72, 212}, {199, 115, 115, 160}, {199, 115, 117, 73}}},
{Country: "United States", City: "Chicago", Hostname: "us-chi.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{66, 23, 205, 226}, {108, 62, 202, 211}, {173, 234, 41, 130}, {174, 34, 184, 130}}},
{Country: "United States", City: "Dallas", Hostname: "us-dal.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{172, 241, 115, 99}, {172, 241, 113, 19}, {172, 241, 112, 92}}},
{Country: "United States", City: "Denver", Hostname: "us-den.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{23, 237, 26, 131}, {23, 237, 26, 67}}},
{Country: "United States", City: "Houston", Hostname: "us-hou.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{162, 218, 228, 194}, {162, 218, 228, 196}, {66, 187, 75, 122}, {162, 218, 229, 106}}},
{Country: "United States", City: "Las Vegas", Hostname: "us-lv.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{185, 242, 5, 18}, {185, 242, 5, 22}}},
{Country: "United States", City: "Los Angeles", Hostname: "us-la.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{64, 31, 33, 154}, {192, 184, 48, 10}, {23, 83, 37, 209}, {23, 83, 37, 213}, {45, 136, 131, 40}, {69, 162, 99, 70}}},
{Country: "United States", City: "Miami", Hostname: "us-mia.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{186, 233, 185, 29}, {186, 233, 185, 79}, {186, 233, 185, 80}, {186, 233, 184, 187}, {186, 233, 184, 188}, {186, 233, 184, 37}, {186, 233, 184, 31}}},
{Country: "United States", City: "New York", Hostname: "us-ny-free.vpnunlimitedapp.com", Free: true, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{64, 94, 215, 66}, {64, 94, 215, 162}, {64, 94, 215, 170}}},
{Country: "United States", City: "New York", Hostname: "us-ny.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{64, 42, 178, 202}, {23, 105, 134, 162}, {64, 42, 178, 226}, {23, 237, 58, 112}, {23, 108, 31, 122}}},
{Country: "United States", City: "Saint Louis", Hostname: "us-sl.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{69, 64, 58, 110}, {69, 64, 58, 255}, {209, 239, 123, 77}, {209, 239, 123, 107}}},
{Country: "United States", City: "Salt Lake City", Hostname: "us-slc.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{209, 95, 53, 223}, {209, 95, 53, 225}}},
{Country: "United States", City: "San Francisco", Hostname: "us-sf.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{209, 58, 139, 34}, {209, 58, 135, 72}, {209, 58, 130, 210}, {209, 58, 135, 106}, {209, 58, 135, 108}, {209, 58, 135, 74}, {209, 58, 139, 35}, {209, 58, 137, 94}, {172, 241, 251, 164}, {209, 58, 135, 120}}},
{Country: "United States", City: "Seattle", Hostname: "us-sea.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{216, 244, 82, 50}, {23, 81, 209, 137}, {216, 244, 82, 210}}},
{Country: "Vietnam", City: "", Hostname: "vn.vpnunlimitedapp.com", Free: false, Stream: false, TCP: false, UDP: true, IPs: []net.IP{{103, 9, 78, 84}, {146, 196, 67, 7}}},
}
}

View File

@@ -21,6 +21,7 @@ func VyprvpnRegionChoices() (choices []string) {
}
//nolint:lll
// VyprvpnServers returns a slice of all the VyprVPN servers.
func VyprvpnServers() []models.VyprvpnServer {
return []models.VyprvpnServer{
{Region: "Algeria", Hostname: "dz1.vyprvpn.com", TCP: false, UDP: true, IPs: []net.IP{{209, 99, 75, 20}}},

View File

@@ -40,6 +40,7 @@ func WindscribeHostnameChoices() (choices []string) {
}
//nolint:lll
// WindscribeServers returns a slice of all the Windscribe servers.
func WindscribeServers() []models.WindscribeServer {
return []models.WindscribeServer{
{Region: "Albania", City: "Tirana", Hostname: "al-002.whiskergalaxy.com", IPs: []net.IP{{31, 171, 152, 178}, {31, 171, 152, 179}, {31, 171, 152, 180}}},

View File

@@ -159,6 +159,11 @@ func (l *looper) Run(ctx context.Context, done chan<- struct{}) {
stayHere = false
case err := <-waitError: // unexpected error
unboundCancel()
if ctx.Err() != nil {
close(waitError)
closeStreams()
return
}
l.state.setStatusWithLock(constants.Crashed)
const fallback = true
l.useUnencryptedDNS(fallback)

View File

@@ -6,7 +6,6 @@ import (
"strings"
"time"
"github.com/kyokomi/emoji"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
)
@@ -36,7 +35,7 @@ func title() []string {
"=========== For tunneling to ============",
"======== your favorite VPN server =======",
"=========================================",
"=== Made with " + emoji.Sprint(":heart:") + " by github.com/qdm12 ====",
"=== Made with ❤️ by github.com/qdm12 ====",
"=========================================",
}
}
@@ -49,14 +48,14 @@ func announcement() []string {
if time.Now().After(expirationDate) {
return nil
}
return []string{emoji.Sprint(":mega: ") + constants.Announcement}
return []string{"📣" + constants.Announcement}
}
func links() []string {
return []string{
emoji.Sprint(":wrench: ") + "Need help? " + constants.IssueLink,
emoji.Sprint(":computer: ") + "Email? quentin.mcgaw@gmail.com",
emoji.Sprint(":coffee: ") + "Slack? Join from the Slack button on Github",
emoji.Sprint(":money_with_wings: ") + "Help me? https://github.com/sponsors/qdm12",
"🔧 Need help? " + constants.IssueLink,
"💻 Email? quentin.mcgaw@gmail.com",
"Slack? Join from the Slack button on Github",
"💰 Help me? https://github.com/sponsors/qdm12",
}
}

View File

@@ -47,6 +47,20 @@ func (s *HideMyAssServer) String() string {
s.Country, s.Region, s.City, s.Hostname, s.TCP, s.UDP, goStringifyIPs(s.IPs))
}
type IpvanishServer struct {
Country string `json:"country"`
City string `json:"city"`
Hostname string `json:"hostname"`
TCP bool `json:"tcp"`
UDP bool `json:"udp"`
IPs []net.IP `json:"ips"`
}
func (s *IpvanishServer) String() string {
return fmt.Sprintf("{Country: %q, City: %q, Hostname: %q, TCP: %t, UDP: %t, IPs: %s}",
s.Country, s.City, s.Hostname, s.TCP, s.UDP, goStringifyIPs(s.IPs))
}
type IvpnServer struct {
Country string `json:"country"`
City string `json:"city"`
@@ -188,6 +202,22 @@ func (s *TorguardServer) String() string {
s.Country, s.City, s.Hostname, s.TCP, s.UDP, goStringifyIPs(s.IPs))
}
type VPNUnlimitedServer struct {
Country string `json:"country"`
City string `json:"city"`
Hostname string `json:"hostname"`
Free bool `json:"free"`
Stream bool `json:"stream"`
TCP bool `json:"tcp"`
UDP bool `json:"udp"`
IPs []net.IP `json:"ips"`
}
func (s *VPNUnlimitedServer) String() string {
return fmt.Sprintf("{Country: %q, City: %q, Hostname: %q, Free: %t, Stream: %t, TCP: %t, UDP: %t, IPs: %s}",
s.Country, s.City, s.Hostname, s.Free, s.Stream, s.TCP, s.UDP, goStringifyIPs(s.IPs))
}
type VyprvpnServer struct {
Region string `json:"region"`
Hostname string `json:"hostname"`

View File

@@ -5,6 +5,7 @@ type AllServers struct {
Cyberghost CyberghostServers `json:"cyberghost"`
Fastestvpn FastestvpnServers `json:"fastestvpn"`
HideMyAss HideMyAssServers `json:"hidemyass"`
Ipvanish IpvanishServers `json:"ipvanish"`
Ivpn IvpnServers `json:"ivpn"`
Mullvad MullvadServers `json:"mullvad"`
Nordvpn NordvpnServers `json:"nordvpn"`
@@ -15,6 +16,7 @@ type AllServers struct {
Purevpn PurevpnServers `json:"purevpn"`
Surfshark SurfsharkServers `json:"surfshark"`
Torguard TorguardServers `json:"torguard"`
VPNUnlimited VPNUnlimitedServers `json:"vpnunlimited"`
Vyprvpn VyprvpnServers `json:"vyprvpn"`
Windscribe WindscribeServers `json:"windscribe"`
}
@@ -23,6 +25,7 @@ func (a *AllServers) Count() int {
return len(a.Cyberghost.Servers) +
len(a.Fastestvpn.Servers) +
len(a.HideMyAss.Servers) +
len(a.Ipvanish.Servers) +
len(a.Ivpn.Servers) +
len(a.Mullvad.Servers) +
len(a.Nordvpn.Servers) +
@@ -33,6 +36,7 @@ func (a *AllServers) Count() int {
len(a.Purevpn.Servers) +
len(a.Surfshark.Servers) +
len(a.Torguard.Servers) +
len(a.VPNUnlimited.Servers) +
len(a.Vyprvpn.Servers) +
len(a.Windscribe.Servers)
}
@@ -52,6 +56,11 @@ type HideMyAssServers struct {
Timestamp int64 `json:"timestamp"`
Servers []HideMyAssServer `json:"servers"`
}
type IpvanishServers struct {
Version uint16 `json:"version"`
Timestamp int64 `json:"timestamp"`
Servers []IpvanishServer `json:"servers"`
}
type IvpnServers struct {
Version uint16 `json:"version"`
Timestamp int64 `json:"timestamp"`
@@ -102,6 +111,11 @@ type TorguardServers struct {
Timestamp int64 `json:"timestamp"`
Servers []TorguardServer `json:"servers"`
}
type VPNUnlimitedServers struct {
Version uint16 `json:"version"`
Timestamp int64 `json:"timestamp"`
Servers []VPNUnlimitedServer `json:"servers"`
}
type VyprvpnServers struct {
Version uint16 `json:"version"`
Timestamp int64 `json:"timestamp"`

View File

@@ -11,6 +11,7 @@ import (
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/provider/utils"
"github.com/qdm12/golibs/os"
)
@@ -64,6 +65,7 @@ func modifyCustomConfig(lines []string, username string,
strings.HasPrefix(line, "verb "),
strings.HasPrefix(line, "auth-user-pass "),
len(settings.Cipher) > 0 && strings.HasPrefix(line, "cipher "),
len(settings.Cipher) > 0 && strings.HasPrefix(line, "data-ciphers"),
len(settings.Auth) > 0 && strings.HasPrefix(line, "auth "),
settings.MSSFix > 0 && strings.HasPrefix(line, "mssfix "),
!settings.Provider.ExtraConfigOptions.OpenVPNIPv6 && strings.HasPrefix(line, "tun-ipv6"):
@@ -78,10 +80,12 @@ func modifyCustomConfig(lines []string, username string,
modified = append(modified, "pull-filter ignore \"auth-token\"") // prevent auth failed loop
modified = append(modified, "auth-retry nointeract")
modified = append(modified, "suppress-timestamps")
if settings.User != "" {
modified = append(modified, "auth-user-pass "+constants.OpenVPNAuthConf)
}
modified = append(modified, "verb "+strconv.Itoa(settings.Verbosity))
if len(settings.Cipher) > 0 {
modified = append(modified, "cipher "+settings.Cipher)
modified = append(modified, utils.CipherLines(settings.Cipher, settings.Version)...)
}
if len(settings.Auth) > 0 {
modified = append(modified, "auth "+settings.Auth)
@@ -193,10 +197,10 @@ func setConnectionToLines(lines []string, connection models.OpenVPNConnection) (
for i, line := range lines {
switch {
case strings.HasPrefix(line, "proto "):
lines[i] = "proto " + connection.Protocol
lines[i] = connection.ProtoLine()
case strings.HasPrefix(line, "remote "):
lines[i] = "remote " + connection.RemoteLine()
lines[i] = connection.RemoteLine()
}
}

View File

@@ -143,11 +143,13 @@ func (l *looper) Run(ctx context.Context, done chan<- struct{}) { //nolint:gocog
continue
}
if settings.User != "" {
if err := l.conf.WriteAuthFile(settings.User, settings.Password, l.puid, l.pgid); err != nil {
l.signalCrashedStatus()
l.logAndWait(ctx, err)
continue
}
}
if err := l.fw.SetVPNConnection(ctx, connection); err != nil {
l.signalCrashedStatus()
@@ -211,6 +213,14 @@ func (l *looper) Run(ctx context.Context, done chan<- struct{}) { //nolint:gocog
stayHere = false
case err := <-waitError: // unexpected error
openvpnCancel()
if ctx.Err() != nil {
close(waitError)
close(stdoutLines)
close(stderrLines)
<-lineCollectionDone
<-portForwardDone
return
}
l.state.setStatusWithLock(constants.Crashed)
l.logAndWait(ctx, err)
l.crashed = true
@@ -317,8 +327,5 @@ func writeOpenvpnConf(lines []string, openFile os.OpenFileFunc) error {
if err != nil {
return err
}
if err := file.Close(); err != nil {
return err
}
return nil
return file.Close()
}

View File

@@ -23,7 +23,7 @@ func (c *configurator) CheckTUN() error {
func (c *configurator) CreateTUN() error {
c.logger.Info("creating %s", constants.TunnelDevice)
if err := c.os.MkdirAll("/dev/net", 0751); err != nil {
if err := c.os.MkdirAll("/dev/net", 0751); err != nil { //nolint:gomnd
return err
}
@@ -36,7 +36,7 @@ func (c *configurator) CreateTUN() error {
return err
}
file, err := c.os.OpenFile(constants.TunnelDevice, os.O_WRONLY, 0666)
file, err := c.os.OpenFile(constants.TunnelDevice, os.O_WRONLY, 0666) //nolint:gomnd
if err != nil {
return err
}

View File

@@ -0,0 +1,45 @@
package ipvanish
import (
"errors"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/provider/utils"
)
var ErrProtocolUnsupported = errors.New("network protocol is not supported")
func (i *Ipvanish) GetOpenVPNConnection(selection configuration.ServerSelection) (
connection models.OpenVPNConnection, err error) {
const port = 443
const protocol = constants.UDP
if selection.TCP {
return connection, ErrProtocolUnsupported
}
servers, err := i.filterServers(selection)
if err != nil {
return connection, err
}
var connections []models.OpenVPNConnection
for _, server := range servers {
for _, IP := range server.IPs {
connection := models.OpenVPNConnection{
IP: IP,
Port: port,
Protocol: protocol,
Hostname: server.Hostname,
}
connections = append(connections, connection)
}
}
if selection.TargetIP != nil {
return utils.GetTargetIPConnection(connections, selection.TargetIP)
}
return utils.PickRandomConnection(connections, i.randSource), nil
}

View File

@@ -0,0 +1,29 @@
package ipvanish
import (
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/provider/utils"
)
func (i *Ipvanish) filterServers(selection configuration.ServerSelection) (
servers []models.IpvanishServer, err error) {
for _, server := range i.servers {
switch {
case
utils.FilterByPossibilities(server.Country, selection.Countries),
utils.FilterByPossibilities(server.City, selection.Cities),
utils.FilterByPossibilities(server.Hostname, selection.Hostnames),
selection.TCP && !server.TCP,
!selection.TCP && !server.UDP:
default:
servers = append(servers, server)
}
}
if len(servers) == 0 {
return nil, utils.NoServerFoundError(selection)
}
return servers, nil
}

View File

@@ -0,0 +1,65 @@
package ipvanish
import (
"strconv"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/provider/utils"
)
func (i *Ipvanish) BuildConf(connection models.OpenVPNConnection,
username string, settings configuration.OpenVPN) (lines []string) {
if settings.Cipher == "" {
settings.Cipher = constants.AES256cbc
}
if settings.Auth == "" {
settings.Auth = constants.SHA256
}
lines = []string{
"client",
"dev tun",
"nobind",
"persist-key",
"ping-timer-rem",
"tls-exit",
// Ipvanish specific
"comp-lzo",
"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",
"keysize 256",
// Added constant values
"mute-replay-warnings",
"auth-nocache",
"pull-filter ignore \"auth-token\"", // prevent auth failed loops
"auth-retry nointeract",
"suppress-timestamps",
// Modified variables
"verb " + strconv.Itoa(settings.Verbosity),
"auth-user-pass " + constants.OpenVPNAuthConf,
"proto " + connection.Protocol,
connection.RemoteLine(),
"verify-x509-name " + connection.Hostname, // + " name"
"auth " + settings.Auth,
}
lines = append(lines, utils.CipherLines(settings.Cipher, settings.Version)...)
if settings.MSSFix > 0 {
lines = append(lines, "mssfix "+strconv.Itoa(int(settings.MSSFix)))
}
if !settings.Root {
lines = append(lines, "user "+username)
}
lines = append(lines, utils.WrapOpenvpnCA(constants.IpvanishCA)...)
lines = append(lines, "")
return lines
}

View File

@@ -0,0 +1,17 @@
package ipvanish
import (
"context"
"net"
"net/http"
"github.com/qdm12/gluetun/internal/firewall"
"github.com/qdm12/golibs/logging"
"github.com/qdm12/golibs/os"
)
func (i *Ipvanish) PortForward(ctx context.Context, client *http.Client,
openFile os.OpenFileFunc, pfLogger logging.Logger, gateway net.IP,
fw firewall.Configurator, syncState func(port uint16) (pfFilepath string)) {
panic("port forwarding is not supported for Ipvanish")
}

View File

@@ -0,0 +1,19 @@
package ipvanish
import (
"math/rand"
"github.com/qdm12/gluetun/internal/models"
)
type Ipvanish struct {
servers []models.IpvanishServer
randSource rand.Source
}
func New(servers []models.IpvanishServer, randSource rand.Source) *Ipvanish {
return &Ipvanish{
servers: servers,
randSource: randSource,
}
}

View File

@@ -2,6 +2,7 @@ package ivpn
import (
"strconv"
"strings"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
@@ -15,6 +16,8 @@ func (i *Ivpn) BuildConf(connection models.OpenVPNConnection,
settings.Cipher = constants.AES256cbc
}
namePrefix := strings.Split(connection.Hostname, ".")[0]
lines = []string{
"client",
"dev tun",
@@ -43,7 +46,7 @@ func (i *Ivpn) BuildConf(connection models.OpenVPNConnection,
"auth-user-pass " + constants.OpenVPNAuthConf,
"proto " + connection.Protocol,
connection.RemoteLine(),
"verify-x509-name " + connection.Hostname, // + " name-prefix"
"verify-x509-name " + namePrefix + " name-prefix",
}
lines = append(lines, utils.CipherLines(settings.Cipher, settings.Version)...)

View File

@@ -2,7 +2,6 @@ package privateinternetaccess
import (
"strconv"
"strings"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
@@ -25,8 +24,8 @@ func (p *PIA) BuildConf(connection models.OpenVPNConnection,
X509CRL = constants.PiaX509CRLStrong
certificate = constants.PIACertificateStrong
default: // no encryption preset
defaultCipher = ""
defaultAuth = ""
defaultCipher = "none"
defaultAuth = "none"
X509CRL = constants.PiaX509CRLNormal
certificate = constants.PIACertificateNormal
}
@@ -50,6 +49,7 @@ func (p *PIA) BuildConf(connection models.OpenVPNConnection,
"reneg-sec 0",
"disable-occ",
"compress", // allow PIA server to choose the compression to use
"ncp-disable", // prevent from auto-upgrading cipher to aes-256-gcm
// Added constant values
"auth-nocache",
@@ -73,10 +73,6 @@ func (p *PIA) BuildConf(connection models.OpenVPNConnection,
lines = append(lines, "auth "+settings.Auth)
}
if strings.HasSuffix(settings.Cipher, "-gcm") {
lines = append(lines, "ncp-disable")
}
if !settings.Root {
lines = append(lines, "user "+username)
}

View File

@@ -25,6 +25,7 @@ var (
ErrBindPort = errors.New("cannot bind port")
)
// PortForward obtains a VPN server side port forwarded from PIA.
//nolint:gocognit
func (p *PIA) PortForward(ctx context.Context, client *http.Client,
openFile os.OpenFileFunc, logger logging.Logger, gateway net.IP, fw firewall.Configurator,

View File

@@ -15,6 +15,7 @@ import (
"github.com/qdm12/gluetun/internal/provider/cyberghost"
"github.com/qdm12/gluetun/internal/provider/fastestvpn"
"github.com/qdm12/gluetun/internal/provider/hidemyass"
"github.com/qdm12/gluetun/internal/provider/ipvanish"
"github.com/qdm12/gluetun/internal/provider/ivpn"
"github.com/qdm12/gluetun/internal/provider/mullvad"
"github.com/qdm12/gluetun/internal/provider/nordvpn"
@@ -25,6 +26,7 @@ import (
"github.com/qdm12/gluetun/internal/provider/purevpn"
"github.com/qdm12/gluetun/internal/provider/surfshark"
"github.com/qdm12/gluetun/internal/provider/torguard"
"github.com/qdm12/gluetun/internal/provider/vpnunlimited"
"github.com/qdm12/gluetun/internal/provider/vyprvpn"
"github.com/qdm12/gluetun/internal/provider/windscribe"
"github.com/qdm12/golibs/logging"
@@ -49,6 +51,8 @@ func New(provider string, allServers models.AllServers, timeNow func() time.Time
return fastestvpn.New(allServers.Fastestvpn.Servers, randSource)
case constants.HideMyAss:
return hidemyass.New(allServers.HideMyAss.Servers, randSource)
case constants.Ipvanish:
return ipvanish.New(allServers.Ipvanish.Servers, randSource)
case constants.Ivpn:
return ivpn.New(allServers.Ivpn.Servers, randSource)
case constants.Mullvad:
@@ -69,6 +73,8 @@ func New(provider string, allServers models.AllServers, timeNow func() time.Time
return surfshark.New(allServers.Surfshark.Servers, randSource)
case constants.Torguard:
return torguard.New(allServers.Torguard.Servers, randSource)
case constants.VPNUnlimited:
return vpnunlimited.New(allServers.VPNUnlimited.Servers, randSource)
case constants.Vyprvpn:
return vyprvpn.New(allServers.Vyprvpn.Servers, randSource)
case constants.Windscribe:

View File

@@ -12,7 +12,7 @@ import (
func (p *Purevpn) BuildConf(connection models.OpenVPNConnection,
username string, settings configuration.OpenVPN) (lines []string) {
if settings.Cipher == "" {
settings.Cipher = constants.AES256cbc
settings.Cipher = constants.AES256gcm
}
lines = []string{

View File

@@ -0,0 +1,44 @@
package vpnunlimited
import (
"errors"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/provider/utils"
)
var ErrProtocolUnsupported = errors.New("network protocol is not supported")
func (p *Provider) GetOpenVPNConnection(selection configuration.ServerSelection) (
connection models.OpenVPNConnection, err error) {
const port = 1194
const protocol = constants.UDP
if selection.TCP {
return connection, ErrProtocolUnsupported
}
servers, err := p.filterServers(selection)
if err != nil {
return connection, err
}
var connections []models.OpenVPNConnection
for _, server := range servers {
for _, IP := range server.IPs {
connection := models.OpenVPNConnection{
IP: IP,
Port: port,
Protocol: protocol,
}
connections = append(connections, connection)
}
}
if selection.TargetIP != nil {
return utils.GetTargetIPConnection(connections, selection.TargetIP)
}
return utils.PickRandomConnection(connections, p.randSource), nil
}

View File

@@ -0,0 +1,31 @@
package vpnunlimited
import (
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/provider/utils"
)
func (p *Provider) filterServers(selection configuration.ServerSelection) (
servers []models.VPNUnlimitedServer, err error) {
for _, server := range p.servers {
switch {
case
utils.FilterByPossibilities(server.Country, selection.Countries),
utils.FilterByPossibilities(server.City, selection.Cities),
utils.FilterByPossibilities(server.Hostname, selection.Hostnames),
selection.FreeOnly && !server.Free,
selection.StreamOnly && !server.Stream,
selection.TCP && !server.TCP,
!selection.TCP && !server.UDP:
default:
servers = append(servers, server)
}
}
if len(servers) == 0 {
return nil, utils.NoServerFoundError(selection)
}
return servers, nil
}

View File

@@ -0,0 +1,69 @@
package vpnunlimited
import (
"strconv"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/provider/utils"
)
func (p *Provider) BuildConf(connection models.OpenVPNConnection,
username string, settings configuration.OpenVPN) (lines []string) {
lines = []string{
"client",
"dev tun",
"nobind",
"persist-key",
"tls-exit",
"remote-cert-tls server",
// VPNUnlimited specific
"reneg-sec 0",
"ping 5",
"ping-exit 30",
"comp-lzo no",
"route-metric 1",
// Added constant values
"auth-nocache",
"mute-replay-warnings",
"pull-filter ignore \"auth-token\"", // prevent auth failed loops
"auth-retry nointeract",
"suppress-timestamps",
// Modified variables
"verb " + strconv.Itoa(settings.Verbosity),
// "auth-user-pass " + constants.OpenVPNAuthConf,
connection.ProtoLine(),
connection.RemoteLine(),
}
if settings.Cipher != "" {
lines = append(lines, utils.CipherLines(settings.Cipher, settings.Version)...)
}
if settings.Auth != "" {
lines = append(lines, "auth "+settings.Auth)
}
if settings.MSSFix > 0 {
lines = append(lines, "mssfix "+strconv.Itoa(int(settings.MSSFix)))
}
if !settings.Root {
lines = append(lines, "user "+username)
}
lines = append(lines, utils.WrapOpenvpnCA(
constants.VPNUnlimitedCertificateAuthority)...)
lines = append(lines, utils.WrapOpenvpnCert(
settings.Provider.ExtraConfigOptions.ClientCertificate)...)
lines = append(lines, utils.WrapOpenvpnKey(
settings.Provider.ExtraConfigOptions.ClientKey)...)
lines = append(lines, "")
return lines
}

View File

@@ -0,0 +1,17 @@
package vpnunlimited
import (
"context"
"net"
"net/http"
"github.com/qdm12/gluetun/internal/firewall"
"github.com/qdm12/golibs/logging"
"github.com/qdm12/golibs/os"
)
func (p *Provider) PortForward(ctx context.Context, client *http.Client,
openFile os.OpenFileFunc, pfLogger logging.Logger, gateway net.IP,
fw firewall.Configurator, syncState func(port uint16) (pfFilepath string)) {
panic("port forwarding is not supported for VPN Unlimited")
}

View File

@@ -0,0 +1,19 @@
package vpnunlimited
import (
"math/rand"
"github.com/qdm12/gluetun/internal/models"
)
type Provider struct {
servers []models.VPNUnlimitedServer
randSource rand.Source
}
func New(servers []models.VPNUnlimitedServer, randSource rand.Source) *Provider {
return &Provider{
servers: servers,
randSource: randSource,
}
}

View File

@@ -31,11 +31,7 @@ func (r *routing) setOutboundRoutes(outboundSubnets []net.IPNet,
}
r.removeOutboundSubnets(subnetsToRemove, defaultInterfaceName, defaultGateway)
if err := r.addOutboundSubnets(subnetsToAdd, defaultInterfaceName, defaultGateway); err != nil {
return err
}
return nil
return r.addOutboundSubnets(subnetsToAdd, defaultInterfaceName, defaultGateway)
}
func (r *routing) removeOutboundSubnets(subnets []net.IPNet,

View File

@@ -139,6 +139,9 @@ func (l *looper) Run(ctx context.Context, done chan<- struct{}) {
case err := <-waitError: // unexpected error
shadowsocksCancel()
close(waitError)
if ctx.Err() != nil {
return
}
l.state.setStatusWithLock(constants.Crashed)
l.logAndWait(ctx, err)
crashed = true

View File

@@ -1,49 +0,0 @@
package shutdown
import (
"context"
"errors"
"fmt"
"time"
"github.com/qdm12/golibs/logging"
)
type Order interface {
Append(waves ...Wave)
Shutdown(timeout time.Duration, logger logging.Logger) (err error)
}
type order struct {
waves []Wave
}
func NewOrder() Order {
return &order{}
}
var ErrIncomplete = errors.New("one or more routines did not terminate gracefully")
func (o *order) Append(waves ...Wave) {
o.waves = append(o.waves, waves...)
}
func (o *order) Shutdown(timeout time.Duration, logger logging.Logger) (err error) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
total := 0
incomplete := 0
for _, wave := range o.waves {
total += wave.size()
incomplete += wave.shutdown(ctx, logger)
}
if incomplete == 0 {
return nil
}
return fmt.Errorf("%w: %d not terminated on %d routines",
ErrIncomplete, incomplete, total)
}

View File

@@ -1,28 +0,0 @@
package shutdown
import (
"context"
"fmt"
"time"
)
type routine struct {
name string
cancel context.CancelFunc
done <-chan struct{}
timeout time.Duration
}
func (r *routine) shutdown(ctx context.Context) (err error) {
ctx, cancel := context.WithTimeout(ctx, r.timeout)
defer cancel()
r.cancel()
select {
case <-r.done:
return nil
case <-ctx.Done():
return fmt.Errorf("for routine %q: %w", r.name, ctx.Err())
}
}

View File

@@ -1,66 +0,0 @@
package shutdown
import (
"context"
"time"
"github.com/qdm12/golibs/logging"
)
type Wave interface {
Add(name string, timeout time.Duration) (
ctx context.Context, done chan struct{})
size() int
shutdown(ctx context.Context, logger logging.Logger) (incomplete int)
}
type wave struct {
name string
routines []routine
}
func NewWave(name string) Wave {
return &wave{
name: name,
}
}
func (w *wave) Add(name string, timeout time.Duration) (ctx context.Context, done chan struct{}) {
ctx, cancel := context.WithCancel(context.Background())
done = make(chan struct{})
routine := routine{
name: name,
cancel: cancel,
done: done,
timeout: timeout,
}
w.routines = append(w.routines, routine)
return ctx, done
}
func (w *wave) size() int { return len(w.routines) }
func (w *wave) shutdown(ctx context.Context, logger logging.Logger) (incomplete int) {
completed := make(chan bool)
for _, r := range w.routines {
go func(r routine) {
if err := r.shutdown(ctx); err != nil {
logger.Warn(w.name + " routines: " + err.Error() + " ⚠️")
completed <- false
} else {
logger.Info(w.name + " routines: " + r.name + " terminated ✔️")
completed <- err == nil
}
}(r)
}
for range w.routines {
c := <-completed
if !c {
incomplete++
}
}
return incomplete
}

View File

@@ -4,6 +4,7 @@ import (
"strconv"
"time"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
)
@@ -35,6 +36,7 @@ func (s *storage) mergeServers(hardcoded, persisted models.AllServers) models.Al
Cyberghost: s.mergeCyberghost(hardcoded.Cyberghost, persisted.Cyberghost),
Fastestvpn: s.mergeFastestvpn(hardcoded.Fastestvpn, persisted.Fastestvpn),
HideMyAss: s.mergeHideMyAss(hardcoded.HideMyAss, persisted.HideMyAss),
Ipvanish: s.mergeIpvanish(hardcoded.Ipvanish, persisted.Ipvanish),
Ivpn: s.mergeIvpn(hardcoded.Ivpn, persisted.Ivpn),
Mullvad: s.mergeMullvad(hardcoded.Mullvad, persisted.Mullvad),
Nordvpn: s.mergeNordVPN(hardcoded.Nordvpn, persisted.Nordvpn),
@@ -45,6 +47,7 @@ func (s *storage) mergeServers(hardcoded, persisted models.AllServers) models.Al
Purevpn: s.mergePureVPN(hardcoded.Purevpn, persisted.Purevpn),
Surfshark: s.mergeSurfshark(hardcoded.Surfshark, persisted.Surfshark),
Torguard: s.mergeTorguard(hardcoded.Torguard, persisted.Torguard),
VPNUnlimited: s.mergeVPNUnlimited(hardcoded.VPNUnlimited, persisted.VPNUnlimited),
Vyprvpn: s.mergeVyprvpn(hardcoded.Vyprvpn, persisted.Vyprvpn),
Windscribe: s.mergeWindscribe(hardcoded.Windscribe, persisted.Windscribe),
}
@@ -91,6 +94,19 @@ func (s *storage) mergeHideMyAss(hardcoded, persisted models.HideMyAssServers) m
return persisted
}
func (s *storage) mergeIpvanish(hardcoded, persisted models.IpvanishServers) models.IpvanishServers {
if persisted.Timestamp <= hardcoded.Timestamp {
return hardcoded
}
versionDiff := hardcoded.Version - persisted.Version
if versionDiff > 0 {
s.logVersionDiff("Ipvanish", versionDiff)
return hardcoded
}
s.logTimeDiff("Ipvanish", persisted.Timestamp, hardcoded.Timestamp)
return persisted
}
func (s *storage) mergeIvpn(hardcoded, persisted models.IvpnServers) models.IvpnServers {
if persisted.Timestamp <= hardcoded.Timestamp {
return hardcoded
@@ -234,6 +250,20 @@ func (s *storage) mergeTorguard(hardcoded, persisted models.TorguardServers) mod
return persisted
}
func (s *storage) mergeVPNUnlimited(hardcoded, persisted models.VPNUnlimitedServers) models.VPNUnlimitedServers {
if persisted.Timestamp <= hardcoded.Timestamp {
return hardcoded
}
versionDiff := hardcoded.Version - persisted.Version
if versionDiff > 0 {
s.logVersionDiff(constants.VPNUnlimited, versionDiff)
return hardcoded
}
s.logTimeDiff(constants.VPNUnlimited, persisted.Timestamp, hardcoded.Timestamp)
return persisted
}
func (s *storage) mergeVyprvpn(hardcoded, persisted models.VyprvpnServers) models.VyprvpnServers {
if persisted.Timestamp <= hardcoded.Timestamp {
return hardcoded

View File

@@ -21,6 +21,7 @@ func countServers(allServers models.AllServers) int {
return len(allServers.Cyberghost.Servers) +
len(allServers.Fastestvpn.Servers) +
len(allServers.HideMyAss.Servers) +
len(allServers.Ipvanish.Servers) +
len(allServers.Ivpn.Servers) +
len(allServers.Mullvad.Servers) +
len(allServers.Nordvpn.Servers) +
@@ -31,6 +32,7 @@ func countServers(allServers models.AllServers) int {
len(allServers.Purevpn.Servers) +
len(allServers.Surfshark.Servers) +
len(allServers.Torguard.Servers) +
len(allServers.VPNUnlimited.Servers) +
len(allServers.Vyprvpn.Servers) +
len(allServers.Windscribe.Servers)
}

View File

@@ -5,5 +5,5 @@ import sysunix "golang.org/x/sys/unix"
// Constants used for convenience so "os" does not have to be imported
const (
S_IFCHR = sysunix.S_IFCHR //nolint:golint
S_IFCHR = sysunix.S_IFCHR //nolint:revive
)

View File

@@ -4,9 +4,11 @@ import (
"context"
"fmt"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/updater/providers/cyberghost"
"github.com/qdm12/gluetun/internal/updater/providers/fastestvpn"
"github.com/qdm12/gluetun/internal/updater/providers/hidemyass"
"github.com/qdm12/gluetun/internal/updater/providers/ipvanish"
"github.com/qdm12/gluetun/internal/updater/providers/ivpn"
"github.com/qdm12/gluetun/internal/updater/providers/mullvad"
"github.com/qdm12/gluetun/internal/updater/providers/nordvpn"
@@ -17,6 +19,7 @@ import (
"github.com/qdm12/gluetun/internal/updater/providers/purevpn"
"github.com/qdm12/gluetun/internal/updater/providers/surfshark"
"github.com/qdm12/gluetun/internal/updater/providers/torguard"
"github.com/qdm12/gluetun/internal/updater/providers/vpnunlimited"
"github.com/qdm12/gluetun/internal/updater/providers/vyprvpn"
"github.com/qdm12/gluetun/internal/updater/providers/windscribe"
)
@@ -75,6 +78,26 @@ func (u *updater) updateHideMyAss(ctx context.Context) (err error) {
return nil
}
func (u *updater) updateIpvanish(ctx context.Context) (err error) {
minServers := getMinServers(len(u.servers.Ipvanish.Servers))
servers, warnings, err := ipvanish.GetServers(
ctx, u.unzipper, u.presolver, minServers)
if u.options.CLI {
for _, warning := range warnings {
u.logger.Warn("Ipvanish: %s", warning)
}
}
if err != nil {
return err
}
if u.options.Stdout {
u.println(ipvanish.Stringify(servers))
}
u.servers.Ipvanish.Timestamp = u.timeNow().Unix()
u.servers.Ipvanish.Servers = servers
return nil
}
func (u *updater) updateIvpn(ctx context.Context) (err error) {
minServers := getMinServers(len(u.servers.Ivpn.Servers))
servers, warnings, err := ivpn.GetServers(
@@ -261,6 +284,26 @@ func (u *updater) updateTorguard(ctx context.Context) (err error) {
return nil
}
func (u *updater) updateVPNUnlimited(ctx context.Context) (err error) {
minServers := getMinServers(len(u.servers.VPNUnlimited.Servers))
servers, warnings, err := vpnunlimited.GetServers(
ctx, u.unzipper, u.presolver, minServers)
if u.options.CLI {
for _, warning := range warnings {
u.logger.Warn(constants.VPNUnlimited + ": " + warning)
}
}
if err != nil {
return err
}
if u.options.Stdout {
u.println(vpnunlimited.Stringify(servers))
}
u.servers.VPNUnlimited.Timestamp = u.timeNow().Unix()
u.servers.VPNUnlimited.Servers = servers
return nil
}
func (u *updater) updateVyprvpn(ctx context.Context) (err error) {
minServers := getMinServers(len(u.servers.Vyprvpn.Servers))
servers, warnings, err := vyprvpn.GetServers(

View File

@@ -13,9 +13,9 @@ func resolveHosts(ctx context.Context, presolver resolver.Parallel,
hostToIPs map[string][]net.IP, err error) {
const (
maxFailRatio = 1
maxDuration = 10 * time.Second
betweenDuration = 500 * time.Millisecond
maxNoNew = 2
maxDuration = 20 * time.Second
betweenDuration = time.Second
maxNoNew = 4
maxFails = 10
)
settings := resolver.ParallelSettings{

View File

@@ -0,0 +1,39 @@
package ipvanish
import (
"errors"
"fmt"
"strings"
"github.com/qdm12/gluetun/internal/constants"
)
var errCountryCodeUnknown = errors.New("country code is unknown")
func parseFilename(fileName, hostname string) (
country, city string, err error) {
const prefix = "ipvanish-"
s := strings.TrimPrefix(fileName, prefix)
const ext = ".ovpn"
host := strings.Split(hostname, ".")[0]
suffix := "-" + host + ext
s = strings.TrimSuffix(s, suffix)
parts := strings.Split(s, "-")
countryCodes := constants.CountryCodes()
countryCode := strings.ToLower(parts[0])
country, ok := countryCodes[countryCode]
if !ok {
return "", "", fmt.Errorf("%w: %s", errCountryCodeUnknown, countryCode)
}
country = strings.Title(country)
if len(parts) > 1 {
city = strings.Join(parts[1:], " ")
city = strings.Title(city)
}
return country, city, nil
}

View File

@@ -0,0 +1,54 @@
package ipvanish
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_parseFilename(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
fileName string
hostname string
country string
city string
err error
}{
"unknown country code": {
fileName: "ipvanish-unknown-host.ovpn",
hostname: "host.ipvanish.com",
err: errors.New("country code is unknown: unknown"),
},
"country code only": {
fileName: "ipvanish-ca-host.ovpn",
hostname: "host.ipvanish.com",
country: "Canada",
},
"country code and city": {
fileName: "ipvanish-ca-sao-paulo-host.ovpn",
hostname: "host.ipvanish.com",
country: "Canada",
city: "Sao Paulo",
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
country, city, err := parseFilename(testCase.fileName, testCase.hostname)
if testCase.err != nil {
require.Error(t, err)
assert.Equal(t, testCase.err.Error(), err.Error())
} else {
assert.NoError(t, err)
}
assert.Equal(t, testCase.country, country)
assert.Equal(t, testCase.city, city)
})
}
}

View File

@@ -0,0 +1,58 @@
package ipvanish
import (
"net"
"sort"
"github.com/qdm12/gluetun/internal/models"
)
type hostToServer map[string]models.IpvanishServer
func (hts hostToServer) add(host, country, city string, tcp, udp bool) {
server, ok := hts[host]
if !ok {
server.Hostname = host
server.Country = country
server.City = city
}
if tcp {
server.TCP = tcp
}
if udp {
server.UDP = udp
}
hts[host] = server
}
func (hts hostToServer) toHostsSlice() (hosts []string) {
hosts = make([]string, 0, len(hts))
for host := range hts {
hosts = append(hosts, host)
}
sort.Slice(hosts, func(i, j int) bool {
return hosts[i] < hosts[j]
})
return hosts
}
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
for host, IPs := range hostToIPs {
server := hts[host]
server.IPs = IPs
hts[host] = server
}
for host, server := range hts {
if len(server.IPs) == 0 {
delete(hts, host)
}
}
}
func (hts hostToServer) toServersSlice() (servers []models.IpvanishServer) {
servers = make([]models.IpvanishServer, 0, len(hts))
for _, server := range hts {
servers = append(servers, server)
}
return servers
}

View File

@@ -0,0 +1,211 @@
package ipvanish
import (
"net"
"testing"
"github.com/qdm12/gluetun/internal/models"
"github.com/stretchr/testify/assert"
)
func Test_hostToServer_add(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
initialHTS hostToServer
host string
country string
city string
tcp bool
udp bool
expectedHTS hostToServer
}{
"empty host to server": {
initialHTS: hostToServer{},
host: "host",
country: "country",
city: "city",
tcp: true,
udp: true,
expectedHTS: hostToServer{
"host": {
Hostname: "host",
Country: "country",
City: "city",
TCP: true,
UDP: true,
},
},
},
"add server": {
initialHTS: hostToServer{
"existing host": {},
},
host: "host",
country: "country",
city: "city",
tcp: true,
udp: true,
expectedHTS: hostToServer{
"existing host": {},
"host": models.IpvanishServer{
Hostname: "host",
Country: "country",
City: "city",
TCP: true,
UDP: true,
},
},
},
"extend existing server": {
initialHTS: hostToServer{
"host": models.IpvanishServer{
Hostname: "host",
Country: "country",
City: "city",
TCP: true,
},
},
host: "host",
country: "country",
city: "city",
tcp: false,
udp: true,
expectedHTS: hostToServer{
"host": models.IpvanishServer{
Hostname: "host",
Country: "country",
City: "city",
TCP: true,
UDP: true,
},
},
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
testCase.initialHTS.add(testCase.host, testCase.country, testCase.city, testCase.tcp, testCase.udp)
assert.Equal(t, testCase.expectedHTS, testCase.initialHTS)
})
}
}
func Test_hostToServer_toHostsSlice(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
hts hostToServer
hosts []string
}{
"empty host to server": {
hts: hostToServer{},
hosts: []string{},
},
"single host": {
hts: hostToServer{
"A": {},
},
hosts: []string{"A"},
},
"multiple hosts": {
hts: hostToServer{
"A": {},
"B": {},
},
hosts: []string{"A", "B"},
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
hosts := testCase.hts.toHostsSlice()
assert.ElementsMatch(t, testCase.hosts, hosts)
})
}
}
func Test_hostToServer_adaptWithIPs(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
initialHTS hostToServer
hostToIPs map[string][]net.IP
expectedHTS hostToServer
}{
"create server": {
initialHTS: hostToServer{},
hostToIPs: map[string][]net.IP{
"A": {{1, 2, 3, 4}},
},
expectedHTS: hostToServer{
"A": models.IpvanishServer{
IPs: []net.IP{{1, 2, 3, 4}},
},
},
},
"add IPs to existing server": {
initialHTS: hostToServer{
"A": models.IpvanishServer{
Country: "country",
},
},
hostToIPs: map[string][]net.IP{
"A": {{1, 2, 3, 4}},
},
expectedHTS: hostToServer{
"A": models.IpvanishServer{
Country: "country",
IPs: []net.IP{{1, 2, 3, 4}},
},
},
},
"remove server without IP": {
initialHTS: hostToServer{
"A": models.IpvanishServer{
Country: "country",
},
},
hostToIPs: map[string][]net.IP{},
expectedHTS: hostToServer{},
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
testCase.initialHTS.adaptWithIPs(testCase.hostToIPs)
assert.Equal(t, testCase.expectedHTS, testCase.initialHTS)
})
}
}
func Test_hostToServer_toServersSlice(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
hts hostToServer
servers []models.IpvanishServer
}{
"empty host to server": {
hts: hostToServer{},
servers: []models.IpvanishServer{},
},
"multiple servers": {
hts: hostToServer{
"A": {Country: "A"},
"B": {Country: "B"},
},
servers: []models.IpvanishServer{
{Country: "A"},
{Country: "B"},
},
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
servers := testCase.hts.toServersSlice()
assert.ElementsMatch(t, testCase.servers, servers)
})
}
}

View File

@@ -0,0 +1,36 @@
package ipvanish
import (
"context"
"net"
"time"
"github.com/qdm12/gluetun/internal/updater/resolver"
)
func getResolveSettings(minServers int) (settings resolver.ParallelSettings) {
const (
maxFailRatio = 0.1
maxDuration = 20 * time.Second
betweenDuration = time.Second
maxNoNew = 2
maxFails = 2
)
return resolver.ParallelSettings{
MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration,
BetweenDuration: betweenDuration,
MaxNoNew: maxNoNew,
MaxFails: maxFails,
},
}
}
func resolveHosts(ctx context.Context, presolver resolver.Parallel,
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
settings := getResolveSettings(minServers)
return presolver.Resolve(ctx, hosts, settings)
}

View File

@@ -0,0 +1,56 @@
package ipvanish
import (
"context"
"errors"
"net"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver"
"github.com/stretchr/testify/assert"
)
func Test_resolveHosts(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
ctx := context.Background()
presolver := mock_resolver.NewMockParallel(ctrl)
hosts := []string{"host1", "host2"}
const minServers = 10
expectedHostToIPs := map[string][]net.IP{
"host1": {{1, 2, 3, 4}},
"host2": {{2, 3, 4, 5}},
}
expectedWarnings := []string{"warning1", "warning2"}
expectedErr := errors.New("dummy")
const (
maxFailRatio = 0.1
maxDuration = 20 * time.Second
betweenDuration = time.Second
maxNoNew = 2
maxFails = 2
)
expectedSettings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration,
BetweenDuration: betweenDuration,
MaxNoNew: maxNoNew,
MaxFails: maxFails,
},
}
presolver.EXPECT().Resolve(ctx, hosts, expectedSettings).
Return(expectedHostToIPs, expectedWarnings, expectedErr)
hostToIPs, warnings, err := resolveHosts(ctx, presolver, hosts, minServers)
assert.Equal(t, expectedHostToIPs, hostToIPs)
assert.Equal(t, expectedWarnings, warnings)
assert.Equal(t, expectedErr, err)
}

View File

@@ -0,0 +1,92 @@
// Package ipvanish contains code to obtain the server information
// for the Surshark provider.
package ipvanish
import (
"context"
"errors"
"fmt"
"strings"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/updater/openvpn"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/unzip"
)
var ErrNotEnoughServers = errors.New("not enough servers found")
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
presolver resolver.Parallel, minServers int) (
servers []models.IpvanishServer, warnings []string, err error) {
const url = "https://www.ipvanish.com/software/configs/configs.zip"
contents, err := unzipper.FetchAndExtract(ctx, url)
if err != nil {
return nil, nil, err
} else if len(contents) < minServers {
return nil, nil, fmt.Errorf("%w: %d and expected at least %d",
ErrNotEnoughServers, len(contents), minServers)
}
hts := make(hostToServer)
for fileName, content := range contents {
if !strings.HasSuffix(fileName, ".ovpn") {
continue // not an OpenVPN file
}
tcp, udp, err := openvpn.ExtractProto(content)
if err != nil {
// treat error as warning and go to next file
warning := err.Error() + ": in " + fileName
warnings = append(warnings, warning)
continue
}
hostname, warning, err := openvpn.ExtractHost(content)
if warning != "" {
warnings = append(warnings, warning)
}
if err != nil {
// treat error as warning and go to next file
warning := err.Error() + " in " + fileName
warnings = append(warnings, warning)
continue
}
country, city, err := parseFilename(fileName, hostname)
if err != nil {
// treat error as warning and go to next file
warning := err.Error() + " in " + fileName
warnings = append(warnings, warning)
continue
}
hts.add(hostname, country, city, tcp, udp)
}
if len(hts) < minServers {
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
ErrNotEnoughServers, len(hts), minServers)
}
hosts := hts.toHostsSlice()
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
warnings = append(warnings, newWarnings...)
if err != nil {
return nil, warnings, err
}
hts.adaptWithIPs(hostToIPs)
servers = hts.toServersSlice()
if len(servers) < minServers {
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
ErrNotEnoughServers, len(servers), minServers)
}
sortServers(servers)
return servers, warnings, nil
}

View File

@@ -0,0 +1,150 @@
package ipvanish
import (
"context"
"errors"
"net"
"testing"
"github.com/golang/mock/gomock"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver"
"github.com/qdm12/gluetun/internal/updater/unzip/mock_unzip"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_GetServers(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
// Inputs
minServers int
// Unzip
unzipContents map[string][]byte
unzipErr error
// Resolution
expectResolve bool
hostsToResolve []string
resolveSettings resolver.ParallelSettings
hostToIPs map[string][]net.IP
resolveWarnings []string
resolveErr error
// Output
servers []models.IpvanishServer
warnings []string
err error
}{
"unzipper error": {
unzipErr: errors.New("dummy"),
err: errors.New("dummy"),
},
"not enough unzip contents": {
minServers: 1,
unzipContents: map[string][]byte{},
err: errors.New("not enough servers found: 0 and expected at least 1"),
},
"no openvpn file": {
minServers: 1,
unzipContents: map[string][]byte{"somefile.txt": {}},
err: errors.New("not enough servers found: 0 and expected at least 1"),
},
"invalid proto": {
minServers: 1,
unzipContents: map[string][]byte{"badproto.ovpn": []byte(`proto invalid`)},
warnings: []string{"unknown protocol: invalid: in badproto.ovpn"},
err: errors.New("not enough servers found: 0 and expected at least 1"),
},
"no host": {
minServers: 1,
unzipContents: map[string][]byte{"nohost.ovpn": []byte(``)},
warnings: []string{"remote host not found in nohost.ovpn"},
err: errors.New("not enough servers found: 0 and expected at least 1"),
},
"multiple hosts": {
minServers: 1,
unzipContents: map[string][]byte{
"ipvanish-CA-City-A-hosta.ovpn": []byte("remote hosta\nremote hostb"),
},
expectResolve: true,
hostsToResolve: []string{"hosta"},
resolveSettings: getResolveSettings(1),
warnings: []string{"only using the first host \"hosta\" and discarding 1 other hosts"},
err: errors.New("not enough servers found: 0 and expected at least 1"),
},
"resolve error": {
unzipContents: map[string][]byte{
"ipvanish-CA-City-A-hosta.ovpn": []byte("remote hosta"),
},
expectResolve: true,
hostsToResolve: []string{"hosta"},
resolveSettings: getResolveSettings(0),
resolveWarnings: []string{"resolve warning"},
resolveErr: errors.New("dummy"),
warnings: []string{"resolve warning"},
err: errors.New("dummy"),
},
"filename parsing error": {
minServers: 1,
unzipContents: map[string][]byte{
"ipvanish-unknown-City-A-hosta.ovpn": []byte("remote hosta"),
},
warnings: []string{"country code is unknown: unknown in ipvanish-unknown-City-A-hosta.ovpn"},
err: errors.New("not enough servers found: 0 and expected at least 1"),
},
"success": {
minServers: 1,
unzipContents: map[string][]byte{
"ipvanish-CA-City-A-hosta.ovpn": []byte("remote hosta"),
"ipvanish-LU-City-B-hostb.ovpn": []byte("remote hostb"),
},
expectResolve: true,
hostsToResolve: []string{"hosta", "hostb"},
resolveSettings: getResolveSettings(1),
hostToIPs: map[string][]net.IP{
"hosta": {{1, 1, 1, 1}, {2, 2, 2, 2}},
"hostb": {{3, 3, 3, 3}, {4, 4, 4, 4}},
},
resolveWarnings: []string{"resolve warning"},
servers: []models.IpvanishServer{
{Country: "Canada", City: "City A", Hostname: "hosta", UDP: true, IPs: []net.IP{{1, 1, 1, 1}, {2, 2, 2, 2}}},
{Country: "Luxembourg", City: "City B", Hostname: "hostb", UDP: true, IPs: []net.IP{{3, 3, 3, 3}, {4, 4, 4, 4}}},
},
warnings: []string{"resolve warning"},
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
ctx := context.Background()
unzipper := mock_unzip.NewMockUnzipper(ctrl)
const zipURL = "https://www.ipvanish.com/software/configs/configs.zip"
unzipper.EXPECT().FetchAndExtract(ctx, zipURL).
Return(testCase.unzipContents, testCase.unzipErr)
presolver := mock_resolver.NewMockParallel(ctrl)
if testCase.expectResolve {
presolver.EXPECT().Resolve(ctx, testCase.hostsToResolve, testCase.resolveSettings).
Return(testCase.hostToIPs, testCase.resolveWarnings, testCase.resolveErr)
}
servers, warnings, err := GetServers(ctx, unzipper, presolver, testCase.minServers)
assert.Equal(t, testCase.servers, servers)
assert.Equal(t, testCase.warnings, warnings)
if testCase.err != nil {
require.Error(t, err)
assert.Equal(t, testCase.err.Error(), err.Error())
} else {
assert.NoError(t, err)
}
})
}
}

View File

@@ -0,0 +1,19 @@
package ipvanish
import (
"sort"
"github.com/qdm12/gluetun/internal/models"
)
func sortServers(servers []models.IpvanishServer) {
sort.Slice(servers, func(i, j int) bool {
if servers[i].Country == servers[j].Country {
if servers[i].City == servers[j].City {
return servers[i].Hostname < servers[j].Hostname
}
return servers[i].City < servers[j].City
}
return servers[i].Country < servers[j].Country
})
}

View File

@@ -0,0 +1,40 @@
package ipvanish
import (
"testing"
"github.com/qdm12/gluetun/internal/models"
"github.com/stretchr/testify/assert"
)
func Test_sortServers(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
initialServers []models.IpvanishServer
sortedServers []models.IpvanishServer
}{
"no server": {},
"sorted servers": {
initialServers: []models.IpvanishServer{
{Country: "B", City: "A", Hostname: "A"},
{Country: "A", City: "A", Hostname: "B"},
{Country: "A", City: "A", Hostname: "A"},
{Country: "A", City: "B", Hostname: "A"},
},
sortedServers: []models.IpvanishServer{
{Country: "A", City: "A", Hostname: "A"},
{Country: "A", City: "A", Hostname: "B"},
{Country: "A", City: "B", Hostname: "A"},
{Country: "B", City: "A", Hostname: "A"},
},
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
sortServers(testCase.initialServers)
assert.Equal(t, testCase.sortedServers, testCase.initialServers)
})
}
}

View File

@@ -0,0 +1,14 @@
package ipvanish
import "github.com/qdm12/gluetun/internal/models"
func Stringify(servers []models.IpvanishServer) (s string) {
s = "func IpvanishServers() []models.IpvanishServer {\n"
s += " return []models.IpvanishServer{\n"
for _, server := range servers {
s += " " + server.String() + ",\n"
}
s += " }\n"
s += "}"
return s
}

View File

@@ -0,0 +1,43 @@
package ipvanish
import (
"testing"
"github.com/qdm12/gluetun/internal/models"
"github.com/stretchr/testify/assert"
)
func Test_Stringify(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
servers []models.IpvanishServer
s string
}{
"no server": {
s: `func IpvanishServers() []models.IpvanishServer {
return []models.IpvanishServer{
}
}`,
},
"multiple servers": {
servers: []models.IpvanishServer{
{Country: "A"},
{Country: "B"},
},
s: `func IpvanishServers() []models.IpvanishServer {
return []models.IpvanishServer{
{Country: "A", City: "", Hostname: "", TCP: false, UDP: false, IPs: []net.IP{}},
{Country: "B", City: "", Hostname: "", TCP: false, UDP: false, IPs: []net.IP{}},
}
}`,
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
s := Stringify(testCase.servers)
assert.Equal(t, testCase.s, s)
})
}
}

View File

@@ -19,7 +19,7 @@ func parseServerName(serverName string) (number uint16, err error) {
}
idString := serverName[i+1:]
idUint64, err := strconv.ParseUint(idString, 10, 16)
idUint64, err := strconv.ParseUint(idString, 10, 16) //nolint:gomnd
if err != nil {
return 0, fmt.Errorf("%w: %s", ErrInvalidIDInServerName, serverName)
}

View File

@@ -0,0 +1,160 @@
package vpnunlimited
import (
"strings"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
)
func getHostToServer() (hts hostToServer, warnings []string) {
shortHTS := map[string]models.VPNUnlimitedServer{
"ae": {},
"ar": {},
"at": {},
"au-syd": {
City: "Sydney",
},
"ba": {},
"be": {},
"bg": {},
"br": {},
"by": {},
"ca-tr": {
City: "Toronto",
},
"ca-vn": {
City: "Vancouver",
},
"ca": {},
"ch": {},
"cr": {},
"cy": {},
"cz": {},
"de-dus": {
City: "Düsseldorf",
},
"de": {},
"dk": {},
"ee": {},
"es": {},
"fi": {},
"fr-rbx": {
City: "Roubaix",
},
"fr": {},
"gr": {},
"hr": {},
"hu": {},
"ie-dub": {
City: "Dublin",
},
"il": {},
"im": {},
"in-ka": {
City: "Karnataka",
},
"in": {},
"is": {},
"it-mil": {
City: "Milan",
},
"jp": {},
"kr": {},
"lt": {},
"lu": {},
"lv": {},
"ly": {},
"md": {},
"mx": {},
"mys": {},
"nl": {},
"no": {},
"nz": {},
"om": {},
"pl": {},
"pt": {},
"ro": {},
"rs": {},
"se": {},
"sg-free": {
Free: true,
},
"sg": {},
"si": {},
"sk": {},
"th": {},
"tr": {},
"uk-cv": {
City: "London",
},
"uk-lon": {
City: "London",
},
"uk": {},
"us-chi": {
City: "Chicago",
},
"us-dal": {
City: "Dallas",
},
"us-den": {
City: "Denver",
},
"us-hou": {
City: "Houston",
},
"us-la": {
City: "Los Angeles",
},
"us-lv": {
City: "Las Vegas",
},
"us-mia": {
City: "Miami",
},
"us-ny-free": {
City: "New York",
Free: true,
},
"us-ny": {
City: "New York",
},
"us-sea": {
City: "Seattle",
},
"us-sf": {
City: "San Francisco",
},
"us-sl": {
City: "Saint Louis",
},
"us-slc": {
City: "Salt Lake City",
},
"us-stream": {
Stream: true,
},
"us": {},
"vn": {},
"za": {},
}
hts = make(hostToServer, len(shortHTS))
countryCodesMap := constants.CountryCodes()
for shortHost, server := range shortHTS {
server.UDP = true
server.Hostname = shortHost + ".vpnunlimitedapp.com"
countryCode := strings.Split(shortHost, "-")[0]
country, ok := countryCodesMap[countryCode]
if !ok {
warnings = append(warnings, "country code not found: "+countryCode)
continue
}
server.Country = country
hts[server.Hostname] = server
}
return hts, warnings
}

View File

@@ -0,0 +1,38 @@
package vpnunlimited
import (
"net"
"github.com/qdm12/gluetun/internal/models"
)
type hostToServer map[string]models.VPNUnlimitedServer
func (hts hostToServer) toHostsSlice() (hosts []string) {
hosts = make([]string, 0, len(hts))
for host := range hts {
hosts = append(hosts, host)
}
return hosts
}
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
for host, IPs := range hostToIPs {
server := hts[host]
server.IPs = IPs
hts[host] = server
}
for host, server := range hts {
if len(server.IPs) == 0 {
delete(hts, host)
}
}
}
func (hts hostToServer) toServersSlice() (servers []models.VPNUnlimitedServer) {
servers = make([]models.VPNUnlimitedServer, 0, len(hts))
for _, server := range hts {
servers = append(servers, server)
}
return servers
}

View File

@@ -0,0 +1,32 @@
package vpnunlimited
import (
"context"
"net"
"time"
"github.com/qdm12/gluetun/internal/updater/resolver"
)
func resolveHosts(ctx context.Context, presolver resolver.Parallel,
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
warnings []string, err error) {
const (
maxFailRatio = 0.1
maxDuration = 20 * time.Second
betweenDuration = time.Second
maxNoNew = 2
maxFails = 2
)
settings := resolver.ParallelSettings{
MaxFailRatio: maxFailRatio,
MinFound: minServers,
Repeat: resolver.RepeatSettings{
MaxDuration: maxDuration,
BetweenDuration: betweenDuration,
MaxNoNew: maxNoNew,
MaxFails: maxFails,
},
}
return presolver.Resolve(ctx, hosts, settings)
}

View File

@@ -0,0 +1,42 @@
// Package vpnunlimited contains code to obtain the server information
// for the VPNUnlimited provider.
package vpnunlimited
import (
"context"
"errors"
"fmt"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/unzip"
)
var ErrNotEnoughServers = errors.New("not enough servers found")
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
presolver resolver.Parallel, minServers int) (
servers []models.VPNUnlimitedServer, warnings []string, err error) {
// Hardcoded data from a user provided ZIP file since it's behind a login wall
hts, warnings := getHostToServer()
hosts := hts.toHostsSlice()
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
warnings = append(warnings, newWarnings...)
if err != nil {
return nil, warnings, err
}
hts.adaptWithIPs(hostToIPs)
servers = hts.toServersSlice()
if len(servers) < minServers {
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
ErrNotEnoughServers, len(servers), minServers)
}
sortServers(servers)
return servers, warnings, nil
}

View File

@@ -0,0 +1,19 @@
package vpnunlimited
import (
"sort"
"github.com/qdm12/gluetun/internal/models"
)
func sortServers(servers []models.VPNUnlimitedServer) {
sort.Slice(servers, func(i, j int) bool {
if servers[i].Country == servers[j].Country {
if servers[i].City == servers[j].City {
return servers[i].Hostname < servers[j].Hostname
}
return servers[i].City < servers[j].City
}
return servers[i].Country < servers[j].Country
})
}

View File

@@ -0,0 +1,14 @@
package vpnunlimited
import "github.com/qdm12/gluetun/internal/models"
func Stringify(servers []models.VPNUnlimitedServer) (s string) {
s = "func VPNUnlimitedServers() []models.VPNUnlimitedServer {\n"
s += " return []models.VPNUnlimitedServer{\n"
for _, server := range servers {
s += " " + server.String() + ",\n"
}
s += " }\n"
s += "}"
return s
}

View File

@@ -8,6 +8,7 @@ import (
"time"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/updater/resolver"
"github.com/qdm12/gluetun/internal/updater/unzip"
@@ -84,6 +85,16 @@ func (u *updater) UpdateServers(ctx context.Context) (allServers models.AllServe
}
}
if u.options.Ipvanish {
u.logger.Info("updating Ipvanish servers...")
if err := u.updateIpvanish(ctx); err != nil {
u.logger.Error(err)
}
if err := ctx.Err(); err != nil {
return allServers, err
}
}
if u.options.Ivpn {
u.logger.Info("updating Ivpn servers...")
if err := u.updateIvpn(ctx); err != nil {
@@ -186,6 +197,16 @@ func (u *updater) UpdateServers(ctx context.Context) (allServers models.AllServe
}
}
if u.options.VPNUnlimited {
u.logger.Info("updating " + constants.VPNUnlimited + " servers...")
if err := u.updateVPNUnlimited(ctx); err != nil {
if ctxErr := ctx.Err(); ctxErr != nil {
return allServers, ctxErr
}
u.logger.Error(err)
}
}
if u.options.Vyprvpn {
u.logger.Info("updating Vyprvpn servers...")
if err := u.updateVyprvpn(ctx); err != nil {

Some files were not shown because too many files have changed in this diff Show More