Using ProtonVPN for Privacy and Security

Being a long-time user of OpenVPN and generally liking the security approach of ProtonMail I decided to take ProtonVPN for a test drive.  These are my experiences using their Linux CLI and a persistent systemd connection, Mac OSX briefly and IOS.  This Swiss-based VPN service provides a free tier and reasonably priced paid plans for more benefits.

 

Why Would I want a VPN?
This lifehacker article does a much better job of explaining this than me, but let me summarize the basics:

  • The internet is really aggressive, it helps you ensure all your traffic is encrypted and free from snooping or more malicious eavesdropping to steal your data.
  • You value your privacy and may not be able to trust all public networks
  • You are in a potentially oppressive country where it could be dangerous to use the internet due to censorship and/or retaliation against free speech.
  • The Netflix/some-other-web-service selection SUUUCKS from where you are traveling (or isn’t available).

What is ProtonVPN
ProtonVPN is an OpenVPN-based hosted service offered by the same folks who created ProtonMail (end-to-end encrypted email service) based in Switzerland.  You can use it via bog-standard OpenVPN client or use their multi-platform application (Windows, Mac OSX, Linux, Iphone IOS, Android).

Unlike a lot of other hosted VPN services their free tier is truly free with some reasonably imposed limits you’d expect (3 Country locations only for endpoints, more QoS’d speeds and only 1 connection at a time, no P2P traffic) but otherwise no bandwidth limitations that I was able to see.

Being a fan of Swiss-based companies like ProtonMail and pCloud already and being a fairly frequent traveler just running my own OpenVPN server from home doesn’t always suffice due to my location(s) so I decided to take ProtonVPN for a test drive.

This is a personal review of ProtonVPN’s hosted OpenVPN solution, nothing stops you from running your own DIY OpenVPN service on your home system for both privacy/security as well as access to home network resources which isn’t covered here.

Installation on Linux
After making an account you can download the Linux CLI client or simply integrate the settings (obtained on your account page) into OpenVPN using NetworkManager/nmcli or just use the normal openvpn command(s) if you’re used to those.

To try something different I’m going to cover using the official ProtonVPN Linux CLI tool.  As of typing this their instructions page (and staff responses to questions/comments) is full of more info than this post hopes to cover so that’s worth a look.  You should also consult that page for options beyond installation and configuration that we’ll cover here.

Note: Your ProtonVPN username/password is NOT for the Linux CLI tool, it’s for the other official GUI applications (OSX, Windows, IOS, Android).  The credentials you’ll be using shortly will instead be the same as the ones you’d use in OpenVPN.

As you can see above this is spelled out pretty well in the account screen but I managed to screw it up by not really checking as I was trying to setup the client where it asks for your login credentials.

Note: I am running the below commands as the root user, it is possible to instead use your local non-privileged user instead by passing environment variables into the Systemd service being setup (see comments on this post that reader @cohen has provided if you want to do this).

Update 2020-09-29

The official Python-based ProtonVPN CLI is now available as a package from most Linux distributions

dnf install -y protonvpn-cli

See the official, supported ProtonVPN CLI Github here for installation steps.

If your system has Python 3.6 or higher and OpenVPN 2.4 or higher then you can stop here and use the official Github instructions and your respective distribution package of protonvpn-cli above.

I am leaving the below steps in place in case you’re running an older version of Python (Python 3.4 and below is not supported).

I’ve applied a small patch to the old shell-based ProtonVPN CLI client that will also support OpenVPN versions 2.3 and older as well.

Download the CLI Tool (Legacy, only for older systems <= Python 3.4)
First download the CLI tool, I have patched a forked copy of their old CLI utility that might be helpful for folks that don’t have Python 3.4 or greater which is required.

git clone https://github.com/sadsfae/protonvpn-cli

Install OpenVPN (Legacy, only for older systems <= Python 3.4)
You’re also going to need openvpn and dialog, I’ll leave that up to you as to how to install it.  For me on Fedora it was simply:

dnf install openvpn dialog -y

Run the Setup
Next you’re going to run the CLI setup which will generate certificates/keys, add your username/password (OpenVPN credentials from above) to a static file where it can be fed into openvpn and setup some local configuration values.  I did all this as the root user and kept it in roots home directory.

cd protonvpn-cli/

./protonvpn-cli.sh -init

Note:  On EL-based distributions (CentOS, RHEL, Fedora) there is no resolvconf package available, that’s ok – it’s been changed to a bash function that is integrated when you choose Y during the installation questions.  All it does is provide a way for protonvpn-cli to update your DNS servers anyway.

