This note originates from an effort to find ways to automate OpenVPN and SSTP VPN connections from an Ubuntu 18.04 machine using CLI. For setting VPN connection from GUI, NetworkManager GNOME has nice third-party packages for most VPN protocols. Only follow this note if you want to setup OpenVPN or SSTP VPN connection from CLI.

OpenVPN has a nice CLI tool (i.e. openvpn). However, connecting to an SSTP VPN server using CLI (e.g., sstpc) could be problematic since it may involve some manual network setting tasks (e.g., changing the DNS nameserver of the local stub resolver in /etc/resolv.conf, adding and deleting route(s) from the routing table). Perhaps, you were redirected to this note from my previous effort to connect to an SSTP VPN server from CLI.

0. Prerequisites:

  • In order to follow steps in this note, you will need to have these packages installed in your Ubuntu 18.04 machine.

    sudo apt-get update &&
    sudo apt-get upgrade &&
    sudo add-apt-repository -y ppa:eivnaes/network-manager-sstp &&
    sudo apt-get update && sudo apt-get install -y network-manager &&
    sudo apt-get install -y openvpn sstp-client&&
    sudo apt-get install -y network-manager-openvpn network-manager-sstp &&
    sudo apt-get install -y network-manager-openvpn-gnome network-manager-sstp-gnome && # This line is only needed if you want a GUI in your NetworkManager.
    sudo apt-get update
    
  • For connecting to an OpenVPN server, you need to have a configuration .ovpn file, and sometimes authentication cert as well as login credentials. For connecting to an SSTP server, you need to know information about the server, including login credentials (i.e., username, password), server address (i.e., hostname or IP address), authentication protocol used by the server (e.g., MS-CHAP, etc..). The information is often provided to you by your VPN service provider.

  • IFF your VPN connection does not cover IPv6, make sure you disable IPv6 (if supported by your ISP). Otherwise, IPv6 leakage may ruin the whole purpose of using VPN. In case you are not sure whether your ISP provides you with an IPv6, you can visit this website: https://whatismyipaddress.com/. If you have an IPv6, it will be shown. Then, you can run these commands to disable IPv6 (if exists), and change 1 to 0 if you want to re-enable IPv6.

    sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
    sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
    

1. Adding an OpenVPN VPN connection:

Nowadays, most VPN providers support OpenVPN protocol. Often time, together with a username and a password, you will be provided with configuration files, including .ovpn files, a TLS Authentication .key file, and a ca.cert file. Thankfully, these files make adding OpenVPN connections to NetworkManager easier. Once you have all of these files together in the same directory, we can run the following command, from within that directory, to import an OpenVPN connection. Note that the <your_openvpn_file_name> will be treated as the connection.id of your OpenVPN connection. If you want to systematically manage many connections later, you may need to change the name of all .ovpn files in your desired format before adding them. In my opinion, the name of .ovpn files (if provided by a VPN provider) are often well-formatted already (e.g. Germany-Frankfurt-TCP.ovpn). And here is the command:

nmcli connection import type openvpn file <your_openvpn_file_name>.ovpn

This command will import all parameters needed to initiate the connection, except for the login credentials (i.e. username and password). Again, you can always open the NetworkManager GUI to add these credentials, but let me do it the hard way (i.e. adding them from nmcli). One may ask why we need to go the hard way. Lets imagine that we have hundreds of .ovpn files, and we want to add them all to NetworkManager, nmcli is our friend - not the GUI! In that case, you will just need to get the name of all .ovpn files, put them in the for clause, and run the command with for ...; do <the_above_command_>; done.

nmcli connection modify id <your_openvpn_connection_name> \
+vpn.data password-flags=0,username=<your_username> \
+vpn.secrets password=<your_password>

The above command will add the username and password to your VPN configuration.

In case your VPN provider uses user certificate, user private key, and user key password for authentication, you will need to run this command to instead.

nmcli connection modify id <your_openvpn_connection_name> \
+vpn.data cert-pass-flags=0 \
+vpn.secrets cert-pass=<your_cert_password>

You can check it in /etc/NetworkManager/system-connections/ directory. You should only add the password IFF you are the only user of the machine. If you share the machine, you may not want to add the last line. This way, you will be prompted to input the password every time you want to activate your connection. If you only need to add a OpenVPN connection, you can skip the next session, and jump to activating connection.

2. Adding an SSTP VPN connection:

The following command will add an SSTP VPN connection to your machine, managed by NetworkManager. In order to run this command, you need to replace all <...> with your own values. (1) <name_of_interface> can be found using ifconfig command. (2) <name_of_the_vpn_connection> can be any string value, e.g. My-SSTP-VPN. (3) <vpn_server_address> is given to you by the VPN service provider. It can be in the form of IP address or hostname. (4) <username> and <password> should also be provided to you by your VPN service provider.

1    nmcli connection add \
2    save yes \
3    type vpn \
4    connection.interface-name <name_of_interface> \
5    connection.id <name_of_the_vpn_connection> \
6    vpn.data gateway=<vpn_server_address>,ignore-cert-warn=yes,lcp-echo-failure=5,lcp-echo-interval=30,nobsdcomp=yes,nodeflate=yes,password-flags=0,proxy-password-flags=0,refuse-chap=yes,refuse-eap=yes,refuse-pap=yes,user=<username> \
7    vpn.secrets password=<password> \
8    vpn.service-type org.freedesktop.NetworkManager.sstp
9  

