Wireguard support for Mullvad and Windscribe (#565)
- `internal/wireguard` client package with unit tests - Implementation works with kernel space or user space if unavailable - `WIREGUARD_PRIVATE_KEY` - `WIREGUARD_ADDRESS` - `WIREGUARD_PRESHARED_KEY` - `WIREGUARD_PORT` - `internal/netlink` package used by `internal/wireguard`
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"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"
|
||||
@@ -19,7 +20,8 @@ func Test_Cyberghost_filterServers(t *testing.T) {
|
||||
err error
|
||||
}{
|
||||
"no servers": {
|
||||
err: errors.New("no server found: for protocol udp"),
|
||||
selection: configuration.ServerSelection{VPN: constants.OpenVPN},
|
||||
err: errors.New("no server found: for VPN openvpn; protocol udp"),
|
||||
},
|
||||
"servers without filter defaults to UDP": {
|
||||
servers: []models.CyberghostServer{
|
||||
|
||||
@@ -9,16 +9,8 @@ import (
|
||||
|
||||
func (m *Mullvad) GetConnection(selection configuration.ServerSelection) (
|
||||
connection models.Connection, err error) {
|
||||
var port uint16 = 1194
|
||||
protocol := constants.UDP
|
||||
if selection.OpenVPN.TCP {
|
||||
port = 443
|
||||
protocol = constants.TCP
|
||||
}
|
||||
|
||||
if selection.OpenVPN.CustomPort > 0 {
|
||||
port = selection.OpenVPN.CustomPort
|
||||
}
|
||||
port := getPort(selection)
|
||||
protocol := getProtocol(selection)
|
||||
|
||||
servers, err := m.filterServers(selection)
|
||||
if err != nil {
|
||||
@@ -33,6 +25,7 @@ func (m *Mullvad) GetConnection(selection configuration.ServerSelection) (
|
||||
IP: IP,
|
||||
Port: port,
|
||||
Protocol: protocol,
|
||||
PubKey: server.WgPubKey, // Wireguard only
|
||||
}
|
||||
connections = append(connections, connection)
|
||||
}
|
||||
@@ -44,3 +37,33 @@ func (m *Mullvad) GetConnection(selection configuration.ServerSelection) (
|
||||
|
||||
return utils.PickRandomConnection(connections, m.randSource), nil
|
||||
}
|
||||
|
||||
func getPort(selection configuration.ServerSelection) (port uint16) {
|
||||
switch selection.VPN {
|
||||
case constants.Wireguard:
|
||||
customPort := selection.Wireguard.CustomPort
|
||||
if customPort > 0 {
|
||||
return customPort
|
||||
}
|
||||
const defaultPort = 51820
|
||||
return defaultPort
|
||||
default: // OpenVPN
|
||||
customPort := selection.OpenVPN.CustomPort
|
||||
if customPort > 0 {
|
||||
return customPort
|
||||
}
|
||||
port = 1194
|
||||
if selection.OpenVPN.TCP {
|
||||
port = 443
|
||||
}
|
||||
return port
|
||||
}
|
||||
}
|
||||
|
||||
func getProtocol(selection configuration.ServerSelection) (protocol string) {
|
||||
protocol = constants.UDP
|
||||
if selection.VPN == constants.OpenVPN && selection.OpenVPN.TCP {
|
||||
protocol = constants.TCP
|
||||
}
|
||||
return protocol
|
||||
}
|
||||
|
||||
204
internal/provider/mullvad/connection_test.go
Normal file
204
internal/provider/mullvad/connection_test.go
Normal file
@@ -0,0 +1,204 @@
|
||||
package mullvad
|
||||
|
||||
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_Mullvad_GetConnection(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := map[string]struct {
|
||||
servers []models.MullvadServer
|
||||
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.MullvadServer{
|
||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
||||
{IPs: []net.IP{net.IPv4(2, 2, 2, 2)}},
|
||||
{IPs: []net.IP{net.IPv4(3, 3, 3, 3)}},
|
||||
},
|
||||
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.MullvadServer{
|
||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
||||
{IPs: []net.IP{net.IPv4(2, 2, 2, 2)}},
|
||||
{IPs: []net.IP{net.IPv4(3, 3, 3, 3)}},
|
||||
},
|
||||
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.MullvadServer{
|
||||
{Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
||||
{Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}},
|
||||
{Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}},
|
||||
},
|
||||
connection: models.Connection{
|
||||
IP: net.IPv4(2, 2, 2, 2),
|
||||
Port: 1194,
|
||||
Protocol: constants.UDP,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
"Wireguard": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.Wireguard,
|
||||
},
|
||||
port: 51820,
|
||||
},
|
||||
"Wireguard custom port": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.Wireguard,
|
||||
Wireguard: configuration.WireguardSelection{
|
||||
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 {
|
||||
selection configuration.ServerSelection
|
||||
protocol string
|
||||
}{
|
||||
"default": {
|
||||
protocol: constants.UDP,
|
||||
},
|
||||
"OpenVPN UDP": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.OpenVPN,
|
||||
},
|
||||
protocol: constants.UDP,
|
||||
},
|
||||
"OpenVPN TCP": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.OpenVPN,
|
||||
OpenVPN: configuration.OpenVPNSelection{
|
||||
TCP: true,
|
||||
},
|
||||
},
|
||||
protocol: constants.TCP,
|
||||
},
|
||||
"Wireguard": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.Wireguard,
|
||||
},
|
||||
protocol: constants.UDP,
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
protocol := getProtocol(testCase.selection)
|
||||
|
||||
assert.Equal(t, testCase.protocol, protocol)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ func (m *Mullvad) filterServers(selection configuration.ServerSelection) (
|
||||
for _, server := range m.servers {
|
||||
switch {
|
||||
case
|
||||
server.VPN != selection.VPN,
|
||||
utils.FilterByPossibilities(server.Country, selection.Countries),
|
||||
utils.FilterByPossibilities(server.City, selection.Cities),
|
||||
utils.FilterByPossibilities(server.ISP, selection.ISPs),
|
||||
|
||||
143
internal/provider/mullvad/filter_test.go
Normal file
143
internal/provider/mullvad/filter_test.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package mullvad
|
||||
|
||||
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_Mullvad_filterServers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := map[string]struct {
|
||||
servers []models.MullvadServer
|
||||
selection configuration.ServerSelection
|
||||
filtered []models.MullvadServer
|
||||
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.MullvadServer{
|
||||
{Hostname: "a"},
|
||||
{Hostname: "b"},
|
||||
{Hostname: "c"},
|
||||
},
|
||||
filtered: []models.MullvadServer{
|
||||
{Hostname: "a"},
|
||||
{Hostname: "b"},
|
||||
{Hostname: "c"},
|
||||
},
|
||||
},
|
||||
"filter OpenVPN out": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.Wireguard,
|
||||
},
|
||||
servers: []models.MullvadServer{
|
||||
{VPN: constants.OpenVPN, Hostname: "a"},
|
||||
{VPN: constants.Wireguard, Hostname: "b"},
|
||||
{VPN: constants.OpenVPN, Hostname: "c"},
|
||||
},
|
||||
filtered: []models.MullvadServer{
|
||||
{VPN: constants.Wireguard, Hostname: "b"},
|
||||
},
|
||||
},
|
||||
"filter by country": {
|
||||
selection: configuration.ServerSelection{
|
||||
Countries: []string{"b"},
|
||||
},
|
||||
servers: []models.MullvadServer{
|
||||
{Country: "a"},
|
||||
{Country: "b"},
|
||||
{Country: "c"},
|
||||
},
|
||||
filtered: []models.MullvadServer{
|
||||
{Country: "b"},
|
||||
},
|
||||
},
|
||||
"filter by city": {
|
||||
selection: configuration.ServerSelection{
|
||||
Cities: []string{"b"},
|
||||
},
|
||||
servers: []models.MullvadServer{
|
||||
{City: "a"},
|
||||
{City: "b"},
|
||||
{City: "c"},
|
||||
},
|
||||
filtered: []models.MullvadServer{
|
||||
{City: "b"},
|
||||
},
|
||||
},
|
||||
"filter by ISP": {
|
||||
selection: configuration.ServerSelection{
|
||||
ISPs: []string{"b"},
|
||||
},
|
||||
servers: []models.MullvadServer{
|
||||
{ISP: "a"},
|
||||
{ISP: "b"},
|
||||
{ISP: "c"},
|
||||
},
|
||||
filtered: []models.MullvadServer{
|
||||
{ISP: "b"},
|
||||
},
|
||||
},
|
||||
"filter by hostname": {
|
||||
selection: configuration.ServerSelection{
|
||||
Hostnames: []string{"b"},
|
||||
},
|
||||
servers: []models.MullvadServer{
|
||||
{Hostname: "a"},
|
||||
{Hostname: "b"},
|
||||
{Hostname: "c"},
|
||||
},
|
||||
filtered: []models.MullvadServer{
|
||||
{Hostname: "b"},
|
||||
},
|
||||
},
|
||||
"filter by owned": {
|
||||
selection: configuration.ServerSelection{
|
||||
Owned: true,
|
||||
},
|
||||
servers: []models.MullvadServer{
|
||||
{Hostname: "a"},
|
||||
{Hostname: "b", Owned: true},
|
||||
{Hostname: "c"},
|
||||
},
|
||||
filtered: []models.MullvadServer{
|
||||
{Hostname: "b", Owned: 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)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ var ErrNoServerFound = errors.New("no server found")
|
||||
func NoServerFoundError(selection configuration.ServerSelection) (err error) {
|
||||
var messageParts []string
|
||||
|
||||
messageParts = append(messageParts, "VPN "+selection.VPN)
|
||||
|
||||
protocol := constants.UDP
|
||||
if selection.OpenVPN.TCP {
|
||||
protocol = constants.TCP
|
||||
|
||||
34
internal/provider/utils/wireguard.go
Normal file
34
internal/provider/utils/wireguard.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/configuration"
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
"github.com/qdm12/gluetun/internal/wireguard"
|
||||
)
|
||||
|
||||
func BuildWireguardSettings(connection models.Connection,
|
||||
userSettings configuration.Wireguard) (settings wireguard.Settings) {
|
||||
settings.PrivateKey = userSettings.PrivateKey
|
||||
settings.PublicKey = connection.PubKey
|
||||
settings.PreSharedKey = userSettings.PreSharedKey
|
||||
settings.InterfaceName = userSettings.Interface
|
||||
|
||||
const routePriority = 101 // 100 is to receive external connections
|
||||
settings.RulePriority = routePriority
|
||||
|
||||
settings.Endpoint = new(net.UDPAddr)
|
||||
settings.Endpoint.IP = make(net.IP, len(connection.IP))
|
||||
copy(settings.Endpoint.IP, connection.IP)
|
||||
settings.Endpoint.Port = int(connection.Port)
|
||||
|
||||
address := new(net.IPNet)
|
||||
address.IP = make(net.IP, len(userSettings.Address.IP))
|
||||
copy(address.IP, userSettings.Address.IP)
|
||||
address.Mask = make(net.IPMask, len(userSettings.Address.Mask))
|
||||
copy(address.Mask, userSettings.Address.Mask)
|
||||
settings.Addresses = append(settings.Addresses, address)
|
||||
|
||||
return settings
|
||||
}
|
||||
@@ -9,16 +9,8 @@ import (
|
||||
|
||||
func (w *Windscribe) GetConnection(selection configuration.ServerSelection) (
|
||||
connection models.Connection, err error) {
|
||||
protocol := constants.UDP
|
||||
var port uint16 = 443
|
||||
if selection.OpenVPN.TCP {
|
||||
protocol = constants.TCP
|
||||
port = 1194
|
||||
}
|
||||
|
||||
if selection.OpenVPN.CustomPort > 0 {
|
||||
port = selection.OpenVPN.CustomPort
|
||||
}
|
||||
port := getPort(selection)
|
||||
protocol := getProtocol(selection)
|
||||
|
||||
servers, err := w.filterServers(selection)
|
||||
if err != nil {
|
||||
@@ -34,6 +26,7 @@ func (w *Windscribe) GetConnection(selection configuration.ServerSelection) (
|
||||
Port: port,
|
||||
Protocol: protocol,
|
||||
Hostname: server.OvpnX509,
|
||||
PubKey: server.WgPubKey,
|
||||
}
|
||||
connections = append(connections, connection)
|
||||
}
|
||||
@@ -45,3 +38,33 @@ func (w *Windscribe) GetConnection(selection configuration.ServerSelection) (
|
||||
|
||||
return utils.PickRandomConnection(connections, w.randSource), nil
|
||||
}
|
||||
|
||||
func getPort(selection configuration.ServerSelection) (port uint16) {
|
||||
switch selection.VPN {
|
||||
case constants.Wireguard:
|
||||
customPort := selection.Wireguard.CustomPort
|
||||
if customPort > 0 {
|
||||
return customPort
|
||||
}
|
||||
const defaultPort = 1194
|
||||
return defaultPort
|
||||
default: // OpenVPN
|
||||
customPort := selection.OpenVPN.CustomPort
|
||||
if customPort > 0 {
|
||||
return customPort
|
||||
}
|
||||
port = 1194
|
||||
if selection.OpenVPN.TCP {
|
||||
port = 443
|
||||
}
|
||||
return port
|
||||
}
|
||||
}
|
||||
|
||||
func getProtocol(selection configuration.ServerSelection) (protocol string) {
|
||||
protocol = constants.UDP
|
||||
if selection.VPN == constants.OpenVPN && selection.OpenVPN.TCP {
|
||||
protocol = constants.TCP
|
||||
}
|
||||
return protocol
|
||||
}
|
||||
|
||||
204
internal/provider/windscribe/connection_test.go
Normal file
204
internal/provider/windscribe/connection_test.go
Normal file
@@ -0,0 +1,204 @@
|
||||
package windscribe
|
||||
|
||||
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_Windscribe_GetConnection(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := map[string]struct {
|
||||
servers []models.WindscribeServer
|
||||
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.WindscribeServer{
|
||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
||||
{IPs: []net.IP{net.IPv4(2, 2, 2, 2)}},
|
||||
{IPs: []net.IP{net.IPv4(3, 3, 3, 3)}},
|
||||
},
|
||||
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.WindscribeServer{
|
||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
||||
{IPs: []net.IP{net.IPv4(2, 2, 2, 2)}},
|
||||
{IPs: []net.IP{net.IPv4(3, 3, 3, 3)}},
|
||||
},
|
||||
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.WindscribeServer{
|
||||
{Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
||||
{Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}},
|
||||
{Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}},
|
||||
},
|
||||
connection: models.Connection{
|
||||
IP: net.IPv4(2, 2, 2, 2),
|
||||
Port: 1194,
|
||||
Protocol: constants.UDP,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
"Wireguard": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.Wireguard,
|
||||
},
|
||||
port: 1194,
|
||||
},
|
||||
"Wireguard custom port": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.Wireguard,
|
||||
Wireguard: configuration.WireguardSelection{
|
||||
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 {
|
||||
selection configuration.ServerSelection
|
||||
protocol string
|
||||
}{
|
||||
"default": {
|
||||
protocol: constants.UDP,
|
||||
},
|
||||
"OpenVPN UDP": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.OpenVPN,
|
||||
},
|
||||
protocol: constants.UDP,
|
||||
},
|
||||
"OpenVPN TCP": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.OpenVPN,
|
||||
OpenVPN: configuration.OpenVPNSelection{
|
||||
TCP: true,
|
||||
},
|
||||
},
|
||||
protocol: constants.TCP,
|
||||
},
|
||||
"Wireguard": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.Wireguard,
|
||||
},
|
||||
protocol: constants.UDP,
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
protocol := getProtocol(testCase.selection)
|
||||
|
||||
assert.Equal(t, testCase.protocol, protocol)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ func (w *Windscribe) filterServers(selection configuration.ServerSelection) (
|
||||
for _, server := range w.servers {
|
||||
switch {
|
||||
case
|
||||
server.VPN != selection.VPN,
|
||||
utils.FilterByPossibilities(server.Region, selection.Regions),
|
||||
utils.FilterByPossibilities(server.City, selection.Cities),
|
||||
utils.FilterByPossibilities(server.Hostname, selection.Hostnames):
|
||||
|
||||
117
internal/provider/windscribe/filter_test.go
Normal file
117
internal/provider/windscribe/filter_test.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package windscribe
|
||||
|
||||
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_Windscribe_filterServers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := map[string]struct {
|
||||
servers []models.WindscribeServer
|
||||
selection configuration.ServerSelection
|
||||
filtered []models.WindscribeServer
|
||||
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.WindscribeServer{
|
||||
{Hostname: "a"},
|
||||
{Hostname: "b"},
|
||||
{Hostname: "c"},
|
||||
},
|
||||
filtered: []models.WindscribeServer{
|
||||
{Hostname: "a"},
|
||||
{Hostname: "b"},
|
||||
{Hostname: "c"},
|
||||
},
|
||||
},
|
||||
"filter OpenVPN out": {
|
||||
selection: configuration.ServerSelection{
|
||||
VPN: constants.Wireguard,
|
||||
},
|
||||
servers: []models.WindscribeServer{
|
||||
{VPN: constants.OpenVPN, Hostname: "a"},
|
||||
{VPN: constants.Wireguard, Hostname: "b"},
|
||||
{VPN: constants.OpenVPN, Hostname: "c"},
|
||||
},
|
||||
filtered: []models.WindscribeServer{
|
||||
{VPN: constants.Wireguard, Hostname: "b"},
|
||||
},
|
||||
},
|
||||
"filter by region": {
|
||||
selection: configuration.ServerSelection{
|
||||
Regions: []string{"b"},
|
||||
},
|
||||
servers: []models.WindscribeServer{
|
||||
{Region: "a"},
|
||||
{Region: "b"},
|
||||
{Region: "c"},
|
||||
},
|
||||
filtered: []models.WindscribeServer{
|
||||
{Region: "b"},
|
||||
},
|
||||
},
|
||||
"filter by city": {
|
||||
selection: configuration.ServerSelection{
|
||||
Cities: []string{"b"},
|
||||
},
|
||||
servers: []models.WindscribeServer{
|
||||
{City: "a"},
|
||||
{City: "b"},
|
||||
{City: "c"},
|
||||
},
|
||||
filtered: []models.WindscribeServer{
|
||||
{City: "b"},
|
||||
},
|
||||
},
|
||||
"filter by hostname": {
|
||||
selection: configuration.ServerSelection{
|
||||
Hostnames: []string{"b"},
|
||||
},
|
||||
servers: []models.WindscribeServer{
|
||||
{Hostname: "a"},
|
||||
{Hostname: "b"},
|
||||
{Hostname: "c"},
|
||||
},
|
||||
filtered: []models.WindscribeServer{
|
||||
{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)
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user