Feature: filter by name and hostname for NordVPN

This commit is contained in:
Quentin McGaw
2021-05-08 22:51:59 +00:00
parent 2924d711cb
commit 248cc0d3d3
8 changed files with 5394 additions and 5326 deletions

View File

@@ -97,7 +97,7 @@ ENV VPNSP=pia \
OPENVPN_CLIENTKEY_SECRETFILE=/run/secrets/openvpn_clientkey \
# Nordvpn only:
SERVER_NUMBER= \
# ProtonVPN only:
# NordVPN and ProtonVPN only:
SERVER_NAME= \
# Openvpn
OPENVPN_CIPHER= \

View File

@@ -13,6 +13,14 @@ func (settings *Provider) nordvpnLines() (lines []string) {
lines = append(lines, lastIndent+"Regions: "+commaJoin(settings.ServerSelection.Regions))
}
if len(settings.ServerSelection.Hostnames) > 0 {
lines = append(lines, lastIndent+"Hostnames: "+commaJoin(settings.ServerSelection.Hostnames))
}
if len(settings.ServerSelection.Names) > 0 {
lines = append(lines, lastIndent+"Names: "+commaJoin(settings.ServerSelection.Hostnames))
}
if numbersUint16 := settings.ServerSelection.Numbers; len(numbersUint16) > 0 {
numbersString := make([]string, len(numbersUint16))
for i, numberUint16 := range numbersUint16 {
@@ -42,6 +50,16 @@ func (settings *Provider) readNordvpn(r reader) (err error) {
return err
}
settings.ServerSelection.Hostnames, err = r.env.CSVInside("SERVER_HOSTNAME", constants.NordvpnHostnameChoices())
if err != nil {
return err
}
settings.ServerSelection.Names, err = r.env.CSVInside("SERVER_NAME", constants.NordvpnHostnameChoices())
if err != nil {
return err
}
settings.ServerSelection.Numbers, err = readNordVPNServerNumbers(r.env)
if err != nil {
return err

File diff suppressed because it is too large Load Diff

View File

@@ -27,8 +27,8 @@ func GetAllServers() (allServers models.AllServers) {
Servers: MullvadServers(),
},
Nordvpn: models.NordvpnServers{
Version: 1,
Timestamp: 1620435633,
Version: 2,
Timestamp: 1620514180,
Servers: NordvpnServers(),
},
Privado: models.PrivadoServers{

View File

@@ -57,7 +57,7 @@ func Test_versions(t *testing.T) {
"Nordvpn": {
model: models.NordvpnServer{},
version: allServers.Nordvpn.Version,
digest: "040de8d0",
digest: "a3b5d609",
},
"Privado": {
model: models.PrivadoServer{},
@@ -163,7 +163,7 @@ func Test_timestamps(t *testing.T) {
"Nordvpn": {
servers: allServers.Nordvpn.Servers,
timestamp: allServers.Nordvpn.Timestamp,
digest: "69cb84b3",
digest: "b2619eea",
},
"Privado": {
servers: allServers.Privado.Servers,

View File

@@ -64,6 +64,8 @@ func (s *MullvadServer) String() string {
type NordvpnServer struct { //nolint:maligned
Region string `json:"region"`
Hostname string `json:"hostname"`
Name string `json:"name"`
Number uint16 `json:"number"`
IP net.IP `json:"ip"`
TCP bool `json:"tcp"`
@@ -71,8 +73,8 @@ type NordvpnServer struct { //nolint:maligned
}
func (s *NordvpnServer) String() string {
return fmt.Sprintf("{Region: %q, Number: %d, TCP: %t, UDP: %t, IP: %s}",
s.Region, s.Number, s.TCP, s.UDP, goStringifyIP(s.IP))
return fmt.Sprintf("{Region: %q, Hostname: %q, Name: %q, Number: %d, TCP: %t, UDP: %t, IP: %s}",
s.Region, s.Hostname, s.Name, s.Number, s.TCP, s.UDP, goStringifyIP(s.IP))
}
type PrivadoServer struct {

View File

@@ -2,6 +2,7 @@ package provider
import (
"context"
"errors"
"fmt"
"math/rand"
"net"
@@ -28,7 +29,7 @@ func newNordvpn(servers []models.NordvpnServer, timeNow timeNowFunc) *nordvpn {
}
}
func (n *nordvpn) filterServers(regions []string, protocol string, numbers []uint16) (
func (n *nordvpn) filterServers(regions, hostnames, names []string, numbers []uint16, protocol string) (
servers []models.NordvpnServer) {
numbersStr := make([]string, len(numbers))
for i := range numbers {
@@ -41,6 +42,8 @@ func (n *nordvpn) filterServers(regions []string, protocol string, numbers []uin
protocol == constants.TCP && !server.TCP,
protocol == constants.UDP && !server.UDP,
filterByPossibilities(server.Region, regions),
filterByPossibilities(server.Hostname, hostnames),
filterByPossibilities(server.Name, names),
filterByPossibilities(numberStr, numbersStr):
default:
servers = append(servers, server)
@@ -49,6 +52,34 @@ func (n *nordvpn) filterServers(regions []string, protocol string, numbers []uin
return servers
}
var errNoServerFound = errors.New("no server found")
func (n *nordvpn) notFoundErr(selection configuration.ServerSelection) error {
message := "for protocol " + selection.Protocol
if len(selection.Regions) > 0 {
message += " + regions " + commaJoin(selection.Regions)
}
if len(selection.Hostnames) > 0 {
message += " + hostnames " + commaJoin(selection.Hostnames)
}
if len(selection.Names) > 0 {
message += " + names " + commaJoin(selection.Names)
}
if len(selection.Numbers) > 0 {
numbers := make([]string, len(selection.Numbers))
for i, n := range selection.Numbers {
numbers[i] = strconv.Itoa(int(n))
}
message += " + numbers " + commaJoin(numbers)
}
return fmt.Errorf("%w: %s", errNoServerFound, message)
}
func (n *nordvpn) GetOpenVPNConnection(selection configuration.ServerSelection) (
connection models.OpenVPNConnection, err error) {
var port uint16
@@ -65,10 +96,10 @@ func (n *nordvpn) GetOpenVPNConnection(selection configuration.ServerSelection)
return models.OpenVPNConnection{IP: selection.TargetIP, Port: port, Protocol: selection.Protocol}, nil
}
servers := n.filterServers(selection.Regions, selection.Protocol, selection.Numbers)
servers := n.filterServers(selection.Regions, selection.Hostnames,
selection.Names, selection.Numbers, selection.Protocol)
if len(servers) == 0 {
return connection, fmt.Errorf("no server found for region %s, protocol %s and numbers %v",
commaJoin(selection.Regions), selection.Protocol, selection.Numbers)
return connection, n.notFoundErr(selection)
}
connections := make([]models.OpenVPNConnection, len(servers))

View File

@@ -45,6 +45,8 @@ func GetServers(ctx context.Context, client *http.Client, minServers int) (
server := models.NordvpnServer{
Region: jsonServer.Country,
Hostname: jsonServer.Domain,
Name: jsonServer.Name,
Number: number,
IP: ip,
TCP: jsonServer.Features.TCP,