Skip to content

Commit

Permalink
Nordvpn support (#189), fix #178
Browse files Browse the repository at this point in the history
  • Loading branch information
qdm12 authored Jul 15, 2020
1 parent 616ba0c commit 1281026
Show file tree
Hide file tree
Showing 15 changed files with 5,564 additions and 51 deletions.
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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" \
Expand All @@ -58,6 +58,8 @@ ENV VPNSP=pia \
PORT= \
# Cyberghost only
CYBERGHOST_GROUP="Premium UDP Europe" \
# NordVPN only
SERVER_NUMBER= \
# Openvpn
OPENVPN_CIPHER= \
OPENVPN_AUTH= \
Expand Down
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)*

Expand Down Expand Up @@ -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`
Expand Down Expand Up @@ -90,9 +93,9 @@
[![https://windscribe.com/?affid=mh7nyafu](https://raw.githubusercontent.com/qdm12/private-internet-access-docker/master/doc/windscribe.jpg)](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`
Expand All @@ -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)**

Expand All @@ -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 |
Expand Down Expand Up @@ -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

Expand Down
106 changes: 106 additions & 0 deletions cmd/mapper/main.go
Original file line number Diff line number Diff line change
@@ -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
}
47 changes: 11 additions & 36 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading

0 comments on commit 1281026

Please sign in to comment.