@@ -42,7 +42,7 @@ ENV VPNSP=pia \
|
||||
UID=1000 \
|
||||
GID=1000 \
|
||||
IP_STATUS_FILE="/ip" \
|
||||
# PIA, Windscribe, Surfshark and Cyberghost only
|
||||
# PIA, Windscribe, Surfshark, Cyberghost, Vyprvpn, NordVPN only
|
||||
USER= \
|
||||
PASSWORD= \
|
||||
REGION="Austria" \
|
||||
@@ -58,6 +58,8 @@ ENV VPNSP=pia \
|
||||
PORT= \
|
||||
# Cyberghost only
|
||||
CYBERGHOST_GROUP="Premium UDP Europe" \
|
||||
# NordVPN only
|
||||
SERVER_NUMBER= \
|
||||
# Openvpn
|
||||
OPENVPN_CIPHER= \
|
||||
OPENVPN_AUTH= \
|
||||
|
||||
25
README.md
25
README.md
@@ -1,6 +1,8 @@
|
||||
# Gluetun VPN client
|
||||
|
||||
*Lightweight swiss-knife-like VPN client to tunnel to Private Internet Access, Mullvad, Windscribe, Surfshark and Cyberghost VPN servers, using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and Tinyproxy*
|
||||
*Lightweight swiss-knife-like VPN client to tunnel to Private Internet Access,
|
||||
Mullvad, Windscribe, Surfshark Cyberghost and NordVPN VPN servers, using Go, OpenVPN,
|
||||
iptables, DNS over TLS, ShadowSocks and Tinyproxy*
|
||||
|
||||
**ANNOUNCEMENT**: *[Video of the Git history of Gluetun](https://youtu.be/khipOYJtGJ0)*
|
||||
|
||||
@@ -33,7 +35,8 @@
|
||||
## Features
|
||||
|
||||
- Based on Alpine 3.12 for a small Docker image of 52MB
|
||||
- Supports **Private Internet Access**, **Mullvad**, **Windscribe**, **Surfshark** and **Cyberghost** servers
|
||||
- Supports **Private Internet Access**, **Mullvad**, **Windscribe**,
|
||||
**Surfshark**, **Cyberghost** and **NordVPN** servers
|
||||
- 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
|
||||
- Choose the vpn network protocol, `udp` or `tcp`
|
||||
@@ -90,9 +93,9 @@
|
||||
[](https://windscribe.com/?affid=mh7nyafu)
|
||||
|
||||
- Surfshark: **username** and **password** ([sign up](https://order.surfshark.com/))
|
||||
- Cyberghost: **username**, **password** and **device client key file**
|
||||
([sign up](https://www.cyberghostvpn.com/en_US/buy/cyberghost-vpn-4))
|
||||
- Cyberghost: **username**, **password** and **device client key file** ([sign up](https://www.cyberghostvpn.com/en_US/buy/cyberghost-vpn-4))
|
||||
- Vyprvpn: **username** and **password**
|
||||
- NordVPN: **username** and **password**
|
||||
- If you have a host or router firewall, please refer [to the firewall documentation](https://github.com/qdm12/private-internet-access-docker/blob/master/doc/firewall.md)
|
||||
|
||||
1. On some devices you may need to setup your tunnel kernel module on your host with `insmod /lib/modules/tun.ko` or `modprobe tun`
|
||||
@@ -118,7 +121,6 @@
|
||||
- Use `-p 8888:8888/tcp` to access the HTTP web proxy (and put your LAN in `EXTRA_SUBNETS` environment variable, in example `192.168.1.0/24`)
|
||||
- Use `-p 8388:8388/tcp -p 8388:8388/udp` to access the SOCKS5 proxy (and put your LAN in `EXTRA_SUBNETS` environment variable, in example `192.168.1.0/24`)
|
||||
- Use `-p 8000:8000/tcp` to access the [HTTP control server](#HTTP-control-server) built-in
|
||||
- Pass additional arguments to *openvpn* using Docker's command function (commands after the image name)
|
||||
|
||||
**If you encounter an issue with the tun device not being available, see [the FAQ](https://github.com/qdm12/private-internet-access-docker/blob/master/doc/faq.md#how-to-fix-openvpn-failing-to-start)**
|
||||
|
||||
@@ -142,7 +144,7 @@ Want more testing? ▶ [see the Wiki](https://github.com/qdm12/private-internet-
|
||||
|
||||
| Variable | Default | Choices | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| 🏁 `VPNSP` | `private internet access` | `private internet access`, `mullvad`, `windscribe`, `surfshark`, `vyprvpn` | VPN Service Provider |
|
||||
| 🏁 `VPNSP` | `private internet access` | `private internet access`, `mullvad`, `windscribe`, `surfshark`, `vyprvpn`, `nordvpn` | VPN Service Provider |
|
||||
| `IP_STATUS_FILE` | `/ip` | Any filepath | Filepath to store the public IP address assigned |
|
||||
| `PROTOCOL` | `udp` | `udp` or `tcp` | Network protocol to use |
|
||||
| `OPENVPN_VERBOSITY` | `1` | `0` to `6` | Openvpn verbosity level |
|
||||
@@ -210,13 +212,22 @@ Want more testing? ▶ [see the Wiki](https://github.com/qdm12/private-internet-
|
||||
|
||||
And use the line produced as the value for the environment variable `CLIENT_KEY`.
|
||||
|
||||
- VyprVPN
|
||||
- NordVPN
|
||||
|
||||
| Variable | Default | Choices | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| 🏁 `USER` | | | Your username |
|
||||
| 🏁 `PASSWORD` | | | Your password |
|
||||
| `REGION` | `Austria` | One of the [VyprVPN regions](https://www.vyprvpn.com/server-locations) | VPN server region |
|
||||
| `SERVER_NUMBER` | | Server integer number | Optional server number. For example `251` for `Italy #251` |
|
||||
|
||||
- NordVPN
|
||||
|
||||
| Variable | Default | Choices | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| 🏁 `USER` | | | Your username |
|
||||
| 🏁 `PASSWORD` | | | Your password |
|
||||
| 🏁 `REGION` | `Austria` (wrong) | One of the NordVPN server name, i.e. `Cyprus #12` | VPN server name |
|
||||
|
||||
### DNS over TLS
|
||||
|
||||
|
||||
106
cmd/mapper/main.go
Normal file
106
cmd/mapper/main.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/qdm12/golibs/network"
|
||||
"github.com/qdm12/private-internet-access-docker/internal/models"
|
||||
)
|
||||
|
||||
func main() {
|
||||
os.Exit(_main())
|
||||
}
|
||||
|
||||
func _main() int {
|
||||
provider := flag.String("provider", "nordvpn", "VPN provider to map region to IP addresses using their API, can be 'nordvpn'")
|
||||
flag.Parse()
|
||||
|
||||
client := network.NewClient(30 * time.Second) // big file so 30 seconds
|
||||
switch *provider {
|
||||
case "nordvpn":
|
||||
servers, ignoredServers, err := nordvpn(client)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return 1
|
||||
}
|
||||
for _, server := range servers {
|
||||
fmt.Printf(
|
||||
"{Region: %q, Number: %d, TCP: %t, UDP: %t, IP: net.IP{%s}},\n",
|
||||
server.Region, server.Number, server.TCP, server.UDP, strings.ReplaceAll(server.IP.String(), ".", ", "),
|
||||
)
|
||||
}
|
||||
fmt.Print("\n\n")
|
||||
for _, serverName := range ignoredServers {
|
||||
fmt.Printf("ignored server %q because it does not support both UDP and TCP\n", serverName)
|
||||
}
|
||||
default:
|
||||
fmt.Printf("Provider %q is not supported\n", *provider)
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func nordvpn(client network.Client) (servers []models.NordvpnServer, ignoredServers []string, err error) {
|
||||
content, status, err := client.GetContent("https://nordvpn.com/api/server")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
} else if status != http.StatusOK {
|
||||
return nil, nil, fmt.Errorf("HTTP status %d from NordVPN API", status)
|
||||
}
|
||||
response := []struct {
|
||||
IPAddress string `json:"ip_address"`
|
||||
Name string `json:"name"`
|
||||
Country string `json:"country"`
|
||||
Features struct {
|
||||
UDP bool `json:"openvpn_udp"`
|
||||
TCP bool `json:"openvpn_tcp"`
|
||||
} `json:"features"`
|
||||
}{}
|
||||
if err := json.Unmarshal(content, &response); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for _, element := range response {
|
||||
if !element.Features.TCP && !element.Features.UDP {
|
||||
ignoredServers = append(ignoredServers, element.Name)
|
||||
}
|
||||
ip := net.ParseIP(element.IPAddress)
|
||||
if ip == nil {
|
||||
return nil, nil, fmt.Errorf("IP address %q is not valid for server %q", element.IPAddress, element.Name)
|
||||
}
|
||||
i := strings.IndexRune(element.Name, '#')
|
||||
if i < 0 {
|
||||
return nil, nil, fmt.Errorf("No ID in server name %q", element.Name)
|
||||
}
|
||||
idString := element.Name[i+1:]
|
||||
idUint64, err := strconv.ParseUint(idString, 10, 16)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Bad ID in server name %q", element.Name)
|
||||
}
|
||||
id := uint16(idUint64)
|
||||
server := models.NordvpnServer{
|
||||
Region: element.Country,
|
||||
Number: id,
|
||||
IP: ip,
|
||||
TCP: element.Features.TCP,
|
||||
UDP: element.Features.UDP,
|
||||
}
|
||||
servers = append(servers, server)
|
||||
}
|
||||
sort.Slice(servers, func(i, j int) bool {
|
||||
if servers[i].Region == servers[j].Region {
|
||||
return servers[i].Number < servers[j].Number
|
||||
}
|
||||
return servers[i].Region < servers[j].Region
|
||||
})
|
||||
return servers, ignoredServers, nil
|
||||
}
|
||||
@@ -15,50 +15,25 @@ services:
|
||||
environment:
|
||||
# More variables are available, see the readme table
|
||||
- VPNSP=private internet access
|
||||
- PROTOCOL=udp
|
||||
- OPENVPN_VERBOSITY=1
|
||||
- OPENVPN_ROOT=no
|
||||
- OPENVPN_TARGET_IP=
|
||||
|
||||
# Timezone for accurate logs times
|
||||
- TZ=
|
||||
|
||||
# PIA, Windscribe, Surfshark and Cyberghost only
|
||||
- REGION=Austria
|
||||
# All VPN providers
|
||||
- USER=js89ds7
|
||||
|
||||
# All VPN providers but Mullvad
|
||||
- PASSWORD=8fd9s239G
|
||||
|
||||
# PIA only
|
||||
- PIA_ENCRYPTION=strong
|
||||
- PORT_FORWARDING=off
|
||||
# Cyberghost only
|
||||
- CLIENT_KEY=
|
||||
|
||||
# All VPN providers but Mullvad
|
||||
- REGION=Austria
|
||||
|
||||
# Mullvad only
|
||||
- COUNTRY=Sweden
|
||||
- CITY=
|
||||
- ISP=
|
||||
|
||||
# Mullvad and Windscribe only
|
||||
- PORT=
|
||||
|
||||
# Cyberghost only
|
||||
- CYBERGHOST_GROUP=Premium UDP Europe
|
||||
- CLIENT_KEY=
|
||||
|
||||
# DNS over TLS
|
||||
- DOT=on
|
||||
- DOT_PROVIDERS=cloudflare
|
||||
- DOT_IPV6=off
|
||||
- DOT_VERBOSITY=1
|
||||
- BLOCK_MALICIOUS=on
|
||||
- BLOCK_SURVEILLANCE=off
|
||||
- BLOCK_ADS=off
|
||||
- UNBLOCK=
|
||||
- DNS_UPDATE_PERIOD=24h
|
||||
# Firewall
|
||||
# Allow for example your LAN, set to: 192.168.1.0/24
|
||||
- EXTRA_SUBNETS=
|
||||
# Shadowsocks
|
||||
- SHADOWSOCKS=off
|
||||
- SHADOWSOCKS_PASSWORD=
|
||||
# Tinyproxy
|
||||
- TINYPROXY=off
|
||||
- TINYPROXY_USER=
|
||||
- TINYPROXY_PASSWORD=
|
||||
restart: always
|
||||
|
||||
5184
internal/constants/nordvpn.go
Normal file
5184
internal/constants/nordvpn.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,8 @@ const (
|
||||
Cyberghost models.VPNProvider = "cyberghost"
|
||||
// Vyprvpn is a VPN provider
|
||||
Vyprvpn models.VPNProvider = "vyprvpn"
|
||||
// NordVPN is a VPN provider
|
||||
Nordvpn models.VPNProvider = "nordvpn"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -14,12 +14,12 @@ type ProviderSettings struct {
|
||||
PortForwarding PortForwarding
|
||||
}
|
||||
|
||||
type ServerSelection struct {
|
||||
type ServerSelection struct { //nolint:maligned
|
||||
// Common
|
||||
Protocol NetworkProtocol
|
||||
TargetIP net.IP
|
||||
|
||||
// Cyberghost, PIA, Surfshark, Windscribe
|
||||
// Cyberghost, PIA, Surfshark, Windscribe, Vyprvpn, NordVPN
|
||||
Region string
|
||||
|
||||
// Cyberghost
|
||||
@@ -36,6 +36,9 @@ type ServerSelection struct {
|
||||
|
||||
// PIA
|
||||
EncryptionPreset string
|
||||
|
||||
// NordVPN
|
||||
Number uint16
|
||||
}
|
||||
|
||||
type ExtraConfigOptions struct {
|
||||
@@ -61,6 +64,14 @@ func (p *ProviderSettings) String() string {
|
||||
fmt.Sprintf("%s settings:", strings.Title(string(p.Name))),
|
||||
"Network protocol: " + string(p.ServerSelection.Protocol),
|
||||
}
|
||||
customPort := ""
|
||||
if p.ServerSelection.CustomPort > 0 {
|
||||
customPort = fmt.Sprintf("%d", p.ServerSelection.CustomPort)
|
||||
}
|
||||
number := ""
|
||||
if p.ServerSelection.Number > 0 {
|
||||
number = fmt.Sprintf("%d", p.ServerSelection.Number)
|
||||
}
|
||||
switch strings.ToLower(string(p.Name)) {
|
||||
case "private internet access":
|
||||
settingsList = append(settingsList,
|
||||
@@ -73,12 +84,12 @@ func (p *ProviderSettings) String() string {
|
||||
"Country: "+p.ServerSelection.Country,
|
||||
"City: "+p.ServerSelection.City,
|
||||
"ISP: "+p.ServerSelection.ISP,
|
||||
"Custom port: "+string(p.ServerSelection.CustomPort),
|
||||
"Custom port: "+customPort,
|
||||
)
|
||||
case "windscribe":
|
||||
settingsList = append(settingsList,
|
||||
"Region: "+p.ServerSelection.Region,
|
||||
"Custom port: "+string(p.ServerSelection.CustomPort),
|
||||
"Custom port: "+customPort,
|
||||
)
|
||||
case "surfshark":
|
||||
settingsList = append(settingsList,
|
||||
@@ -94,6 +105,15 @@ func (p *ProviderSettings) String() string {
|
||||
settingsList = append(settingsList,
|
||||
"Region: "+p.ServerSelection.Region,
|
||||
)
|
||||
case "nordvpn":
|
||||
settingsList = append(settingsList,
|
||||
"Region: "+p.ServerSelection.Region,
|
||||
"Number: "+number,
|
||||
)
|
||||
default:
|
||||
settingsList = append(settingsList,
|
||||
"<Missing String method, please implement me!>",
|
||||
)
|
||||
}
|
||||
if p.ServerSelection.TargetIP != nil {
|
||||
settingsList = append(settingsList,
|
||||
|
||||
@@ -36,3 +36,11 @@ type VyprvpnServer struct {
|
||||
Region string
|
||||
IPs []net.IP
|
||||
}
|
||||
|
||||
type NordvpnServer struct { //nolint:maligned
|
||||
Region string
|
||||
Number uint16
|
||||
IP net.IP
|
||||
TCP bool
|
||||
UDP bool
|
||||
}
|
||||
|
||||
22
internal/params/nordvpn.go
Normal file
22
internal/params/nordvpn.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package params
|
||||
|
||||
import (
|
||||
libparams "github.com/qdm12/golibs/params"
|
||||
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
||||
)
|
||||
|
||||
// GetNordvpnRegion obtains the region (country) for the NordVPN server from the
|
||||
// environment variable REGION
|
||||
func (r *reader) GetNordvpnRegion() (region string, err error) {
|
||||
return r.envParams.GetValueIfInside("REGION", constants.NordvpnRegionChoices())
|
||||
}
|
||||
|
||||
// GetNordvpnRegion obtains the server number (optional) for the NordVPN server from the
|
||||
// environment variable SERVER_NUMBER
|
||||
func (r *reader) GetNordvpnNumber() (number uint16, err error) {
|
||||
n, err := r.envParams.GetEnvIntRange("SERVER_NUMBER", 0, 65535, libparams.Default("0"))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint16(n), nil
|
||||
}
|
||||
@@ -81,6 +81,10 @@ type Reader interface {
|
||||
// Vyprvpn getters
|
||||
GetVyprvpnRegion() (region string, err error)
|
||||
|
||||
// NordVPN getters
|
||||
GetNordvpnRegion() (region string, err error)
|
||||
GetNordvpnNumber() (number uint16, err error)
|
||||
|
||||
// Shadowsocks getters
|
||||
GetShadowSocks() (activated bool, err error)
|
||||
GetShadowSocksLog() (activated bool, err error)
|
||||
@@ -123,7 +127,7 @@ func NewReader(logger logging.Logger, fileManager files.FileManager) Reader {
|
||||
|
||||
// GetVPNSP obtains the VPN service provider to use from the environment variable VPNSP
|
||||
func (r *reader) GetVPNSP() (vpnServiceProvider models.VPNProvider, err error) {
|
||||
s, err := r.envParams.GetValueIfInside("VPNSP", []string{"pia", "private internet access", "mullvad", "windscribe", "surfshark", "cyberghost", "vyprvpn"})
|
||||
s, err := r.envParams.GetValueIfInside("VPNSP", []string{"pia", "private internet access", "mullvad", "windscribe", "surfshark", "cyberghost", "vyprvpn", "nordvpn"})
|
||||
if s == "pia" {
|
||||
s = "private internet access"
|
||||
}
|
||||
|
||||
153
internal/provider/nordvpn.go
Normal file
153
internal/provider/nordvpn.go
Normal file
@@ -0,0 +1,153 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/qdm12/golibs/network"
|
||||
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
||||
"github.com/qdm12/private-internet-access-docker/internal/models"
|
||||
)
|
||||
|
||||
type nordvpn struct{}
|
||||
|
||||
func newNordvpn() *nordvpn {
|
||||
return &nordvpn{}
|
||||
}
|
||||
|
||||
func findServers(selection models.ServerSelection) (servers []models.NordvpnServer) {
|
||||
for _, server := range constants.NordvpnServers() {
|
||||
if strings.EqualFold(server.Region, selection.Region) {
|
||||
if (selection.Protocol == constants.TCP && !server.TCP) || (selection.Protocol == constants.UDP && !server.UDP) {
|
||||
continue
|
||||
}
|
||||
if selection.Number > 0 && server.Number == selection.Number {
|
||||
return []models.NordvpnServer{server}
|
||||
}
|
||||
servers = append(servers, server)
|
||||
}
|
||||
}
|
||||
return servers
|
||||
}
|
||||
|
||||
func extractIPsFromServers(servers []models.NordvpnServer) (ips []net.IP) {
|
||||
ips = make([]net.IP, len(servers))
|
||||
for i := range servers {
|
||||
ips[i] = servers[i].IP
|
||||
}
|
||||
return ips
|
||||
}
|
||||
|
||||
func targetIPInIps(targetIP net.IP, ips []net.IP) error {
|
||||
for i := range ips {
|
||||
if targetIP.Equal(ips[i]) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
ipsString := make([]string, len(ips))
|
||||
for i := range ips {
|
||||
ipsString[i] = ips[i].String()
|
||||
}
|
||||
return fmt.Errorf("target IP address %s not found in IP addresses %s", targetIP, strings.Join(ipsString, ", "))
|
||||
}
|
||||
|
||||
func (n *nordvpn) GetOpenVPNConnections(selection models.ServerSelection) (connections []models.OpenVPNConnection, err error) { //nolint:dupl
|
||||
servers := findServers(selection)
|
||||
ips := extractIPsFromServers(servers)
|
||||
if len(ips) == 0 {
|
||||
if selection.Number > 0 {
|
||||
return nil, fmt.Errorf("no IP found for region %q, protocol %s and number %d", selection.Region, selection.Protocol, selection.Number)
|
||||
}
|
||||
return nil, fmt.Errorf("no IP found for region %q, protocol %s", selection.Region, selection.Protocol)
|
||||
}
|
||||
var IP net.IP
|
||||
if selection.TargetIP != nil {
|
||||
if err := targetIPInIps(selection.TargetIP, ips); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
IP = selection.TargetIP
|
||||
} else {
|
||||
IP = ips[0]
|
||||
}
|
||||
var port uint16
|
||||
switch {
|
||||
case selection.Protocol == constants.UDP:
|
||||
port = 1194
|
||||
case selection.Protocol == constants.TCP:
|
||||
port = 443
|
||||
default:
|
||||
return nil, fmt.Errorf("protocol %q is unknown", selection.Protocol)
|
||||
}
|
||||
return []models.OpenVPNConnection{{IP: IP, Port: port, Protocol: selection.Protocol}}, nil
|
||||
}
|
||||
|
||||
func (n *nordvpn) BuildConf(connections []models.OpenVPNConnection, verbosity, uid, gid int, root bool, cipher, auth string, extras models.ExtraConfigOptions) (lines []string) { //nolint:dupl
|
||||
if len(cipher) == 0 {
|
||||
cipher = aes256cbc
|
||||
}
|
||||
if len(auth) == 0 {
|
||||
auth = "sha512"
|
||||
}
|
||||
lines = []string{
|
||||
"client",
|
||||
"dev tun",
|
||||
"nobind",
|
||||
"persist-key",
|
||||
"remote-cert-tls server",
|
||||
|
||||
// Nordvpn specific
|
||||
"resolv-retry infinite",
|
||||
"tun-mtu 1500",
|
||||
"tun-mtu-extra 32",
|
||||
"mssfix 1450",
|
||||
"ping 15",
|
||||
"ping-restart 0",
|
||||
"ping-timer-rem",
|
||||
"reneg-sec 0",
|
||||
"comp-lzo no",
|
||||
"fast-io",
|
||||
"key-direction 1",
|
||||
|
||||
// Added constant values
|
||||
"auth-nocache",
|
||||
"mute-replay-warnings",
|
||||
"pull-filter ignore \"auth-token\"", // prevent auth failed loops
|
||||
"auth-retry nointeract",
|
||||
"remote-random",
|
||||
"suppress-timestamps",
|
||||
|
||||
// Modified variables
|
||||
fmt.Sprintf("verb %d", verbosity),
|
||||
fmt.Sprintf("auth-user-pass %s", constants.OpenVPNAuthConf),
|
||||
fmt.Sprintf("proto %s", string(connections[0].Protocol)),
|
||||
fmt.Sprintf("cipher %s", cipher),
|
||||
fmt.Sprintf("auth %s", auth),
|
||||
}
|
||||
if !root {
|
||||
lines = append(lines, "user nonrootuser")
|
||||
}
|
||||
for _, connection := range connections {
|
||||
lines = append(lines, fmt.Sprintf("remote %s %d", connection.IP.String(), connection.Port))
|
||||
}
|
||||
lines = append(lines, []string{
|
||||
"<ca>",
|
||||
"-----BEGIN CERTIFICATE-----",
|
||||
constants.NordvpnCertificate,
|
||||
"-----END CERTIFICATE-----",
|
||||
"</ca>",
|
||||
}...)
|
||||
lines = append(lines, []string{
|
||||
"<tls-auth>",
|
||||
"-----BEGIN OpenVPN Static key V1-----",
|
||||
constants.NordvpnOpenvpnStaticKeyV1,
|
||||
"-----END OpenVPN Static key V1-----",
|
||||
"</tls-auth>",
|
||||
"",
|
||||
}...)
|
||||
return lines
|
||||
}
|
||||
|
||||
func (n *nordvpn) GetPortForward(client network.Client) (port uint16, err error) {
|
||||
panic("port forwarding is not supported for nordvpn")
|
||||
}
|
||||
@@ -27,6 +27,8 @@ func New(provider models.VPNProvider) Provider {
|
||||
return newCyberghost()
|
||||
case constants.Vyprvpn:
|
||||
return newVyprvpn()
|
||||
case constants.Nordvpn:
|
||||
return newNordvpn()
|
||||
default:
|
||||
return nil // should never occur
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ func newSurfshark() *surfshark {
|
||||
return &surfshark{}
|
||||
}
|
||||
|
||||
func (s *surfshark) GetOpenVPNConnections(selection models.ServerSelection) (connections []models.OpenVPNConnection, err error) {
|
||||
func (s *surfshark) GetOpenVPNConnections(selection models.ServerSelection) (connections []models.OpenVPNConnection, err error) { //nolint:dupl
|
||||
var IPs []net.IP
|
||||
for _, server := range constants.SurfsharkServers() {
|
||||
if strings.EqualFold(server.Region, selection.Region) {
|
||||
@@ -54,7 +54,7 @@ func (s *surfshark) GetOpenVPNConnections(selection models.ServerSelection) (con
|
||||
return connections, nil
|
||||
}
|
||||
|
||||
func (s *surfshark) BuildConf(connections []models.OpenVPNConnection, verbosity, uid, gid int, root bool, cipher, auth string, extras models.ExtraConfigOptions) (lines []string) {
|
||||
func (s *surfshark) BuildConf(connections []models.OpenVPNConnection, verbosity, uid, gid int, root bool, cipher, auth string, extras models.ExtraConfigOptions) (lines []string) { //nolint:dupl
|
||||
if len(cipher) == 0 {
|
||||
cipher = aes256cbc
|
||||
}
|
||||
|
||||
@@ -64,6 +64,8 @@ func GetOpenVPNSettings(paramsReader params.Reader, vpnProvider models.VPNProvid
|
||||
settings.Provider, err = GetCyberghostSettings(paramsReader)
|
||||
case constants.Vyprvpn:
|
||||
settings.Provider, err = GetVyprvpnSettings(paramsReader)
|
||||
case constants.Nordvpn:
|
||||
settings.Provider, err = GetNordvpnSettings(paramsReader)
|
||||
default:
|
||||
err = fmt.Errorf("VPN service provider %q is not valid", vpnProvider)
|
||||
}
|
||||
|
||||
@@ -153,3 +153,25 @@ func GetVyprvpnSettings(paramsReader params.Reader) (settings models.ProviderSet
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
// GetNordvpnSettings obtains NordVPN settings from environment variables using the params package.
|
||||
func GetNordvpnSettings(paramsReader params.Reader) (settings models.ProviderSettings, err error) {
|
||||
settings.Name = constants.Nordvpn
|
||||
settings.ServerSelection.Protocol, err = paramsReader.GetNetworkProtocol()
|
||||
if err != nil {
|
||||
return settings, err
|
||||
}
|
||||
settings.ServerSelection.TargetIP, err = paramsReader.GetTargetIP()
|
||||
if err != nil {
|
||||
return settings, err
|
||||
}
|
||||
settings.ServerSelection.Region, err = paramsReader.GetNordvpnRegion()
|
||||
if err != nil {
|
||||
return settings, err
|
||||
}
|
||||
settings.ServerSelection.Number, err = paramsReader.GetNordvpnNumber()
|
||||
if err != nil {
|
||||
return settings, err
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user