Feat: Wireguard support for Ivpn (#584)

This commit is contained in:
Quentin McGaw (desktop)
2021-08-23 16:01:01 +00:00
parent eb6238ee52
commit 06a2d79cb4
14 changed files with 403 additions and 60 deletions

View File

@@ -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`

View File

@@ -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
}

View File

@@ -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}

View File

@@ -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,

View File

@@ -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",

View File

@@ -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{},

View File

@@ -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"`

View File

@@ -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,6 +40,15 @@ func (i *Ivpn) GetConnection(selection configuration.ServerSelection) (
} }
func getPort(selection configuration.ServerSelection) (port uint16) { func getPort(selection configuration.ServerSelection) (port uint16) {
switch selection.VPN {
case constants.Wireguard:
customPort := selection.Wireguard.CustomPort
if customPort > 0 {
return customPort
}
const defaultPort = 58237
return defaultPort
default: // OpenVPN
customPort := selection.OpenVPN.CustomPort customPort := selection.OpenVPN.CustomPort
if customPort > 0 { if customPort > 0 {
return customPort return customPort
@@ -49,9 +59,10 @@ func getPort(selection configuration.ServerSelection) (port uint16) {
} }
return port 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

View File

@@ -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)
}) })

View File

@@ -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),

View File

@@ -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) (

View File

@@ -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)
} }

View File

@@ -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"},
}, },

View File

@@ -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