Nord: an unofficial NordVPN client for GNU/Linux¶
Nord is a client for interacting with the NordVPN service.
At its core is a high-level Python API for interacting both with the web service provided by NordVPN, and for connecting to VPN servers using OpenVPN.
Nord also contains components that expose this API as a command line tool, and (soon) as a web service and frontend.
Overview¶
Nord is a client for interacting with the NordVPN service.
At its core is a high-level Python API for interacting both with the web service provided by NordVPN, and for connecting to VPN servers using OpenVPN.
Nord also contains components that expose this API as a command line tool, and (soon) as a web service and frontend.
Licence¶
Nord is licensed under the terms of the GNU GPLv3. See the LICENSE file for details.
The file web/static/world.geo.json
is Copyright (c) 2017 Richard Zimmerman
and is included here under the conditions of the MIT License
Installation¶
pip install nord
Usage¶
Run nord --help
for the full usage instructions.
Connect to a specific NordVPN server:
nord connect -u my_user -p my_password us893
Connect to any NordVPN server in a given country:
nord connect -u my_user -p my_password US
Serve a web app that allows you to select the country to which you wish to connect:
nord web -u my_user -p my_password
You can also supply your password from a file using the -f
flag.
The special value -
means “read from stdin”. This is particularly
useful when your password is stored in a utility such as
pass:
pass nordvpn_password | nord connect -u my_user -f - us893
Prerequesites¶
GNU/Linux system
Python 3.6
openvpn
sudo
nord contains many Linux-isms (e.g. using the sudo
program to obtain root
access) so it will certainly not work on Windows, it may possibly work
on OSX and *BSD, but support for these platforms is not a goal.
Most recent versions of popular GNU/Linux distributions (with the exception of Debian) have both an OpenVPN client and Python 3.6 in their official repositories. Debian users will have to take additional steps to get a Python 3.6 installation.
Ubuntu 16.10 and newer¶
Ubuntu comes with sudo
already installed, so we just need
to install Python and openVPN:
sudo apt-get install python3.6 openvpn
Fedora 26 and newer¶
Fedora comes with sudo
already installed, so we just need
to install Python and openVPN:
sudo dnf install python36 openvpn
Arch Linux¶
Run the following as root:
pacman -S sudo python openvpn
Then configure sudo
by following the Arch wiki
to give privileges to the user that nord will be running as.
Debian¶
First run the following as root to install the openVPN client and
sudo
from the Debian repositories:
apt install sudo openvpn
Then configure sudo
by following the Debian wiki
to give privileges to the user that nord will be running as.
There are a couple of options for installing Python3.6 on Debian:
Installing from the
unstable
repositoriesInstalling from source (easier than you might think
Both of these methods are explained in top-rated answers to this stackexchange question.
Developing¶
You will need Python 3.6 and Yarn (for the web components).
git clone https://github.com/jbweston/nord
cd nord
virtualenv -p python3.6
source venv/bin/activate
pip install -e .[dev]
yarn install
Periodically check your code with the linter:
pylint nord
Web components¶
When developing the web frontend you can execute the following command to run an auto-reloading web server:
yarn dev
Building the API documentation¶
make -C docs html
xdg-open docs/build/html/index.html
Changelog¶
v0.3.0¶
Implement Web frontend for interacting with Nord VPN servers
Fix a bug where an exception would be raised when incorrect credentials are provided to the CLI
v0.2.0 | 2018-02-01¶
Improve help messages in CLI
Add API method to rank hosts by availability
CLI accepts country code and selects best host automatically
Connect to Nord API via HTTPS
Reduce refresh period for sudo credentials to 30 seconds
Add changelog to docs
v0.1.0 | 2017-09-09¶
First publically released version
Python API + command line client
API documentation¶
nord.api
¶
Interface to the NordVPN web API.
This module contains a single class, Client, which encapsulates all the methods provided by NordVPN.
-
class
nord.api.
Client
(api_url='https://api.nordvpn.com/')[source]¶ Interface to the NordVPN web API.
Instances of this class can be used as async context managers to auto-close the session with the Nord API on exit.
- Parameters
api_url (str, default: ‘https://api.nordvpn.com’) –
-
async
host_config
(host, protocol='tcp')[source]¶ Return the OpenVPN config file contents for a NordVPN host.
- Parameters
host (str) – This hostname may be provided either with or without the trailing ‘.nordvpn.com’.
protocol (str, 'tcp' or 'udp') –
-
async
host_info
()[source]¶ Return detailed information about all hosts.
- Returns
host_info – A map from hostnames to host info dictionaries.
- Return type
(dict: str → dict)
-
async
host_load
(host=None)[source]¶ Return the load on a NordVPN host.
- Parameters
host (str, optional) – This hostname may be provided either with or without the trailing ‘.nordvpn.com’. If not provided, get the load on all NordVPN hosts.
- Returns
load – If ‘host’ was provided, returns the load on the host as a percentage, otherwise returns a map from hostname to percentage load.
- Return type
int or (dict: str → int)
-
async
rank_hosts
(country_code, max_load=70, ping_timeout=1)[source]¶ Return hosts ranked by their suitability.
First, all the NordVPN hosts are filtered to get a list of candidates, then the round-trip time is calculated using ‘ping’, then the candidates are sorted according to some scoring function.
The initial filtering is done based on the country where the host is, and the max.
- Parameters
country_code (str) – 2-letter country code (e.g. US for United States).
max_load (int, default: 70) – An integer between 0 and 100. Hosts with a load greater than this are filtered out.
ping_timeout (int) – Each host will be pinged for this amount of time. Larger values yield more accurate round-trip times.
- Returns
hosts – Fully qualified domain names of valid hosts, sorted by their rank.
- Return type
list of str
-
async
valid_credentials
(username, password)[source]¶ Return True if NordVPN accepts the username and password.
Sometimes connecting to the VPN server gives an authentication error even if the correct credentials are given. This function is useful to first verify credentials so as to avoid unecessary reconnection attempts.
- Parameters
password (username,) –
nord.vpn
¶
Tools for starting and supervising OpenVPN clients.
-
async
nord.vpn.
run
(config, username, password, dns_servers=())[source]¶ Run an OpenVPN client until it dies and return the exit code.
Optionally provide DNS servers that will replace the contents of ‘/etc/resolv.conf’ for the duration of the client.
- Parameters
config (str) – The contents of the OpenVPN config file.
password (username,) – Credentials for the OpenVPN connection.
dns_servers (tuple of str, optional) – IP addresses of DNS servers with which to populate ‘/etc/resolv.conv’ when the VPN is up.
-
async
nord.vpn.
start
(config, username, password)[source]¶ Start an OpenVPN client with the given configuration.
- Parameters
config (str) – The contents of the OpenVPN config file.
password (username,) – Credentials for the OpenVPN connection.
- Returns
proc
- Return type
asyncio.subprocess.Process
- Raises
PermissionError if we cannot use 'sudo' without a password. –
OpenVPNError if the OpenVPN process does not start correctly. –
LockError if a lock could not be obtained for the lockfile. –
Notes
Obtains a lock on a global lockfile before launching an OpenVPN client in a subprocess. The lock is released when the process dies.
-
async
nord.vpn.
supervise
(proc)[source]¶ Supervise a process.
This coroutine supervises a process and writes its stdout to a logger until it dies, or until the coroutine is cancelled, when the process will be killed.
- Parameters
proc (asyncio.subprocess.Process) –
- Returns
returncode – ‘proc.returncode’.
- Return type
int
-
async
nord.vpn.
supervise_with_context
(proc, dns_servers=())[source]¶ Supervise an OpenVPN client until it dies and return the exit code.
Optionally provide DNS servers that will replace the contents of ‘/etc/resolv.conf’ for the duration of the client.
- Parameters
proc (asyncio.Task) – The OpenVPN process to supervise
dns_servers (tuple of str, optional) – IP addresses of DNS servers with which to populate ‘/etc/resolv.conv’ when the VPN is up.
nord.web
¶
Serve nord as a web app.
The API can be accessed by opening a websocket connection to ‘/api’.
Requests¶
The API accepts 2 types of request.
Connect¶
A request to connect to a server in the provided country. Countries are specified as case-insensitive ISO alpha-2 codes. An example request is:
{
"method" : "connect",
"country" : "NL"
}
Disconnect¶
A request to disconnect the current OpenVPN connection. An example request is:
{
"method" : "disconnect"
}
Responses¶
Connecting¶
After receiving a “connect” request, the API will send a message to all connected peers with the following example format:
{
"state" : "connecting",
"country" : "nl",
}
Connected¶
When an OpenVPN connection is established, the API will send a message to all connected peers with the following example format:
{
"state" : "connected",
"host" : "nl123.nordvpn.com"
}
Disconnecting¶
After receiving a “disconnect” request, the API will send a message to all connected peers with the following example format:
{
"state" : "disconnecting"
}
Disconnected¶
When an OpenVPN connection is established, the API will send a message to all connected peers with the following example format:
{
"state" : "disconnected"
}
Error
If there was some error on the server side the API will send a message to all connected peers in the following example format:
{
"state" : "error",
"message" : "Something went wrong!"
}