A week ago, I illustrated a simple way to connect to the NordVPN server using Network Manager. Today I will describe a more advanced solution to automatically import NordVPN configuration using a shell script.

Preparations

Create /etc/nordvpn/config and /etc/nordvpn/certs directories.

$ sudo mkdir -p /etc/nordvpn/{config,certs}

Download OpenVPN configuration files and extract these files to /etc/nordvpn/config directory.

Download CA/TLS certificates and extract these files to /etc/nordvpn/certs directory.

Protect created directories by setting owner and permissions.

$ sudo chown -R root:root /etc/nordvpn
$ sudo chmod -R 600 /etc/nordvpn

Shell script

Save the following shell script as nordvpn-import.sh.

#!/bin/sh
# Import NordVPN https://nordvpn.com/ configuration files to Network Manager (Ubuntu)
#
# Parameters: country number [tcp|udp]
#
# Examples:
#   norvpn-import.sh de 3 
#   norvpn-import.sh de 2 tcp

# OpenVPN configuration files location
path_ovpn="/etc/nordvpn/config"

# CA/TLS certificates location
path_cert="/etc/nordvpn/certs"

# NordVPN username
username="milosz@example.org"

# function to generate config
generate_config(){
  server="$1"
  protocol="$2"
  address="$3"
  crt_file="$4"
  key_file="$5"
  username="$6"

  if test "$protocol" = "tcp"; then
    line_tcp="proto-tcp=yes"
    line_port="port=443"
  else
    line_tcp=""
    line_port=""
  fi

# the ugly part
cat << EOF 
[connection]
id=NordVPN $(echo $server |  awk -v FS="." '{print toupper($1)}') [${protocol}]
uuid=$(uuidgen)
type=vpn
permissions=
secondaries=

[vpn]
ta-dir=1
connection-type=password
password-flags=1
tunnel-mtu=1500
cipher=AES-256-CBC
comp-lzo=yes
remote=${address}
reneg-seconds=0
${line_tcp}
${line_port}
mssfix=yes
dev-type=tun
username=${username}
remote-cert-tls=server
ca=${crt_file}
dev=tun
ta=${key_file}
service-type=org.freedesktop.NetworkManager.openvpn

[ipv4]
dns-search=
method=auto

[ipv6]
dns-search=
ip6-privacy=0
method=auto
EOF
}

# this shell script requires root privileges
if ! test "$(whoami)" = "root"; then
  echo "This shell script requires root privileges"
  exit 1
fi

# this shell script requires network-manager-openvpn-gnome package
if ! dpkg-query -s network-manager-openvpn-gnome 1>/dev/null 2>&-; then
  echo "Please install network-manager-openvpn-gnome package"
  exit 1
fi

# parse parameters
if test "$#" -ge 2; then
  country="$1"
  number="$2"
  
  if test "$#" -eq "3"; then
    case "$3" in
      "tcp") type="tcp443" ;;
      "udp") type="udp1194" ;;
      *)     type=".*"   ;;
    esac
  else
    type=".*"
  fi
else
  echo "Parameters: $0 country number [tcp|udp]"
  echo "Example:    $0 de 3"
  echo "            $0 de 4 tcp"
  exit 1
fi
  
# main loop
for configuration in $(find "${path_ovpn}/" -maxdepth 1 -regex ".*/\(${country}\)\(${number}\).nordvpn.com.\(${type}\).ovpn"); do
  server="$(basename $configuration | awk -v FS="." '{print $1".nordvpn.com"}')"
  protocol="$(basename $configuration | sed "s/.*\.nordvpn\.com\.\(.*\)\(443\|1194\)\.ovpn/\1/")"
  address="$(cat $configuration | sed -ne "s/remote \([.0-9]*\) \(443\|1194\)*/\1/p")"
  crt_file="$path_cert/$(echo $server | tr "." "_")_ca.crt"
  key_file="$path_cert/$(echo $server | tr "." "_")_tls.key"

  output_file="/etc/NetworkManager/system-connections/nordvpn-${server}-${protocol}"

  if ! test -f "$output_file"; then
    generate_config "$server" "$protocol" "$address" "$crt_file" "$key_file" "$username" | tee "$output_file" 1>/dev/null
    echo "Imported $server [$protocol]" 
    chmod 600 "$output_file"
  fi
done

# reload Network Manager
nmcli connection reload

Change username variable to match NordVPN credentials.

Usage

Import UK server 18, tcp and udp.

$ sudo sh nordvpn-import.sh uk 18
Imported uk18.nordvpn.com [tcp]
Imported uk18.nordvpn.com [udp]

Import NL servers 9 and 12, tcp and udp.

$ sudo sh nordvpn-import.sh nl "9\|12"
Imported nl9.nordvpn.com [tcp]
Imported nl9.nordvpn.com [udp]
Imported nl12.nordvpn.com [tcp]
Imported nl12.nordvpn.com [udp]

Import all PL servers, tcp only.

$ sudo sh nordvpn-import.sh pl ".*" tcp
Imported pl3.nordvpn.com [tcp]
Imported pl5.nordvpn.com [tcp]
Imported pl6.nordvpn.com [tcp]

Import DE servers 1, 2, 3 and between 3039, udp only.

$ sudo sh nordvpn-import.sh de "1\|2\|3\|3[0-9]" udp
Imported de1.nordvpn.com [udp]
Imported de2.nordvpn.com [udp]
Imported de3.nordvpn.com [udp]
Imported de30.nordvpn.com [udp]
Imported de31.nordvpn.com [udp]
Imported de32.nordvpn.com [udp]
Imported de33.nordvpn.com [udp]
Imported de34.nordvpn.com [udp]
Imported de35.nordvpn.com [udp]
Imported de36.nordvpn.com [udp]
Imported de37.nordvpn.com [udp]
Imported de38.nordvpn.com [udp]
Imported de39.nordvpn.com [udp]

Import everything.

$ sudo sh nordvpn-import.sh ".*" ".*"
Imported at3.nordvpn.com [tcp]
Imported at3.nordvpn.com [udp]
Imported au1.nordvpn.com [tcp]
Imported au1.nordvpn.com [udp]
Imported au2.nordvpn.com [tcp]
Imported au2.nordvpn.com [udp]
Imported au3.nordvpn.com [tcp]
Imported au3.nordvpn.com [udp]
[...]

Source code is available in the NordVPN import repository.