# ./protonvpn-cli.sh -init
[!] Error: 
update-resolv-conf is not installed.
Would you like 
protonvpn-cli to install update-resolv-conf? (y/N): y

If all goes well you should now be prompted with the setup part.  Use your OpenVPN credentials above and for the free account choose option 1 here.

Enter OpenVPN username: testuser 

Enter OpenVPN password: 

[.] ProtonVPN Plans:

1) Free

2) Basic

3) Plus

4) Visionary

Enter 

Your ProtonVPN plan ID: 1

It will ask you if you want to use a custom DNS server, I chose yes here because I’m using Pi-hole as my DNS server at home for further privacy and security.  You should go with the defaults here unless you’re doing something purposefully different.

Lastly it will prompt you if you want to decrease OpenVPN privileges, this sounds like a good thing to enable.  I chose Y here (default).  It demotes the openvpn service user to the nobody user.

Connecting to ProtonVPN with Linux CLI
Now you should be ready to connect to ProtonVPN via the CLI to test things out.

./protonvpn-cli -c

You’ll be prompted with a list of servers to connect to and then protocol (udp/tcp).  Once that proceeds you should be connected.

Connecting...
[$] 
Connected!
[#] 
New IP: 185.244.XXX.XX

Great, if all goes well you can install symlinks to /usr/local/bin/pvpn which we’ll use for setting up a persistent, service-based connection.

protonvpn-cli/protonvpn-cli.sh --install

Now you should have a pvpn binary (symlink) in your $PATH.

# ls -ln /usr/local/bin/pvpn

lrwxrwxrwx. 1 0 0 28 Dec 27 12:52 /usr/local/bin/pvpn -> /usr/local/bin/protonvpn-cli



# which pvpn

/usr/local/bin/pvpn

Setting up a Persistent ProtonVPN Service
Nothing stops you from just using good old NetworkManager or nmcli or even the regular openvpn command line but I like the idea of using systemd to provide connection persistence.  The ProtonVPN CLI also provides the -f option which chooses the fastest connection to you.

This can be done in a few easy steps, first create the systemd service itself:

cat > /etc/systemd/system/protonvpn.service <<EOF

[Unit]

Description=ProtonVPN

After=syslog.target network-online.target

Wants=network-online.target



[Service]

Type=forking

ExecStart=/usr/bin/pvpn -f

ExecStop=/usr/bin/pvpn -d

ExecReload=/usr/bin/pvpn -f

Restart=always



[Install]

WantedBy=multi-user.target


EOF

Now issue a daemon reload

systemctl daemon-reload

Now you can either set the service to start automatically on boot as you choose (via systemctl enable protonvpn) or simply on-demand.  The above Restart=always should ensure that if it fails it’ll get restarted automatically.

Let’s start it and see what happens.

systemctl start protonvpn

systemctl status protonvpn

All looks good.

● protonvpn.service - ProtonVPN
Loaded: loaded (/etc/systemd/system/protonvpn.service; 
disabled; vendor preset: disabled)
Active: active (running) since 
Thu 2018-12-27 13:00:58 GMT; 14s ago
Process: 3753 
ExecStart=/usr/bin/pvpn -f (code=exited, status=0/SUCCESS)
Main PID: 3890 
(openvpn)
CGroup: /system.slice/protonvpn.service
└─3890 openvpn --daemon 
--config /root/.protonvpn-cli/protonvpn_openvpn
Dec 27 13:00:50 host-01 
systemd[1]: Starting ProtonVPN...

Dec 27 13:00:50 host-01 pvpn[3753]: Fetching ProtonVPN servers...

Dec 27 13:00:52 host-01 pvpn[3753]: Connecting...

Dec 27 13:00:58 host-01 pvpn[3753]: [$] Connected!

Dec 27 13:00:58 host-01 pvpn[3753]: 
[#] New IP: 89.XX.XXX.XXX

Cool, Let’s Break It!
Ok, let’s manually kill the openvpn process and see if it restarts itself.

# ps -ef | grep openvpn 

nobody 3890 1 0 13:00 ? 00:00:00 openvpn --daemon --config

Now let’s abruptly kill the openvpn PID.

# kill 3890

# systemctl status protonvpn

Now we see a new IP address (you’ll have to trust me on this) as well as new connection log timestamps indicating a reconnection.

Dec 27 13:02:19 host-01 systemd[1]: Starting ProtonVPN...

Dec 27 13:02:20 host-01 pvpn[4110]: Fetching ProtonVPN servers...

Dec 27 13:02:21 host-01 pvpn[4110]: Connecting...

Dec 27 13:02:27 host-01 pvpn[4110]: [$] Connected!

Dec 27 13:02:27 host-01 pvpn[4110]: [#] New IP: 89.XX.XXX.XXX

Great, everything restarted as it should.  This would be especially useful for an always-connected machine but also useful if you just wanted connection persistence in general.

First Impressions
The free tier account is suitable enough for having a reliable VPN connection in a pinch, I didn’t see anything wrong speed-wise though when downloading things I was noticeably throttled.  If privacy is your primary concern and you don’t intend to push any P2P traffic this is probably fine.

I was able to stay connected for several days or longer without disconnection issues which prompted me to just spring for the basic plan for $48/year.  I like the service, I like ProtonMail prior to that and I want to support them.  It was also worth it to me to have access to such a large range of VPN servers spread across the world so that pvpn -f would indeed find the best endpoint closest to me, especially if I was out of the country.

Speed and Traffic
For comparison purposes using the speedtest-cli Python program available via pip here are some test numbers before and after on a CentOS7 VM.

I am providing my setup instructions here for posterity:

yum install python-pip python-virtualenv -y

virtualenv speedtest

cd speedtest/bin

source activate

pip install speedtest-cli

Testing Regular Connection Speed
This is simply running speedtest without being connected to ProtonVPN

# speedtest-cli 

Retrieving speedtest.net configuration...

Testing from Virgin Media Ireland (79.XX.XXX.XXX)...

Retrieving speedtest.net server list...
Selecting best server based on ping...

Hosted by IP Telecom (Dublin) [1.78 km]: 16.305 ms

Testing download speed.............................................

Download: 184.26 Mbit/s

Testing upload speed...............................................

Upload: 24.47 Mbit/s

Testing ProtonVPN Connection Speed
This is after I’ve connected to ProtonVPN from the fastest endpoint, for some reason it wanted to use the Amsterdam speedtest servers.  Ok then:

# speedtest-cli 

Retrieving speedtest.net configuration...

Testing from WorldStream B.V. (89.XX.XXX.XXX)...

Retrieving speedtest.net server list...

Selecting best server based on ping...

Hosted by Tele2 Netherlands B.V. (Amsterdam) [1.75 km]: 50.135 ms

Testing download speed.............................................

Download: 83.63 Mbit/s

Testing upload speed...............................................

Upload: 23.74 Mbit/s

Testing P2P Traffic
For P2p traffic I downloaded some Fedora and CentOS ISO’s on a test VM using an in-country VPN endpoint and saw between 3.3 to 4.1 MB/s (26.4 to 32.8 megabits) where I’d normally see 9 to 11 MB/s (72 to 88 megabits/sec).  There is some VM overhead there I am sure also.

For more exhaustive speed testing between the free versus plus plan see the following thread on Reddit.

NOTE: P2P traffic is allowed only on servers from Netherlands, Singapore and Sweden, so for example you would want to use the following pvpn command in your systemd service file instead of /usr/bin/pvpn -f where NL#1 is the server that allows P2P traffic from the Netherlands for example.

ExecStart=/usr/bin/pvpn -c NL#1
ExecReload=/usr/bin/pvpn -c NL#1

After the above changes to /etc/systemd/system/protonvpn.service you’ll want to reload your unit file.

systemctl daemon-reload

There are a lot of legitimate purposes for using P2P protocols like bittorrent and I do not condone using P2P traffic for anything that might be illegal in your country as it pertains to digital copyright, consult the laws in your country.

Testing DNS Leaking
A potential chink in the armor of any VPN service is what DNS services you are using.  While all of your transport traffic is encrypted and hidden your actual DNS queries may be leaking.  ProtonVPN provides secure, private DNS servers for your connections that do not leak your DNS queries.  This is the default unless you changed it.

You can test this via visiting a site like DNS Leak Test.

When I am at home I am using Pi-hole for my local DNS anyways for the additional filtering and ad-blocking but I always use the ProtonVPN DNS server defaults when connecting abroad or while traveling and all tests I’ve done show that no DNS queries are leaked.

ProtonVPN on Mac OSX
I have an older personal Macbook Air 11″ that I use for travel sometimes as it’s super lightweight.  Setting up ProtonVPN on OSX was straightforward.  One humorous thing to note is it looks like one of those futuristic Hollywood “hacker” programs.  “I’m in!”

Once connected to the ProtonVPN.

ProtonVPN on IOS
I briefly installed and used the ProtonVPN service on an Iphone.  The native application worked great, integrated into the innate IOS VPN settings and everything was responsive and easy to use.  I didn’t do any further testing past this.

Other Privacy Features: Secure Core and TOR
One feature that I did not try out as it’s only available in the Plus and beyond plans is the secure core feature.  This obfuscates your ingress connection into any of the VPN endpoints making it very difficult for things like a correlation attack.  There’s a full explanation of the service here and the benefits.

Other plans beyond basic also support TOR (onion routing) through ProtonVPN’s own TOR servers.  You can read more about this here.

Summary
There are lots and lots of VPN providers out there with many, many countries and endpoints to choose from.  ProtonVPN sticks out because their free tier is really free (though understandably limited).  They also support bitcoin for payment which is cool.

I believe you could find better speeds if you shopped around, but I also like the security focus of ProtonVPN/ProtonMail and the speeds for me are good enough (encryption overhead is encryption overhead) that I’m happy supporting them via the basic plan however your mileage may vary.

I’m glad they seem to be actively developing their Linux CLI, and the other official applications I’ve tried appear polished and easy-to-use.  One small nitpick on the Linux CLI is that without the systemd service approach there is no persistent connection option, though there’s a Github issue for this.

Lastly, the username and password is kept in cleartext on the system.  This could probably be salted/hashed somewhere but the CLI is still relatively new (it’s a shell script) and seems to be garnering a lot of improvement quickly.  The counter argument you can make here is if someone has access to this you have bigger problems than someone borrowing your ProtonVPN (OpenVPN only) credentials.

Update: 2019-02
It’s been over a month since I’ve been running ProtonVPN persistently via the systemd service and I have had no issues.  Disconnections, while rare, are reconnected automatically as expected.

About Will Foster

hobo devop/sysadmin/SRE
This entry was posted in open source, sysadmin and tagged , , , , , , , , . Bookmark the permalink.

10 Responses to Using ProtonVPN for Privacy and Security

  1. Shippy says:

    Good review but there are too many confusing VPN reviews out there !

    How about doing a smartDNS services review including DIY, since not many out there. SmartDNS is getting lot interesting given perceptions as below:

    1. VPNs give you privacy while smartDNS unlocks multiple geo locations at once.

    2. VPN DIY servers would be paying much for streaming user bandwidth unless using a cheapo VPS like Hetzner.

    SmartDNS servers don’t pass through user traffic so this could be a big savings (is this true?)

    3. Older computers (10+ years) without CPU AES encryption will slow down your throughout considerably with VPNs.
    No issue with smartDNS.

    4. With a fortuitous combination of smartDNS, DNS adblock and the recent DoH/DoT w. TLS1.3 for privacy, you might have the perfect combo without the downsides.

    Like

    • Will Foster says:

      Hey Shippy. I can see how folks needing to get around geo-blocked content as a primary goal might not need the overhead of an entire VPN connection. Probably this is a good use case for smartDNS. In my uses smartDNS and a VPN service solve different problems in that VPN (in this case provided by ProtonVPN) has the side effect of working around geo-blocked content but its primary goal is securing my data in-transit end to end, what I’m happy to pay for is the plethora of regional servers to do it through though I’m happy running OpenVPN myself as well – I’m just limited to where I’d have a VPS or at home.

      On #2 – As I read it your data still traverses through a third party / intermediary but one located in an acceptable region to intercept and re-route otherwise blocked content. I don’t see a compelling cost or bandwidth reason here in that regard except there wouldn’t be any encryption overhead which might really make a difference streaming 4K+ content (but also lack any privacy/security benefits). As I reviewed ProtonVPN in this regard there is no bandwith limiting even in their free account which is entirely free.

      On #3 – I don’t see encryption overhead (offloaded in software) as a huge deal nowadays, even low-power MIPS processors found in older home routers have OpenVPN clients with the right open source firmware that let you put your entire home network on a VPN if you really wanted to. Surely there’s a performance hit but I’d take a wild guess to say anything so old that’d it would be crippling you’d probably have retired it as a device anyway. Who knows though.

      On #4 – I don’t know, I can’t speak to DoH/DoT and TLS but I think it’s just about what your primary goals are. After using Pi-hole for over a year (and even running a pi-hole docker container on my laptop when I travel) I wouldn’t want to trust a third party to handle any of it, smartDNS looks to (from my cursory reading) control your DNS settings so you wouldn’t be able to employ/control additional DNS blocking there without a splitDNS setup as I understand it. Definitely a topic for further research for sure, interested in what you find.

      Like

  2. tim says:

    Hey, Will… love this post. Exactly what I was looking for, but I am having trouble getting the systemctl part of the tutorial to work. Service fails to start. Mind if I email you some details? Could post here, but it would be rather long and probably wouldn’t display well. Good chance I am doing something simple wrong. Thanks

    Like

    • Will Foster says:

      Sure Tim just use the contact form on the about tab.

      Like

    • Matt says:

      I’m also having some issues when getting to the stage where I’m testing with systemctl. I wonder if the solution you may have discussed via email is the solution I need, too!

      I’m getting this error:
      Failed to start protonvpn.service: Unit protonvpn.service is not loaded properly: Bad message.

      Thoughts?

      Like

      • tim says:

        Matt, I’ve ended up not using systemd. I only need to use pvpn occasionally. Here’s Will’s response:

        I did see this sort of behavior once, for me it was just that pvpn was still active when I had run it manually then tried the system service. Double check that there are no rogue openvpn processes still running and also issue a systemctl stop protonvpn too so systemd knows not to try to restart things if it detects it not running. Check you don’t still have an internal 10.0.8.x etc IP address and route -n shows a routing table without protonvpn additions. After this try a systemctl start protonvpn.

        Not sure, if it applies to your situation. Good luck!

        Like

  3. Cohen says:

    I also had trouble getting systemctl to work as a service, but found a solution. I’m on Ubuntu and when the service tried to run it exited saying that protonvpn had not been initialized and to run `protonvpn-cli –init`. After looking through the code for protonvpn-cli, it tries to get your credentials from your home directory [here](https://github.com/ProtonVPN/protonvpn-cli/blob/001f537793dfee10f5b80eae7df982336f40764c/protonvpn-cli.sh#L78-L89). I added these lines under `[Service]` to help it find my credentials:
    “`
    Environment=SUDO_USER=cohen
    Environment=HOME=/home/cohen
    “`

    Like

    • Will Foster says:

      Yes, for systemctl to work the service needs to have been manually initiated once. Were you able to start / stop the service with the binaries and flags manually?

      I chose the root user for this so it therefore copied the appropriate credentials to roots home (which is who also fires off the service).

      Change this to your liking.

      You should also install the binaries via the —install option too if you haven’t.

      Good point on mentioning wrapping non root commands to systemctl if you like. I just left it as root because it drops the openvpn proceeds to nobody user anyway.

      I have not tried this as a normal user, but if you did modify the unit file you’ll need to reload it via systemctl daemon-reload.

      It may be better here with what you are doing to use the systemd ‘User=‘ directive here instead of sudo if you had issues there but I’m not sure.

      if tinkering with this works let me know and I’ll update the guide to provide a non-privileged user option but I feel root is fine due to service privilege dropping on openvpn instantiation.

      Like

      • Cohen says:

        > Yes, for systemctl to work the service needs to have been manually initiated once. Were you able to start / stop the service with the binaries and flags manually?

        In my case I had initiated ProtonVPN under my user instead of root.This meant that I could start and stop the service manually with sudo since the necessary env vars were set, but running as a service it was looking (presumably) in /root for the credentials.

        > It may be better here with what you are doing to use the systemd ‘User=‘ directive here instead of sudo if you had issues there but I’m not sure.

        My service still runs as root, the env vars just help point it to the credentials since the I initialized ProtonVPN as my (non-root) user.

        > if tinkering with this works let me know

        It definitely works if you have initialized ProtonVPN as a non-root user. I tried setting up the client with root and it mostly works on Ubuntu, but there are some oddities for non-root users like `sudo pvpn –status` reporting ProtonVPN as Not Running yet reporting the correct ProtonVPN IP address, assumably due to the env vars set for sudo.

        All in all, at least for Ubuntu, I think people will have a better experience initializing as their non-privileged user and adding the env vars to the unit file.

        Like

      • Will Foster says:

        Hey thanks for the further feedback. Hopefully this will help others who don’t want to use root user and/or sudo. I’m glad you got it sorted.

        My perspective may differ from others but I think it’s perfectly fine to init and install as root and manage the systemd service this way as defined in the guide as openvpn process should get demoted to the nobody user anyway (if you chose this option during init). This is probably more ideal for system-wide VPN persistence.

        For something totally non-privileged user driven (more desktop friendly?) NetworkManager supports reconnection via some settings as well and that works fine too with ProtonVPN so there’s a few options available.

        https://askubuntu.com/questions/679059/auto-reconnect-to-vpn-on-disconnect

        Like

Leave a reply to Will Foster Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.