Feat: IVPN supports TCP and custom port

This commit is contained in:
Quentin McGaw (desktop)
2021-08-23 13:34:00 +00:00
parent c348343b22
commit f41fec57ed
8 changed files with 454 additions and 86 deletions

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/golibs/params"
)
func (settings *Provider) readIvpn(r reader) (err error) {
@@ -34,5 +35,20 @@ func (settings *Provider) readIvpn(r reader) (err error) {
return fmt.Errorf("environment variable SERVER_HOSTNAME: %w", err)
}
return settings.ServerSelection.OpenVPN.readProtocolOnly(r.env)
return settings.ServerSelection.OpenVPN.readIVPN(r.env)
}
func (settings *OpenVPNSelection) readIVPN(env params.Interface) (err error) {
settings.TCP, err = readProtocol(env)
if err != nil {
return err
}
settings.CustomPort, err = readOpenVPNCustomPort(env, settings.TCP,
[]uint16{80, 443, 1443}, []uint16{53, 1194, 2049, 2050})
if err != nil {
return err
}
return nil
}

View File

@@ -23,6 +23,12 @@ func Test_Provider_readIvpn(t *testing.T) {
err error
}
type singleUint16Call struct {
call bool
value uint16
err error
}
type sliceStringCall struct {
call bool
values []string
@@ -30,12 +36,14 @@ func Test_Provider_readIvpn(t *testing.T) {
}
testCases := map[string]struct {
protocol singleStringCall
targetIP singleStringCall
countries sliceStringCall
cities sliceStringCall
isps sliceStringCall
hostnames sliceStringCall
protocol singleStringCall
portGet singleStringCall
portPort singleUint16Call
settings Provider
err error
}{
@@ -96,6 +104,19 @@ func Test_Provider_readIvpn(t *testing.T) {
},
err: errors.New("environment variable PROTOCOL: dummy test error"),
},
"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},
portGet: singleStringCall{call: true, err: errDummy},
settings: Provider{
Name: constants.Ivpn,
},
err: errors.New("environment variable PORT: dummy test error"),
},
"default settings": {
targetIP: singleStringCall{call: true},
countries: sliceStringCall{call: true},
@@ -103,6 +124,7 @@ func Test_Provider_readIvpn(t *testing.T) {
isps: sliceStringCall{call: true},
hostnames: sliceStringCall{call: true},
protocol: singleStringCall{call: true},
portGet: singleStringCall{call: true, value: "0"},
settings: Provider{
Name: constants.Ivpn,
},
@@ -114,11 +136,14 @@ func Test_Provider_readIvpn(t *testing.T) {
isps: sliceStringCall{call: true, values: []string{"ISP 1"}},
hostnames: sliceStringCall{call: true, values: []string{"E", "F"}},
protocol: singleStringCall{call: true, value: constants.TCP},
portGet: singleStringCall{call: true},
portPort: singleUint16Call{call: true, value: 443},
settings: Provider{
Name: constants.Ivpn,
ServerSelection: ServerSelection{
OpenVPN: OpenVPNSelection{
TCP: true,
TCP: true,
CustomPort: 443,
},
TargetIP: net.IPv4(1, 2, 3, 4),
Countries: []string{"A", "B"},
@@ -136,10 +161,6 @@ func Test_Provider_readIvpn(t *testing.T) {
ctrl := gomock.NewController(t)
env := mock_params.NewMockInterface(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)
@@ -160,6 +181,18 @@ func Test_Provider_readIvpn(t *testing.T) {
env.EXPECT().CSVInside("SERVER_HOSTNAME", constants.IvpnHostnameChoices()).
Return(testCase.hostnames.values, testCase.hostnames.err)
}
if testCase.protocol.call {
env.EXPECT().Inside("PROTOCOL", []string{constants.TCP, constants.UDP}, gomock.Any()).
Return(testCase.protocol.value, testCase.protocol.err)
}
if testCase.portGet.call {
env.EXPECT().Get("PORT", gomock.Any()).
Return(testCase.portGet.value, testCase.portGet.err)
}
if testCase.portPort.call {
env.EXPECT().Port("PORT").
Return(testCase.portPort.value, testCase.portPort.err)
}
r := reader{env: env}

View File

@@ -25971,14 +25971,14 @@
},
"ivpn": {
"version": 2,
"timestamp": 1629589118,
"timestamp": 1629725441,
"servers": [
{
"country": "Australia",
"city": "Sydney",
"isp": "M247",
"hostname": "au-nsw1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"46.102.153.242"
@@ -25989,7 +25989,7 @@
"city": "Vienna",
"isp": "M247",
"hostname": "at1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.244.212.66"
@@ -26000,7 +26000,7 @@
"city": "Brussels",
"isp": "M247",
"hostname": "be1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"194.187.251.10"
@@ -26011,7 +26011,7 @@
"city": "Franca",
"isp": "Qnax",
"hostname": "br1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"45.162.229.130"
@@ -26022,7 +26022,7 @@
"city": "Sofia",
"isp": "M247",
"hostname": "bg1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"82.102.23.18"
@@ -26033,7 +26033,7 @@
"city": "Montreal",
"isp": "M247",
"hostname": "ca-qc1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"87.101.92.26"
@@ -26044,7 +26044,7 @@
"city": "Toronto",
"isp": "Amanah",
"hostname": "ca1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"104.254.90.178"
@@ -26055,7 +26055,7 @@
"city": "Toronto",
"isp": "Amanah",
"hostname": "ca2.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"172.86.186.170"
@@ -26066,7 +26066,7 @@
"city": "Prague",
"isp": "Datapacket",
"hostname": "cz1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"195.181.160.167"
@@ -26077,7 +26077,7 @@
"city": "Copenhagen",
"isp": "M247",
"hostname": "dk1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.245.84.226"
@@ -26088,7 +26088,7 @@
"city": "Helsinki",
"isp": "Creanova",
"hostname": "fi1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.112.82.12"
@@ -26099,7 +26099,7 @@
"city": "Paris",
"isp": "Datapacket",
"hostname": "fr1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.246.211.179"
@@ -26110,7 +26110,7 @@
"city": "Frankfurt",
"isp": "Leaseweb",
"hostname": "de1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"178.162.222.40"
@@ -26121,7 +26121,7 @@
"city": "Frankfurt",
"isp": "Leaseweb",
"hostname": "de2.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"178.162.211.114"
@@ -26132,7 +26132,7 @@
"city": "Hong Kong",
"isp": "Leaseweb",
"hostname": "hk1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"209.58.189.163"
@@ -26143,7 +26143,7 @@
"city": "Hong Kong",
"isp": "Leaseweb",
"hostname": "hk2.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"209.58.188.13"
@@ -26154,7 +26154,7 @@
"city": "Budapest",
"isp": "M247",
"hostname": "hu1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.189.114.186"
@@ -26165,7 +26165,7 @@
"city": "Reykjavik",
"isp": "Advania",
"hostname": "is1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"82.221.107.178"
@@ -26176,7 +26176,7 @@
"city": "Holon, Tel Aviv",
"isp": "HQServ",
"hostname": "il1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.191.207.194"
@@ -26187,7 +26187,7 @@
"city": "Milan",
"isp": "SEFlow",
"hostname": "it1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"158.58.172.73"
@@ -26198,7 +26198,7 @@
"city": "Tokyo",
"isp": "M247",
"hostname": "jp1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"91.207.174.234"
@@ -26209,7 +26209,7 @@
"city": "Luxembourg",
"isp": "Evoluso",
"hostname": "lu1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"92.223.89.53"
@@ -26220,7 +26220,7 @@
"city": "Amsterdam",
"isp": "Leaseweb",
"hostname": "nl3.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"95.211.172.68"
@@ -26231,7 +26231,7 @@
"city": "Amsterdam",
"isp": "Leaseweb",
"hostname": "nl4.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"95.211.172.95"
@@ -26242,7 +26242,7 @@
"city": "Amsterdam",
"isp": "Leaseweb",
"hostname": "nl5.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"95.211.187.222"
@@ -26253,7 +26253,7 @@
"city": "Amsterdam",
"isp": "Leaseweb",
"hostname": "nl6.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"95.211.187.228"
@@ -26264,7 +26264,7 @@
"city": "Amsterdam",
"isp": "Leaseweb",
"hostname": "nl7.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"95.211.95.22"
@@ -26275,7 +26275,7 @@
"city": "Amsterdam",
"isp": "Leaseweb",
"hostname": "nl8.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"95.211.172.18"
@@ -26286,7 +26286,7 @@
"city": "Oslo",
"isp": "Servethewrld",
"hostname": "no1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"194.242.10.150"
@@ -26297,7 +26297,7 @@
"city": "Warsaw",
"isp": "Datapacket",
"hostname": "pl1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.246.208.86"
@@ -26308,7 +26308,7 @@
"city": "Lisbon",
"isp": "Hostwebis",
"hostname": "pt1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"94.46.175.112"
@@ -26319,7 +26319,7 @@
"city": "Bucharest",
"isp": "M247",
"hostname": "ro1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"37.120.206.50"
@@ -26330,7 +26330,7 @@
"city": "Belgrade",
"isp": "M247",
"hostname": "rs1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"141.98.103.250"
@@ -26341,7 +26341,7 @@
"city": "Singapore",
"isp": "M247",
"hostname": "sg1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.128.24.186"
@@ -26352,7 +26352,7 @@
"city": "Bratislava",
"isp": "M247",
"hostname": "sk1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.245.85.250"
@@ -26363,7 +26363,7 @@
"city": "Madrid",
"isp": "Datapacket",
"hostname": "es1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.93.3.193"
@@ -26374,7 +26374,7 @@
"city": "Stockholm",
"isp": "GleSyS",
"hostname": "se1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"80.67.10.138"
@@ -26385,7 +26385,7 @@
"city": "Zurich",
"isp": "M247",
"hostname": "ch1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.212.170.138"
@@ -26396,7 +26396,7 @@
"city": "Zurich",
"isp": "Privatelayer",
"hostname": "ch3.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"141.255.166.194"
@@ -26407,7 +26407,7 @@
"city": "Kharkiv",
"isp": "Xservers",
"hostname": "ua1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"193.203.48.54"
@@ -26418,7 +26418,7 @@
"city": "London",
"isp": "Datapacket",
"hostname": "gb1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.59.221.133"
@@ -26429,7 +26429,7 @@
"city": "London",
"isp": "Datapacket",
"hostname": "gb2.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.59.221.88"
@@ -26440,7 +26440,7 @@
"city": "Manchester",
"isp": "M247",
"hostname": "gb-man1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"89.238.141.228"
@@ -26451,7 +26451,7 @@
"city": "Atlanta, GA",
"isp": "Quadranet",
"hostname": "us-ga1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"104.129.24.146"
@@ -26462,7 +26462,7 @@
"city": "Atlanta, GA",
"isp": "Quadranet",
"hostname": "us-ga2.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"107.150.22.74"
@@ -26473,7 +26473,7 @@
"city": "Chicago, IL",
"isp": "Quadranet",
"hostname": "us-il1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"107.150.28.82"
@@ -26484,7 +26484,7 @@
"city": "Chicago, IL",
"isp": "Quadranet",
"hostname": "us-il2.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"72.11.137.146"
@@ -26495,7 +26495,7 @@
"city": "Dallas, TX",
"isp": "Quadranet",
"hostname": "us-tx1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"96.44.189.194"
@@ -26506,7 +26506,7 @@
"city": "Dallas, TX",
"isp": "Quadranet",
"hostname": "us-tx2.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"96.44.142.74"
@@ -26517,7 +26517,7 @@
"city": "Las Vegas, NV",
"isp": "M247",
"hostname": "us-nv1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"185.242.5.34"
@@ -26528,7 +26528,7 @@
"city": "Los Angeles, CA",
"isp": "Quadranet",
"hostname": "us-ca1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"173.254.196.58"
@@ -26539,7 +26539,7 @@
"city": "Los Angeles, CA",
"isp": "Quadranet",
"hostname": "us-ca2.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"69.12.80.146"
@@ -26550,7 +26550,7 @@
"city": "Los Angeles, CA",
"isp": "Leaseweb",
"hostname": "us-ca3.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"209.58.130.196"
@@ -26561,7 +26561,7 @@
"city": "Los Angeles, CA",
"isp": "Quadranet",
"hostname": "us-ca4.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"173.254.204.202"
@@ -26572,7 +26572,7 @@
"city": "Miami, FL",
"isp": "Quadranet",
"hostname": "us-fl1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"173.44.49.90"
@@ -26583,7 +26583,7 @@
"city": "New Jersey, NJ",
"isp": "Quadranet",
"hostname": "us-nj3.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"23.226.128.18"
@@ -26594,7 +26594,7 @@
"city": "New Jersey, NJ",
"isp": "M247",
"hostname": "us-nj4.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"194.36.111.50"
@@ -26605,7 +26605,7 @@
"city": "New York, NY",
"isp": "Leaseweb",
"hostname": "us-ny1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"64.120.44.114"
@@ -26616,7 +26616,7 @@
"city": "New York, NY",
"isp": "Leaseweb",
"hostname": "us-ny2.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"173.234.153.130"
@@ -26627,7 +26627,7 @@
"city": "Phoenix, AZ",
"isp": "M247",
"hostname": "us-az1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"193.37.254.130"
@@ -26638,7 +26638,7 @@
"city": "Salt Lake City, UT",
"isp": "100TB",
"hostname": "us-ut1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"198.105.216.28"
@@ -26649,7 +26649,7 @@
"city": "Seattle, WA",
"isp": "Leaseweb",
"hostname": "us-wa1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"23.19.87.209"
@@ -26660,7 +26660,7 @@
"city": "Washington, DC",
"isp": "Leaseweb",
"hostname": "us-dc1.gw.ivpn.net",
"tcp": false,
"tcp": true,
"udp": true,
"ips": [
"207.244.108.207"

View File

@@ -1,23 +1,16 @@
package ivpn
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 *Ivpn) GetConnection(selection configuration.ServerSelection) (
connection models.Connection, err error) {
const port = 2049
const protocol = constants.UDP
if selection.OpenVPN.TCP {
return connection, ErrProtocolUnsupported
}
port := getPort(selection)
protocol := getProtocol(selection.OpenVPN.TCP)
servers, err := i.filterServers(selection)
if err != nil {
@@ -44,3 +37,22 @@ func (i *Ivpn) GetConnection(selection configuration.ServerSelection) (
return utils.PickRandomConnection(connections, i.randSource), nil
}
func getPort(selection configuration.ServerSelection) (port uint16) {
customPort := selection.OpenVPN.CustomPort
if customPort > 0 {
return customPort
}
port = 1194
if selection.OpenVPN.TCP {
port = 443
}
return port
}
func getProtocol(tcp bool) (protocol string) {
if tcp {
return constants.TCP
}
return constants.UDP
}

View File

@@ -0,0 +1,173 @@
package ivpn
import (
"errors"
"math/rand"
"net"
"testing"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_Ivpn_GetConnection(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
servers []models.IvpnServer
selection configuration.ServerSelection
connection models.Connection
err error
}{
"no server available": {
selection: configuration.ServerSelection{
VPN: constants.OpenVPN,
},
err: errors.New("no server found: for VPN openvpn; protocol udp"),
},
"no filter": {
servers: []models.IvpnServer{
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, UDP: true},
{IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, UDP: true},
{IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, UDP: true},
},
connection: models.Connection{
IP: net.IPv4(1, 1, 1, 1),
Port: 1194,
Protocol: constants.UDP,
},
},
"target IP": {
selection: configuration.ServerSelection{
TargetIP: net.IPv4(2, 2, 2, 2),
},
servers: []models.IvpnServer{
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, UDP: true},
{IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, UDP: true},
{IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, UDP: true},
},
connection: models.Connection{
IP: net.IPv4(2, 2, 2, 2),
Port: 1194,
Protocol: constants.UDP,
},
},
"with filter": {
selection: configuration.ServerSelection{
Hostnames: []string{"b"},
},
servers: []models.IvpnServer{
{Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, UDP: true},
{Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, UDP: true},
{Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, UDP: true},
},
connection: models.Connection{
IP: net.IPv4(2, 2, 2, 2),
Port: 1194,
Protocol: constants.UDP,
Hostname: "b",
},
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
randSource := rand.NewSource(0)
m := New(testCase.servers, randSource)
connection, err := m.GetConnection(testCase.selection)
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.connection, connection)
})
}
}
func Test_getPort(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
selection configuration.ServerSelection
port uint16
}{
"default": {
port: 1194,
},
"OpenVPN UDP": {
selection: configuration.ServerSelection{
VPN: constants.OpenVPN,
},
port: 1194,
},
"OpenVPN TCP": {
selection: configuration.ServerSelection{
VPN: constants.OpenVPN,
OpenVPN: configuration.OpenVPNSelection{
TCP: true,
},
},
port: 443,
},
"OpenVPN custom port": {
selection: configuration.ServerSelection{
VPN: constants.OpenVPN,
OpenVPN: configuration.OpenVPNSelection{
CustomPort: 1234,
},
},
port: 1234,
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
port := getPort(testCase.selection)
assert.Equal(t, testCase.port, port)
})
}
}
func Test_getProtocol(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
tcp bool
protocol string
}{
"UDP": {
protocol: constants.UDP,
},
"TCP": {
tcp: true,
protocol: constants.TCP,
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
protocol := getProtocol(testCase.tcp)
assert.Equal(t, testCase.protocol, protocol)
})
}
}

View File

@@ -0,0 +1,132 @@
package ivpn
import (
"errors"
"math/rand"
"testing"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_Ivpn_filterServers(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
servers []models.IvpnServer
selection configuration.ServerSelection
filtered []models.IvpnServer
err error
}{
"no server available": {
selection: configuration.ServerSelection{
VPN: constants.OpenVPN,
},
err: errors.New("no server found: for VPN openvpn; protocol udp"),
},
"no filter": {
servers: []models.IvpnServer{
{Hostname: "a", UDP: true},
{Hostname: "b", UDP: true},
{Hostname: "c", UDP: true},
},
filtered: []models.IvpnServer{
{Hostname: "a", UDP: true},
{Hostname: "b", UDP: true},
{Hostname: "c", UDP: true},
},
},
"filter by country": {
selection: configuration.ServerSelection{
Countries: []string{"b"},
},
servers: []models.IvpnServer{
{Country: "a", UDP: true},
{Country: "b", UDP: true},
{Country: "c", UDP: true},
},
filtered: []models.IvpnServer{
{Country: "b", UDP: true},
},
},
"filter by city": {
selection: configuration.ServerSelection{
Cities: []string{"b"},
},
servers: []models.IvpnServer{
{City: "a", UDP: true},
{City: "b", UDP: true},
{City: "c", UDP: true},
},
filtered: []models.IvpnServer{
{City: "b", UDP: true},
},
},
"filter by ISP": {
selection: configuration.ServerSelection{
ISPs: []string{"b"},
},
servers: []models.IvpnServer{
{ISP: "a", UDP: true},
{ISP: "b", UDP: true},
{ISP: "c", UDP: true},
},
filtered: []models.IvpnServer{
{ISP: "b", UDP: true},
},
},
"filter by hostname": {
selection: configuration.ServerSelection{
Hostnames: []string{"b"},
},
servers: []models.IvpnServer{
{Hostname: "a", UDP: true},
{Hostname: "b", UDP: true},
{Hostname: "c", UDP: true},
},
filtered: []models.IvpnServer{
{Hostname: "b", UDP: true},
},
},
"filter by protocol": {
selection: configuration.ServerSelection{
OpenVPN: configuration.OpenVPNSelection{
TCP: true,
},
},
servers: []models.IvpnServer{
{Hostname: "a", UDP: true},
{Hostname: "b", UDP: true, TCP: true},
{Hostname: "c", UDP: true},
},
filtered: []models.IvpnServer{
{Hostname: "b", UDP: true, TCP: true},
},
},
}
for name, testCase := range testCases {
testCase := testCase
t.Run(name, func(t *testing.T) {
t.Parallel()
randSource := rand.NewSource(0)
m := New(testCase.servers, randSource)
servers, err := m.filterServers(testCase.selection)
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.filtered, servers)
})
}
}

View File

@@ -59,9 +59,9 @@ func GetServers(ctx context.Context, client *http.Client,
City: serverData.City,
ISP: serverData.ISP,
Hostname: serverData.Hostnames.OpenVPN,
// TCP is not supported
UDP: true,
IPs: hostToIPs[host],
TCP: true,
UDP: true,
IPs: hostToIPs[host],
}
servers = append(servers, server)
}

View File

@@ -83,8 +83,10 @@ func Test_GetServers(t *testing.T) {
},
resolveWarnings: []string{"resolve warning"},
servers: []models.IvpnServer{
{Country: "Country1", City: "City A", Hostname: "hosta", UDP: true, IPs: []net.IP{{1, 1, 1, 1}, {2, 2, 2, 2}}},
{Country: "Country2", City: "City B", Hostname: "hostb", UDP: true, IPs: []net.IP{{3, 3, 3, 3}, {4, 4, 4, 4}}},
{Country: "Country1", City: "City A", Hostname: "hosta",
TCP: true, UDP: true, IPs: []net.IP{{1, 1, 1, 1}, {2, 2, 2, 2}}},
{Country: "Country2", City: "City B", Hostname: "hostb",
TCP: true, UDP: true, IPs: []net.IP{{3, 3, 3, 3}, {4, 4, 4, 4}}},
},
warnings: []string{"resolve warning"},
},