Feat: Wireguard support for Ivpn (#584)
This commit is contained in:
@@ -58,7 +58,7 @@ using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and an HTTP proxy*
|
|||||||
- Based on Alpine 3.14 for a small Docker image of 31MB
|
- Based on Alpine 3.14 for a small Docker image of 31MB
|
||||||
- Supports: **Cyberghost**, **FastestVPN**, **HideMyAss**, **IPVanish**, **IVPN**, **Mullvad**, **NordVPN**, **Privado**, **Private Internet Access**, **PrivateVPN**, **ProtonVPN**, **PureVPN**, **Surfshark**, **TorGuard**, **VPNUnlimited**, **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
|
- Supports OpenVPN
|
||||||
- Supports Wireguard for **Mullvad** and **Windscribe** (more in progress, see #134)
|
- Supports Wireguard for **Mullvad**, **Ivpn** and **Windscribe** (more in progress, see #134)
|
||||||
- DNS over TLS baked in with service provider(s) of your choice
|
- DNS over TLS baked in with service provider(s) of your choice
|
||||||
- DNS fine blocking of malicious/ads/surveillance hostnames and IP addresses, with live update every 24 hours
|
- DNS fine blocking of malicious/ads/surveillance hostnames and IP addresses, with live update every 24 hours
|
||||||
- Choose the vpn network protocol, `udp` or `tcp`
|
- Choose the vpn network protocol, `udp` or `tcp`
|
||||||
|
|||||||
@@ -35,7 +35,12 @@ func (settings *Provider) readIvpn(r reader) (err error) {
|
|||||||
return fmt.Errorf("environment variable SERVER_HOSTNAME: %w", err)
|
return fmt.Errorf("environment variable SERVER_HOSTNAME: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return settings.ServerSelection.OpenVPN.readIVPN(r.env)
|
err = settings.ServerSelection.OpenVPN.readIVPN(r.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings.ServerSelection.Wireguard.readIVPN(r.env)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (settings *OpenVPNSelection) readIVPN(env params.Interface) (err error) {
|
func (settings *OpenVPNSelection) readIVPN(env params.Interface) (err error) {
|
||||||
@@ -52,3 +57,13 @@ func (settings *OpenVPNSelection) readIVPN(env params.Interface) (err error) {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (settings *WireguardSelection) readIVPN(env params.Interface) (err error) {
|
||||||
|
settings.CustomPort, err = readWireguardCustomPort(env,
|
||||||
|
[]uint16{2049, 2050, 53, 30587, 41893, 48574, 58237})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Provider_readIvpn(t *testing.T) {
|
func Test_Provider_readIvpn(t *testing.T) { //nolint:gocognit
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var errDummy = errors.New("dummy test error")
|
var errDummy = errors.New("dummy test error")
|
||||||
@@ -23,10 +23,13 @@ func Test_Provider_readIvpn(t *testing.T) {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
type singleUint16Call struct {
|
type portCall struct {
|
||||||
call bool
|
getCall bool
|
||||||
value uint16
|
getValue string // "" or "0"
|
||||||
err error
|
getErr error
|
||||||
|
portCall bool
|
||||||
|
portValue uint16
|
||||||
|
portErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
type sliceStringCall struct {
|
type sliceStringCall struct {
|
||||||
@@ -42,8 +45,8 @@ func Test_Provider_readIvpn(t *testing.T) {
|
|||||||
isps sliceStringCall
|
isps sliceStringCall
|
||||||
hostnames sliceStringCall
|
hostnames sliceStringCall
|
||||||
protocol singleStringCall
|
protocol singleStringCall
|
||||||
portGet singleStringCall
|
ovpnPort portCall
|
||||||
portPort singleUint16Call
|
wgPort portCall
|
||||||
settings Provider
|
settings Provider
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
@@ -92,7 +95,7 @@ func Test_Provider_readIvpn(t *testing.T) {
|
|||||||
},
|
},
|
||||||
err: errors.New("environment variable SERVER_HOSTNAME: dummy test error"),
|
err: errors.New("environment variable SERVER_HOSTNAME: dummy test error"),
|
||||||
},
|
},
|
||||||
"protocol error": {
|
"openvpn protocol error": {
|
||||||
targetIP: singleStringCall{call: true},
|
targetIP: singleStringCall{call: true},
|
||||||
countries: sliceStringCall{call: true},
|
countries: sliceStringCall{call: true},
|
||||||
cities: sliceStringCall{call: true},
|
cities: sliceStringCall{call: true},
|
||||||
@@ -104,19 +107,33 @@ func Test_Provider_readIvpn(t *testing.T) {
|
|||||||
},
|
},
|
||||||
err: errors.New("environment variable PROTOCOL: dummy test error"),
|
err: errors.New("environment variable PROTOCOL: dummy test error"),
|
||||||
},
|
},
|
||||||
"custom port error": {
|
"openvpn custom port error": {
|
||||||
targetIP: singleStringCall{call: true},
|
targetIP: singleStringCall{call: true},
|
||||||
countries: sliceStringCall{call: true},
|
countries: sliceStringCall{call: true},
|
||||||
cities: sliceStringCall{call: true},
|
cities: sliceStringCall{call: true},
|
||||||
isps: sliceStringCall{call: true},
|
isps: sliceStringCall{call: true},
|
||||||
hostnames: sliceStringCall{call: true},
|
hostnames: sliceStringCall{call: true},
|
||||||
protocol: singleStringCall{call: true},
|
protocol: singleStringCall{call: true},
|
||||||
portGet: singleStringCall{call: true, err: errDummy},
|
ovpnPort: portCall{getCall: true, getErr: errDummy},
|
||||||
settings: Provider{
|
settings: Provider{
|
||||||
Name: constants.Ivpn,
|
Name: constants.Ivpn,
|
||||||
},
|
},
|
||||||
err: errors.New("environment variable PORT: dummy test error"),
|
err: errors.New("environment variable PORT: dummy test error"),
|
||||||
},
|
},
|
||||||
|
"wireguard custom port error": {
|
||||||
|
targetIP: singleStringCall{call: true},
|
||||||
|
countries: sliceStringCall{call: true},
|
||||||
|
cities: sliceStringCall{call: true},
|
||||||
|
isps: sliceStringCall{call: true},
|
||||||
|
hostnames: sliceStringCall{call: true},
|
||||||
|
protocol: singleStringCall{call: true},
|
||||||
|
ovpnPort: portCall{getCall: true, getValue: "0"},
|
||||||
|
wgPort: portCall{getCall: true, getErr: errDummy},
|
||||||
|
settings: Provider{
|
||||||
|
Name: constants.Ivpn,
|
||||||
|
},
|
||||||
|
err: errors.New("environment variable WIREGUARD_PORT: dummy test error"),
|
||||||
|
},
|
||||||
"default settings": {
|
"default settings": {
|
||||||
targetIP: singleStringCall{call: true},
|
targetIP: singleStringCall{call: true},
|
||||||
countries: sliceStringCall{call: true},
|
countries: sliceStringCall{call: true},
|
||||||
@@ -124,7 +141,8 @@ func Test_Provider_readIvpn(t *testing.T) {
|
|||||||
isps: sliceStringCall{call: true},
|
isps: sliceStringCall{call: true},
|
||||||
hostnames: sliceStringCall{call: true},
|
hostnames: sliceStringCall{call: true},
|
||||||
protocol: singleStringCall{call: true},
|
protocol: singleStringCall{call: true},
|
||||||
portGet: singleStringCall{call: true, value: "0"},
|
ovpnPort: portCall{getCall: true, getValue: "0"},
|
||||||
|
wgPort: portCall{getCall: true, getValue: "0"},
|
||||||
settings: Provider{
|
settings: Provider{
|
||||||
Name: constants.Ivpn,
|
Name: constants.Ivpn,
|
||||||
},
|
},
|
||||||
@@ -136,8 +154,8 @@ func Test_Provider_readIvpn(t *testing.T) {
|
|||||||
isps: sliceStringCall{call: true, values: []string{"ISP 1"}},
|
isps: sliceStringCall{call: true, values: []string{"ISP 1"}},
|
||||||
hostnames: sliceStringCall{call: true, values: []string{"E", "F"}},
|
hostnames: sliceStringCall{call: true, values: []string{"E", "F"}},
|
||||||
protocol: singleStringCall{call: true, value: constants.TCP},
|
protocol: singleStringCall{call: true, value: constants.TCP},
|
||||||
portGet: singleStringCall{call: true},
|
ovpnPort: portCall{getCall: true, portCall: true, portValue: 443},
|
||||||
portPort: singleUint16Call{call: true, value: 443},
|
wgPort: portCall{getCall: true, portCall: true, portValue: 2049},
|
||||||
settings: Provider{
|
settings: Provider{
|
||||||
Name: constants.Ivpn,
|
Name: constants.Ivpn,
|
||||||
ServerSelection: ServerSelection{
|
ServerSelection: ServerSelection{
|
||||||
@@ -145,6 +163,9 @@ func Test_Provider_readIvpn(t *testing.T) {
|
|||||||
TCP: true,
|
TCP: true,
|
||||||
CustomPort: 443,
|
CustomPort: 443,
|
||||||
},
|
},
|
||||||
|
Wireguard: WireguardSelection{
|
||||||
|
CustomPort: 2049,
|
||||||
|
},
|
||||||
TargetIP: net.IPv4(1, 2, 3, 4),
|
TargetIP: net.IPv4(1, 2, 3, 4),
|
||||||
Countries: []string{"A", "B"},
|
Countries: []string{"A", "B"},
|
||||||
Cities: []string{"C", "D"},
|
Cities: []string{"C", "D"},
|
||||||
@@ -161,6 +182,7 @@ func Test_Provider_readIvpn(t *testing.T) {
|
|||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
|
|
||||||
env := mock_params.NewMockInterface(ctrl)
|
env := mock_params.NewMockInterface(ctrl)
|
||||||
|
|
||||||
if testCase.targetIP.call {
|
if testCase.targetIP.call {
|
||||||
env.EXPECT().Get("OPENVPN_TARGET_IP").
|
env.EXPECT().Get("OPENVPN_TARGET_IP").
|
||||||
Return(testCase.targetIP.value, testCase.targetIP.err)
|
Return(testCase.targetIP.value, testCase.targetIP.err)
|
||||||
@@ -185,13 +207,21 @@ func Test_Provider_readIvpn(t *testing.T) {
|
|||||||
env.EXPECT().Inside("PROTOCOL", []string{constants.TCP, constants.UDP}, gomock.Any()).
|
env.EXPECT().Inside("PROTOCOL", []string{constants.TCP, constants.UDP}, gomock.Any()).
|
||||||
Return(testCase.protocol.value, testCase.protocol.err)
|
Return(testCase.protocol.value, testCase.protocol.err)
|
||||||
}
|
}
|
||||||
if testCase.portGet.call {
|
if testCase.ovpnPort.getCall {
|
||||||
env.EXPECT().Get("PORT", gomock.Any()).
|
env.EXPECT().Get("PORT", gomock.Any()).
|
||||||
Return(testCase.portGet.value, testCase.portGet.err)
|
Return(testCase.ovpnPort.getValue, testCase.ovpnPort.getErr)
|
||||||
}
|
}
|
||||||
if testCase.portPort.call {
|
if testCase.ovpnPort.portCall {
|
||||||
env.EXPECT().Port("PORT").
|
env.EXPECT().Port("PORT").
|
||||||
Return(testCase.portPort.value, testCase.portPort.err)
|
Return(testCase.ovpnPort.portValue, testCase.ovpnPort.portErr)
|
||||||
|
}
|
||||||
|
if testCase.wgPort.getCall {
|
||||||
|
env.EXPECT().Get("WIREGUARD_PORT", gomock.Any()).
|
||||||
|
Return(testCase.wgPort.getValue, testCase.wgPort.getErr)
|
||||||
|
}
|
||||||
|
if testCase.wgPort.portCall {
|
||||||
|
env.EXPECT().Port("WIREGUARD_PORT").
|
||||||
|
Return(testCase.wgPort.portValue, testCase.wgPort.portErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
r := reader{env: env}
|
r := reader{env: env}
|
||||||
|
|||||||
@@ -103,7 +103,8 @@ func (settings *Provider) readVPNServiceProvider(r reader, vpnType string) (err
|
|||||||
"privado", "pia", "private internet access", "privatevpn", "protonvpn",
|
"privado", "pia", "private internet access", "privatevpn", "protonvpn",
|
||||||
"purevpn", "surfshark", "torguard", constants.VPNUnlimited, "vyprvpn", "windscribe"}
|
"purevpn", "surfshark", "torguard", constants.VPNUnlimited, "vyprvpn", "windscribe"}
|
||||||
case constants.Wireguard:
|
case constants.Wireguard:
|
||||||
allowedVPNServiceProviders = []string{constants.Mullvad, constants.Windscribe}
|
allowedVPNServiceProviders = []string{constants.Mullvad, constants.Windscribe,
|
||||||
|
constants.Ivpn}
|
||||||
}
|
}
|
||||||
|
|
||||||
vpnsp, err := r.env.Inside("VPNSP", allowedVPNServiceProviders,
|
vpnsp, err := r.env.Inside("VPNSP", allowedVPNServiceProviders,
|
||||||
|
|||||||
@@ -25970,10 +25970,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ivpn": {
|
"ivpn": {
|
||||||
"version": 2,
|
"version": 3,
|
||||||
"timestamp": 1629725441,
|
"timestamp": 1629732504,
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Australia",
|
"country": "Australia",
|
||||||
"city": "Sydney",
|
"city": "Sydney",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -25985,6 +25986,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Austria",
|
"country": "Austria",
|
||||||
"city": "Vienna",
|
"city": "Vienna",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -25996,6 +25998,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Belgium",
|
"country": "Belgium",
|
||||||
"city": "Brussels",
|
"city": "Brussels",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26007,6 +26010,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Brazil",
|
"country": "Brazil",
|
||||||
"city": "Franca",
|
"city": "Franca",
|
||||||
"isp": "Qnax",
|
"isp": "Qnax",
|
||||||
@@ -26018,6 +26022,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Bulgaria",
|
"country": "Bulgaria",
|
||||||
"city": "Sofia",
|
"city": "Sofia",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26029,6 +26034,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Canada",
|
"country": "Canada",
|
||||||
"city": "Montreal",
|
"city": "Montreal",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26040,6 +26046,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "Canada",
|
||||||
|
"city": "Montreal",
|
||||||
|
"isp": "M247",
|
||||||
|
"hostname": "ca1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "rg+GGDmjM4Vxo1hURvKmgm9yonb6qcoKbPCP/DNDBnI=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"37.120.130.58"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Canada",
|
"country": "Canada",
|
||||||
"city": "Toronto",
|
"city": "Toronto",
|
||||||
"isp": "Amanah",
|
"isp": "Amanah",
|
||||||
@@ -26051,6 +26071,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Canada",
|
"country": "Canada",
|
||||||
"city": "Toronto",
|
"city": "Toronto",
|
||||||
"isp": "Amanah",
|
"isp": "Amanah",
|
||||||
@@ -26062,6 +26083,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Czech Republic",
|
"country": "Czech Republic",
|
||||||
"city": "Prague",
|
"city": "Prague",
|
||||||
"isp": "Datapacket",
|
"isp": "Datapacket",
|
||||||
@@ -26073,6 +26095,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Denmark",
|
"country": "Denmark",
|
||||||
"city": "Copenhagen",
|
"city": "Copenhagen",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26084,6 +26107,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Finland",
|
"country": "Finland",
|
||||||
"city": "Helsinki",
|
"city": "Helsinki",
|
||||||
"isp": "Creanova",
|
"isp": "Creanova",
|
||||||
@@ -26095,6 +26119,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "France",
|
"country": "France",
|
||||||
"city": "Paris",
|
"city": "Paris",
|
||||||
"isp": "Datapacket",
|
"isp": "Datapacket",
|
||||||
@@ -26106,6 +26131,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Germany",
|
"country": "Germany",
|
||||||
"city": "Frankfurt",
|
"city": "Frankfurt",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26117,6 +26143,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "Germany",
|
||||||
|
"city": "Frankfurt",
|
||||||
|
"isp": "Datapacket",
|
||||||
|
"hostname": "de1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "mS3/WpXjnMAMmXjSpd4nFzx9HSE3ubv2WyjpyH2REgs=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"185.102.219.26"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Germany",
|
"country": "Germany",
|
||||||
"city": "Frankfurt",
|
"city": "Frankfurt",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26128,6 +26168,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Hong Kong",
|
"country": "Hong Kong",
|
||||||
"city": "Hong Kong",
|
"city": "Hong Kong",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26139,6 +26180,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Hong Kong",
|
"country": "Hong Kong",
|
||||||
"city": "Hong Kong",
|
"city": "Hong Kong",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26150,6 +26192,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Hungary",
|
"country": "Hungary",
|
||||||
"city": "Budapest",
|
"city": "Budapest",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26161,6 +26204,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Iceland",
|
"country": "Iceland",
|
||||||
"city": "Reykjavik",
|
"city": "Reykjavik",
|
||||||
"isp": "Advania",
|
"isp": "Advania",
|
||||||
@@ -26172,6 +26216,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Israel",
|
"country": "Israel",
|
||||||
"city": "Holon, Tel Aviv",
|
"city": "Holon, Tel Aviv",
|
||||||
"isp": "HQServ",
|
"isp": "HQServ",
|
||||||
@@ -26183,6 +26228,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Italy",
|
"country": "Italy",
|
||||||
"city": "Milan",
|
"city": "Milan",
|
||||||
"isp": "SEFlow",
|
"isp": "SEFlow",
|
||||||
@@ -26194,6 +26240,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "Italy",
|
||||||
|
"city": "Milan",
|
||||||
|
"isp": "M247",
|
||||||
|
"hostname": "it1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "Aj6b81yrDk7I913R+fuSW/NAmIl87N73vHgY5/WQY0Q=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"82.102.21.90"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Japan",
|
"country": "Japan",
|
||||||
"city": "Tokyo",
|
"city": "Tokyo",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26205,6 +26265,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Luxembourg",
|
"country": "Luxembourg",
|
||||||
"city": "Luxembourg",
|
"city": "Luxembourg",
|
||||||
"isp": "Evoluso",
|
"isp": "Evoluso",
|
||||||
@@ -26216,6 +26277,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "Netherlands",
|
||||||
|
"city": "Amsterdam",
|
||||||
|
"isp": "Datapacket",
|
||||||
|
"hostname": "nl1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "AsMT2FqpkZbjzWeDch6GwufF5odl259W/hIkGytVfWo=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"185.102.218.104"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Netherlands",
|
"country": "Netherlands",
|
||||||
"city": "Amsterdam",
|
"city": "Amsterdam",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26227,6 +26302,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Netherlands",
|
"country": "Netherlands",
|
||||||
"city": "Amsterdam",
|
"city": "Amsterdam",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26238,6 +26314,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Netherlands",
|
"country": "Netherlands",
|
||||||
"city": "Amsterdam",
|
"city": "Amsterdam",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26249,6 +26326,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Netherlands",
|
"country": "Netherlands",
|
||||||
"city": "Amsterdam",
|
"city": "Amsterdam",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26260,6 +26338,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Netherlands",
|
"country": "Netherlands",
|
||||||
"city": "Amsterdam",
|
"city": "Amsterdam",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26271,6 +26350,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Netherlands",
|
"country": "Netherlands",
|
||||||
"city": "Amsterdam",
|
"city": "Amsterdam",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26282,6 +26362,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Norway",
|
"country": "Norway",
|
||||||
"city": "Oslo",
|
"city": "Oslo",
|
||||||
"isp": "Servethewrld",
|
"isp": "Servethewrld",
|
||||||
@@ -26293,6 +26374,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Poland",
|
"country": "Poland",
|
||||||
"city": "Warsaw",
|
"city": "Warsaw",
|
||||||
"isp": "Datapacket",
|
"isp": "Datapacket",
|
||||||
@@ -26304,6 +26386,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Portugal",
|
"country": "Portugal",
|
||||||
"city": "Lisbon",
|
"city": "Lisbon",
|
||||||
"isp": "Hostwebis",
|
"isp": "Hostwebis",
|
||||||
@@ -26315,6 +26398,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Romania",
|
"country": "Romania",
|
||||||
"city": "Bucharest",
|
"city": "Bucharest",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26326,6 +26410,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Serbia",
|
"country": "Serbia",
|
||||||
"city": "Belgrade",
|
"city": "Belgrade",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26337,6 +26422,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Singapore",
|
"country": "Singapore",
|
||||||
"city": "Singapore",
|
"city": "Singapore",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26348,6 +26434,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "Singapore",
|
||||||
|
"city": "Singapore",
|
||||||
|
"isp": "M247",
|
||||||
|
"hostname": "sg1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "hSg0At4uwuIhmTy5UT4fRbi5AN6JO2ZWTuIvqd4nHCE=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"37.120.151.122"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Slovakia",
|
"country": "Slovakia",
|
||||||
"city": "Bratislava",
|
"city": "Bratislava",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26359,6 +26459,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Spain",
|
"country": "Spain",
|
||||||
"city": "Madrid",
|
"city": "Madrid",
|
||||||
"isp": "Datapacket",
|
"isp": "Datapacket",
|
||||||
@@ -26370,6 +26471,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Sweden",
|
"country": "Sweden",
|
||||||
"city": "Stockholm",
|
"city": "Stockholm",
|
||||||
"isp": "GleSyS",
|
"isp": "GleSyS",
|
||||||
@@ -26381,6 +26483,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "Sweden",
|
||||||
|
"city": "Stockholm",
|
||||||
|
"isp": "M247",
|
||||||
|
"hostname": "se1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "2n0nFE1g/+vQr2AOQPm9Igyiy0zh9uTTultvOOSkMRo=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"37.120.153.226"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Switzerland",
|
"country": "Switzerland",
|
||||||
"city": "Zurich",
|
"city": "Zurich",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26392,6 +26508,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "Switzerland",
|
||||||
|
"city": "Zurich",
|
||||||
|
"isp": "Privatelayer",
|
||||||
|
"hostname": "ch1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "jVZJ61i1xxkAfriDHpwvF/GDuTvZUqhwoWSjkOJvaUA=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"141.255.164.66"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Switzerland",
|
"country": "Switzerland",
|
||||||
"city": "Zurich",
|
"city": "Zurich",
|
||||||
"isp": "Privatelayer",
|
"isp": "Privatelayer",
|
||||||
@@ -26403,6 +26533,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "Ukraine",
|
"country": "Ukraine",
|
||||||
"city": "Kharkiv",
|
"city": "Kharkiv",
|
||||||
"isp": "Xservers",
|
"isp": "Xservers",
|
||||||
@@ -26414,6 +26545,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United Kingdom",
|
"country": "United Kingdom",
|
||||||
"city": "London",
|
"city": "London",
|
||||||
"isp": "Datapacket",
|
"isp": "Datapacket",
|
||||||
@@ -26425,6 +26557,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "United Kingdom",
|
||||||
|
"city": "London",
|
||||||
|
"isp": "M247",
|
||||||
|
"hostname": "gb1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "7+jos+Eg+hMEOQE4Std6OJ+WVnCcmbqS1/EbPwn9w3s=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"81.92.202.114"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United Kingdom",
|
"country": "United Kingdom",
|
||||||
"city": "London",
|
"city": "London",
|
||||||
"isp": "Datapacket",
|
"isp": "Datapacket",
|
||||||
@@ -26436,6 +26582,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United Kingdom",
|
"country": "United Kingdom",
|
||||||
"city": "Manchester",
|
"city": "Manchester",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26447,6 +26594,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Atlanta, GA",
|
"city": "Atlanta, GA",
|
||||||
"isp": "Quadranet",
|
"isp": "Quadranet",
|
||||||
@@ -26458,6 +26606,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "United States",
|
||||||
|
"city": "Atlanta, GA",
|
||||||
|
"isp": "Datapacket",
|
||||||
|
"hostname": "us-ga1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "jD8h+pL5/d6fmYcTzl0lR8AWzQVN5XkwRFSmM/3NcDM=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"185.93.0.212"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Atlanta, GA",
|
"city": "Atlanta, GA",
|
||||||
"isp": "Quadranet",
|
"isp": "Quadranet",
|
||||||
@@ -26469,6 +26631,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Chicago, IL",
|
"city": "Chicago, IL",
|
||||||
"isp": "Quadranet",
|
"isp": "Quadranet",
|
||||||
@@ -26480,6 +26643,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "United States",
|
||||||
|
"city": "Chicago, IL",
|
||||||
|
"isp": "Datapacket",
|
||||||
|
"hostname": "us-il1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "hku9gjamhoii8OvxZgx+TdUDIkOAQYFu39qbav2AyUQ=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"89.187.181.116"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Chicago, IL",
|
"city": "Chicago, IL",
|
||||||
"isp": "Quadranet",
|
"isp": "Quadranet",
|
||||||
@@ -26491,6 +26668,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Dallas, TX",
|
"city": "Dallas, TX",
|
||||||
"isp": "Quadranet",
|
"isp": "Quadranet",
|
||||||
@@ -26502,6 +26680,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "United States",
|
||||||
|
"city": "Dallas, TX",
|
||||||
|
"isp": "Quadranet",
|
||||||
|
"hostname": "us-tx1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "JPT1veXLmasj2uQDstX24mpR7VWD+GmV8JDkidkz91Q=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"198.55.124.114"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Dallas, TX",
|
"city": "Dallas, TX",
|
||||||
"isp": "Quadranet",
|
"isp": "Quadranet",
|
||||||
@@ -26513,6 +26705,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Las Vegas, NV",
|
"city": "Las Vegas, NV",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26524,6 +26717,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Los Angeles, CA",
|
"city": "Los Angeles, CA",
|
||||||
"isp": "Quadranet",
|
"isp": "Quadranet",
|
||||||
@@ -26535,6 +26729,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "United States",
|
||||||
|
"city": "Los Angeles, CA",
|
||||||
|
"isp": "Datapacket",
|
||||||
|
"hostname": "us-ca1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "FGl78s9Ct6xNamQ2/CtAyXwGePrrU0kiZxfM27pm8XA=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"185.180.13.41"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Los Angeles, CA",
|
"city": "Los Angeles, CA",
|
||||||
"isp": "Quadranet",
|
"isp": "Quadranet",
|
||||||
@@ -26546,6 +26754,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Los Angeles, CA",
|
"city": "Los Angeles, CA",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26557,6 +26766,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Los Angeles, CA",
|
"city": "Los Angeles, CA",
|
||||||
"isp": "Quadranet",
|
"isp": "Quadranet",
|
||||||
@@ -26568,6 +26778,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Miami, FL",
|
"city": "Miami, FL",
|
||||||
"isp": "Quadranet",
|
"isp": "Quadranet",
|
||||||
@@ -26579,6 +26790,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "New Jersey, NJ",
|
"city": "New Jersey, NJ",
|
||||||
"isp": "Quadranet",
|
"isp": "Quadranet",
|
||||||
@@ -26590,6 +26802,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "New Jersey, NJ",
|
"city": "New Jersey, NJ",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26601,6 +26814,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "New York, NY",
|
"city": "New York, NY",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26612,6 +26826,20 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "wireguard",
|
||||||
|
"country": "United States",
|
||||||
|
"city": "New York, NY",
|
||||||
|
"isp": "M247",
|
||||||
|
"hostname": "us-ny1.wg.ivpn.net",
|
||||||
|
"wgpubkey": "6/tjvgb7HFl7UuvBSegolxa1zKr3iSlDrlCexCmhAGE=",
|
||||||
|
"tcp": false,
|
||||||
|
"udp": true,
|
||||||
|
"ips": [
|
||||||
|
"91.132.137.170"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "New York, NY",
|
"city": "New York, NY",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26623,6 +26851,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Phoenix, AZ",
|
"city": "Phoenix, AZ",
|
||||||
"isp": "M247",
|
"isp": "M247",
|
||||||
@@ -26634,6 +26863,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Salt Lake City, UT",
|
"city": "Salt Lake City, UT",
|
||||||
"isp": "100TB",
|
"isp": "100TB",
|
||||||
@@ -26645,6 +26875,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Seattle, WA",
|
"city": "Seattle, WA",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -26656,6 +26887,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"vpn": "openvpn",
|
||||||
"country": "United States",
|
"country": "United States",
|
||||||
"city": "Washington, DC",
|
"city": "Washington, DC",
|
||||||
"isp": "Leaseweb",
|
"isp": "Leaseweb",
|
||||||
@@ -118456,4 +118688,4 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ func Test_versions(t *testing.T) {
|
|||||||
"Ivpn": {
|
"Ivpn": {
|
||||||
model: models.IvpnServer{},
|
model: models.IvpnServer{},
|
||||||
version: allServers.Ivpn.Version,
|
version: allServers.Ivpn.Version,
|
||||||
digest: "abdc2848",
|
digest: "88074ceb",
|
||||||
},
|
},
|
||||||
"Mullvad": {
|
"Mullvad": {
|
||||||
model: models.MullvadServer{},
|
model: models.MullvadServer{},
|
||||||
|
|||||||
@@ -39,10 +39,12 @@ type IpvanishServer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type IvpnServer struct {
|
type IvpnServer struct {
|
||||||
|
VPN string `json:"vpn"`
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
City string `json:"city"`
|
City string `json:"city"`
|
||||||
ISP string `json:"isp"`
|
ISP string `json:"isp"`
|
||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
|
WgPubKey string `json:"wgpubkey,omitempty"`
|
||||||
TCP bool `json:"tcp"`
|
TCP bool `json:"tcp"`
|
||||||
UDP bool `json:"udp"`
|
UDP bool `json:"udp"`
|
||||||
IPs []net.IP `json:"ips"`
|
IPs []net.IP `json:"ips"`
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
func (i *Ivpn) GetConnection(selection configuration.ServerSelection) (
|
func (i *Ivpn) GetConnection(selection configuration.ServerSelection) (
|
||||||
connection models.Connection, err error) {
|
connection models.Connection, err error) {
|
||||||
port := getPort(selection)
|
port := getPort(selection)
|
||||||
protocol := getProtocol(selection.OpenVPN.TCP)
|
protocol := getProtocol(selection)
|
||||||
|
|
||||||
servers, err := i.filterServers(selection)
|
servers, err := i.filterServers(selection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -26,6 +26,7 @@ func (i *Ivpn) GetConnection(selection configuration.ServerSelection) (
|
|||||||
Port: port,
|
Port: port,
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
Hostname: server.Hostname,
|
Hostname: server.Hostname,
|
||||||
|
PubKey: server.WgPubKey, // Wireguard only
|
||||||
}
|
}
|
||||||
connections = append(connections, connection)
|
connections = append(connections, connection)
|
||||||
}
|
}
|
||||||
@@ -39,19 +40,29 @@ func (i *Ivpn) GetConnection(selection configuration.ServerSelection) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getPort(selection configuration.ServerSelection) (port uint16) {
|
func getPort(selection configuration.ServerSelection) (port uint16) {
|
||||||
customPort := selection.OpenVPN.CustomPort
|
switch selection.VPN {
|
||||||
if customPort > 0 {
|
case constants.Wireguard:
|
||||||
return customPort
|
customPort := selection.Wireguard.CustomPort
|
||||||
|
if customPort > 0 {
|
||||||
|
return customPort
|
||||||
|
}
|
||||||
|
const defaultPort = 58237
|
||||||
|
return defaultPort
|
||||||
|
default: // OpenVPN
|
||||||
|
customPort := selection.OpenVPN.CustomPort
|
||||||
|
if customPort > 0 {
|
||||||
|
return customPort
|
||||||
|
}
|
||||||
|
port = 1194
|
||||||
|
if selection.OpenVPN.TCP {
|
||||||
|
port = 443
|
||||||
|
}
|
||||||
|
return port
|
||||||
}
|
}
|
||||||
port = 1194
|
|
||||||
if selection.OpenVPN.TCP {
|
|
||||||
port = 443
|
|
||||||
}
|
|
||||||
return port
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getProtocol(tcp bool) (protocol string) {
|
func getProtocol(selection configuration.ServerSelection) (protocol string) {
|
||||||
if tcp {
|
if selection.VPN == constants.OpenVPN && selection.OpenVPN.TCP {
|
||||||
return constants.TCP
|
return constants.TCP
|
||||||
}
|
}
|
||||||
return constants.UDP
|
return constants.UDP
|
||||||
|
|||||||
@@ -130,6 +130,21 @@ func Test_getPort(t *testing.T) {
|
|||||||
},
|
},
|
||||||
port: 1234,
|
port: 1234,
|
||||||
},
|
},
|
||||||
|
"Wireguard": {
|
||||||
|
selection: configuration.ServerSelection{
|
||||||
|
VPN: constants.Wireguard,
|
||||||
|
},
|
||||||
|
port: 58237,
|
||||||
|
},
|
||||||
|
"Wireguard custom port": {
|
||||||
|
selection: configuration.ServerSelection{
|
||||||
|
VPN: constants.Wireguard,
|
||||||
|
Wireguard: configuration.WireguardSelection{
|
||||||
|
CustomPort: 1234,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
port: 1234,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, testCase := range testCases {
|
for name, testCase := range testCases {
|
||||||
@@ -148,16 +163,27 @@ func Test_getProtocol(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
tcp bool
|
selection configuration.ServerSelection
|
||||||
protocol string
|
protocol string
|
||||||
}{
|
}{
|
||||||
"UDP": {
|
"OpenVPN UDP": {
|
||||||
protocol: constants.UDP,
|
protocol: constants.UDP,
|
||||||
},
|
},
|
||||||
"TCP": {
|
"OpenVPN TCP": {
|
||||||
tcp: true,
|
selection: configuration.ServerSelection{
|
||||||
|
VPN: constants.OpenVPN,
|
||||||
|
OpenVPN: configuration.OpenVPNSelection{
|
||||||
|
TCP: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
protocol: constants.TCP,
|
protocol: constants.TCP,
|
||||||
},
|
},
|
||||||
|
"Wireguard": {
|
||||||
|
selection: configuration.ServerSelection{
|
||||||
|
VPN: constants.Wireguard,
|
||||||
|
},
|
||||||
|
protocol: constants.UDP,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, testCase := range testCases {
|
for name, testCase := range testCases {
|
||||||
@@ -165,7 +191,7 @@ func Test_getProtocol(t *testing.T) {
|
|||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
protocol := getProtocol(testCase.tcp)
|
protocol := getProtocol(testCase.selection)
|
||||||
|
|
||||||
assert.Equal(t, testCase.protocol, protocol)
|
assert.Equal(t, testCase.protocol, protocol)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ func (i *Ivpn) filterServers(selection configuration.ServerSelection) (
|
|||||||
for _, server := range i.servers {
|
for _, server := range i.servers {
|
||||||
switch {
|
switch {
|
||||||
case
|
case
|
||||||
|
server.VPN != selection.VPN,
|
||||||
utils.FilterByPossibilities(server.ISP, selection.ISPs),
|
utils.FilterByPossibilities(server.ISP, selection.ISPs),
|
||||||
utils.FilterByPossibilities(server.Country, selection.Countries),
|
utils.FilterByPossibilities(server.Country, selection.Countries),
|
||||||
utils.FilterByPossibilities(server.City, selection.Cities),
|
utils.FilterByPossibilities(server.City, selection.Cities),
|
||||||
|
|||||||
@@ -26,10 +26,12 @@ type apiServer struct {
|
|||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
City string `json:"city"`
|
City string `json:"city"`
|
||||||
ISP string `json:"isp"`
|
ISP string `json:"isp"`
|
||||||
|
WgPubKey string `json:"wg_public_key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type apiHostnames struct {
|
type apiHostnames struct {
|
||||||
OpenVPN string `json:"openvpn"`
|
OpenVPN string `json:"openvpn"`
|
||||||
|
Wireguard string `json:"wireguard"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchAPI(ctx context.Context, client *http.Client) (
|
func fetchAPI(ctx context.Context, client *http.Client) (
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
)
|
)
|
||||||
@@ -28,13 +29,15 @@ func GetServers(ctx context.Context, client *http.Client,
|
|||||||
hosts := make([]string, 0, len(data.Servers))
|
hosts := make([]string, 0, len(data.Servers))
|
||||||
|
|
||||||
for _, serverData := range data.Servers {
|
for _, serverData := range data.Servers {
|
||||||
host := serverData.Hostnames.OpenVPN
|
openVPNHost := serverData.Hostnames.OpenVPN
|
||||||
|
if openVPNHost != "" {
|
||||||
if host == "" {
|
hosts = append(hosts, openVPNHost)
|
||||||
continue // Wireguard
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts = append(hosts, host)
|
wireguardHost := serverData.Hostnames.Wireguard
|
||||||
|
if wireguardHost != "" {
|
||||||
|
hosts = append(hosts, wireguardHost)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(hosts) < minServers {
|
if len(hosts) < minServers {
|
||||||
@@ -49,19 +52,27 @@ func GetServers(ctx context.Context, client *http.Client,
|
|||||||
|
|
||||||
servers = make([]models.IvpnServer, 0, len(hosts))
|
servers = make([]models.IvpnServer, 0, len(hosts))
|
||||||
for _, serverData := range data.Servers {
|
for _, serverData := range data.Servers {
|
||||||
host := serverData.Hostnames.OpenVPN
|
vpnType := constants.OpenVPN
|
||||||
if serverData.Hostnames.OpenVPN == "" {
|
hostname := serverData.Hostnames.OpenVPN
|
||||||
continue // Wireguard
|
tcp := true
|
||||||
|
wgPubKey := ""
|
||||||
|
if hostname == "" {
|
||||||
|
vpnType = constants.Wireguard
|
||||||
|
hostname = serverData.Hostnames.Wireguard
|
||||||
|
tcp = false
|
||||||
|
wgPubKey = serverData.WgPubKey
|
||||||
}
|
}
|
||||||
|
|
||||||
server := models.IvpnServer{
|
server := models.IvpnServer{
|
||||||
|
VPN: vpnType,
|
||||||
Country: serverData.Country,
|
Country: serverData.Country,
|
||||||
City: serverData.City,
|
City: serverData.City,
|
||||||
ISP: serverData.ISP,
|
ISP: serverData.ISP,
|
||||||
Hostname: serverData.Hostnames.OpenVPN,
|
Hostname: hostname,
|
||||||
TCP: true,
|
WgPubKey: wgPubKey,
|
||||||
|
TCP: tcp,
|
||||||
UDP: true,
|
UDP: true,
|
||||||
IPs: hostToIPs[host],
|
IPs: hostToIPs[hostname],
|
||||||
}
|
}
|
||||||
servers = append(servers, server)
|
servers = append(servers, server)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver"
|
"github.com/qdm12/gluetun/internal/updater/resolver/mock_resolver"
|
||||||
@@ -70,23 +71,31 @@ func Test_GetServers(t *testing.T) {
|
|||||||
minServers: 1,
|
minServers: 1,
|
||||||
responseBody: `{"servers":[
|
responseBody: `{"servers":[
|
||||||
{"country":"Country1","city":"City A","hostnames":{"openvpn":"hosta"}},
|
{"country":"Country1","city":"City A","hostnames":{"openvpn":"hosta"}},
|
||||||
{"country":"Country2","city":"City B","hostnames":{"openvpn":"hostb"}},
|
{"country":"Country2","city":"City B","hostnames":{"openvpn":"hostb"},"wg_public_key":"xyz"},
|
||||||
{"country":"Country3","city":"City C","hostnames":{"wireguard":"hostc"}}
|
{"country":"Country3","city":"City C","hostnames":{"wireguard":"hostc"},"wg_public_key":"xyz"}
|
||||||
]}`,
|
]}`,
|
||||||
responseStatus: http.StatusOK,
|
responseStatus: http.StatusOK,
|
||||||
expectResolve: true,
|
expectResolve: true,
|
||||||
hostsToResolve: []string{"hosta", "hostb"},
|
hostsToResolve: []string{"hosta", "hostb", "hostc"},
|
||||||
resolveSettings: getResolveSettings(1),
|
resolveSettings: getResolveSettings(1),
|
||||||
hostToIPs: map[string][]net.IP{
|
hostToIPs: map[string][]net.IP{
|
||||||
"hosta": {{1, 1, 1, 1}, {2, 2, 2, 2}},
|
"hosta": {{1, 1, 1, 1}, {2, 2, 2, 2}},
|
||||||
"hostb": {{3, 3, 3, 3}, {4, 4, 4, 4}},
|
"hostb": {{3, 3, 3, 3}, {4, 4, 4, 4}},
|
||||||
|
"hostc": {{5, 5, 5, 5}, {6, 6, 6, 6}},
|
||||||
},
|
},
|
||||||
resolveWarnings: []string{"resolve warning"},
|
resolveWarnings: []string{"resolve warning"},
|
||||||
servers: []models.IvpnServer{
|
servers: []models.IvpnServer{
|
||||||
{Country: "Country1", City: "City A", Hostname: "hosta",
|
{VPN: constants.OpenVPN, Country: "Country1",
|
||||||
TCP: true, UDP: true, IPs: []net.IP{{1, 1, 1, 1}, {2, 2, 2, 2}}},
|
City: "City A", Hostname: "hosta", TCP: true, UDP: true,
|
||||||
{Country: "Country2", City: "City B", Hostname: "hostb",
|
IPs: []net.IP{{1, 1, 1, 1}, {2, 2, 2, 2}}},
|
||||||
TCP: true, UDP: true, IPs: []net.IP{{3, 3, 3, 3}, {4, 4, 4, 4}}},
|
{VPN: constants.OpenVPN, Country: "Country2",
|
||||||
|
City: "City B", Hostname: "hostb", TCP: true, UDP: true,
|
||||||
|
IPs: []net.IP{{3, 3, 3, 3}, {4, 4, 4, 4}}},
|
||||||
|
{VPN: constants.Wireguard,
|
||||||
|
Country: "Country3", City: "City C",
|
||||||
|
Hostname: "hostc", UDP: true,
|
||||||
|
WgPubKey: "xyz",
|
||||||
|
IPs: []net.IP{{5, 5, 5, 5}, {6, 6, 6, 6}}},
|
||||||
},
|
},
|
||||||
warnings: []string{"resolve warning"},
|
warnings: []string{"resolve warning"},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ func sortServers(servers []models.IvpnServer) {
|
|||||||
sort.Slice(servers, func(i, j int) bool {
|
sort.Slice(servers, func(i, j int) bool {
|
||||||
if servers[i].Country == servers[j].Country {
|
if servers[i].Country == servers[j].Country {
|
||||||
if servers[i].City == servers[j].City {
|
if servers[i].City == servers[j].City {
|
||||||
|
if servers[i].Hostname == servers[j].Hostname {
|
||||||
|
return servers[i].VPN < servers[j].VPN
|
||||||
|
}
|
||||||
return servers[i].Hostname < servers[j].Hostname
|
return servers[i].Hostname < servers[j].Hostname
|
||||||
}
|
}
|
||||||
return servers[i].City < servers[j].City
|
return servers[i].City < servers[j].City
|
||||||
|
|||||||
Reference in New Issue
Block a user