3. SSTP Command explanation:

You may ask how I could form this command. Of course! By reading the man page, and use the magical 'tab' autocompletion in the CLI environment of Ubuntu. Depend on the information about your SSTP server, you may need to tweak the parameters differently. To make it clear, I will briefly explain the purpose of each part of the command below.

  • L1: call the nmcli of NetworkManager with root privilege.
  • L2: save this connection into /etc/NetworkManager/system-connections
  • L3: define the type of this connection as vpn
  • L4: assign an interface for this connection, you can find the interface name by the ifconfig command. For clarity, I use connection.interface-name, but you can use ifname too. Also note that all connection in this command can be replace by con or c for short.
  • L5: connection.id is the name of the VPN connection you want to add. It can be any string value, e.g. My-SSTP-VPN. Note that it has to be unique among connections, if you have more than one connection. Otherwise, NetworkManager will append a long UUID to the end of the string to make it unique.
  • L6: here comes the information (data) about the VPN connection. The string following vpn.data comes in the form of dictionary <key>=<value>.
    • gateway is the address of the VPN server.
    • ignore-cert-warn=yes since my VPN provider does not provide any certificate to authenticate the server. Which I think VERY BAD for security.
    • lcp-echo-failure=5 and lcp-echo-interval=30 belong to pppd (see man pppd). The values 5 and 30 are standard for most systems. Note that the VPN connection is actually wrapped inside a pppd process. Therefore, your machine needs to have pppd, which comes built-in in most Ubuntu versions.
    • nobsdcomp=yes is similar with unchecking the box “Allow BSD data compression”, and nodeflate=yes is similar with unchecking the box “Allow Deflate data compression” on the GNOME GUI of NetworkManager.
    • password-flags=0 allows you to store the password into the configuration, and won’t ask you input it when activating the connection later. If you share the machine with other people, you many want to set the value to 1, and remove line 7. For more details, see nm-settings man page.
    • proxy-password-flags=0 means no proxy needed for this VPN connection.
    • refuse-chap=yes,refuse-eap=yes, and refuse-pap=yes force the authentication to use MSCHAP or MSCHAPv2 method. Having these three parameters is similar with unchecking three boxes: PAP, CHAP, and EAP in “SSTP Advanced Options” on the GNOME GUI of NetworkManager.
    • user=<username> is provided to you by your VPN provider.
  • L7: input your password here. ONLY add this line if you’re the only user of the machine. If you are sharing your machine, you should remove this line.
  • L8: define the vpn.service-type as sstp

Now, if you have more than one SSTP server that you want to add to NetworkManager, a for ...; do ...; done loop will do the trick. In my case, I have some hundreds of servers. Manually adding them from the GUI is definitely not an ideal way in which a CS guy should do. This is exactly one of the foremost reasons why I want to explore the NetworkManager’s nmcli. And here is an example of how your command should look like:

 1  for i in server_1 server_2 ... server_n; do \
 2  nmcli connection add \
 3  save yes \
 4  type vpn \
 5  connection.interface-name <name_of_interface> \
 6  connection.id $i \
 7  vpn.data gateway=$i,ignore-cert-warn=yes,lcp-echo-failure=5,lcp-echo-interval=30,nobsdcomp=yes,nodeflate=yes,password-flags=0,proxy-password-flags=0,refuse-chap=yes,refuse-eap=yes,refuse-pap=yes,user=<username> \
 8  vpn.secrets password=<password> \
 9  vpn.service-type org.freedesktop.NetworkManager.sstp; \
10  done

4. Activating a connection (same for both OpenVPN and SSTP VPN):

After executing the above command successfully, you should see a similar output to this one:

  Connection '<name_of_the_vpn_connection>' (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) successfully added.

You can also check the existence of your connection using nmcli connection. This command will show you all connections managed by NetworkManager. Now, we can start connecting to our VPN server using this command:

  nmcli con up id <name_of_the_vpn_connection> # you may need sudo depend on your account privilege.

If the command succeeds activating the VPN connection, you will see an output like this after a couple seconds:

  Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/<number>)

Similarly, when you want to turn off the VPN connection, replace up by down. When you want to remove the connection from NetworkManager, replace up by delete.

5. Troubleshooting:

If your machine couldn’t connect to the VPN server after all, you may want to make sure that:

  1. The SSTP server is online and accessible. Try 'ping'-ing it to check.
  2. The DNS stub resolver, which can be configured at /etc/resolv.conf, functions properly. Especially, if your VPN server is configured to be a hostname, there is some chance that your current DNS resolver couldn’t resolve its IP address. In that case, you may need to get the root privilege by sudo su, then echo 'nameserver 8.8.8.8' > /etc/resolv.conf to force the local stub resolver to use Google’s OpenDNS. You can also replace 8.8.8.8 with any OpenDNS servers that work in your network.
  3. Your NetworkManager is actually managing your machine’s physical interfaces. You may need to change the line managed=false to managed=true in /etc/NetworkManager/NetworkManager.conf. AskUbuntu has some tricks.
  4. Your machine is “refreshed”. While dealing with computer, it is sometimes weird and magical that things get fixed when we restart/reinstall the software/machine. Crossing my fingers!