TL;DR

Attempting to use the GUI and extract certificates for importing from your .ovpn file to generate a .onc file will just lead to pain and suffering. Use the openvpn binary within the filesystem with your .ovpn file as it is. Here’s how to make that happen…

Introduction

You know, I really like ChromeOS for what it does. It’s lightweight, starts up quickly, and with the Linux containers it gives me access to a real-enough Debian install to allow me to get done what I need. But the biggest pain I’ve found with it is trying to get it to talk to any kind of openvpn server, whether that’s the commercial ‘AS’ edition that you can deploy in AWS, or the standard community edition that you can install in Ubuntu.

The problem

The ChromeOS VPN ‘client’ claims to offer L2TP/IPSec tunnels and OpenVPN. But its implementation of the latter leaves a lot to be desired. In fact, I’d use the saying I came up with soon after starting my Tech Job in Chiswick – “It’s a little bit more complicated than it needs to be ” – because quite frankly, it is.

A standard OpenVPN client file has the server certificate/key pair embedded along with the client certificate, and what you’re expected to do with this on ChromeOS is extract those keys and certificates – a variety of methods exist, in various programming languages – them import those certificates into appropriate keystores on your system.

It sounds easy enough, but to be honest, I’ve never managed to get it to work, and I’m usually pretty good at figuring these things out. The issue appears to be (at least with the ChromeOS 80 build from Neverware I’m using) is that there’s no longer a button for telling the system that the User certificate is trusted – or that’s the issue that’s appearing in the system logs that stops it even trying to connect – and also even though my OpenVPN setup is currently configured for certificate-only, the connect dialog insists that I put in a password…

So if all this is frustrating for me, supposedly of above-average (most days at least!) technical ability  then, what chance has anyone ‘normal’ got?? Sort it out Google!!! 

There’s always a light-bulb moment!

I will admit to having done quite a bit of hacking around ‘under the hood’ with ChromeOS over the last few years, even producing my own builds for installing via USB sticks. So I’ve got a pretty good idea how much Linux there is underneath the basically-a-browser UI.

So when I was looking through the system logs on my ultrabook and spotted it was talking to openvpn somewhere ‘underneath’, I remembered that there was a real binary you could access from a system terminal.
Aha!
However, when I tried running that in client mode – sudo openvpn –config my-config-file.ovpn – it had a good try, but complained about the tun0 device not being available…

The solution

Once I’d had that light-bulb moment, I was back on familiar ground, as that seemed like something I could fix. A quick google search later – “chromeos create tun0 device” – led me to a blog posting about just that thing.

The initial one is here and an update here. I will admit, at the time of writing this I’ve only tried the first one. But it works, which has left me quite excited, not to say relieved, so I haven’t tried the updated one yet…

 

Here we go then:
On your ChromeOS machine, open up a crosh terminal tab by pressing CTRL+ALT+T
At the crosh> prompt, type
shell

to get to the local system prompt, where you should see
chronos@localhost / $

 

Get your .ovpn file onto the system via ssh/rsync/wget or your tool of choice. Save this somewhere obvious.
Now, while your default $PATH includes /usr/local/bin, that might not actually exist, so
sudo mkdir -p /usr/local/bin


Then add the script that we found earlier
sudo vim /usr/local/bin/runopenvpn.sh

So that the pasting doesn’t go wonky, set the paste option in vim
:set paste

Paste the text below:


#!/bin/sh -e
# found on https://techblog.jeppson.org/2016/02/fix-openvpn-on-chromebooks/
trap ” 2
# Stop shill and restart it with a nicer attitude towards tun0
sudo stop shill
sudo start shill BLACKLISTED_DEVICES=tun0
# Sleep 10 seconds to allow chromebook to reconnect to the network
sudo sleep 10
sudo openvpn –mktun –dev tun0
sudo sleep 3
# Add google DNS on top of current ones, since openvpn command does not do it
sudo sed -i ‘1s/^/# new DNS\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n# old DNS\n/’ /var/run/shill/resolv.conf
# Launch openvpn, finally…
sudo openvpn –config $1 –dev tun0
# When ctrl-c is hit remove tun0 and cleanup the DNS
sudo openvpn –rmtun –dev tun0
sudo sed -i ‘/# new DNS/,/# old DNS/d’ /var/run/shill/resolv.conf
trap 2


then save and exit vim
:wq

Because we want to make this easier,
chmod +x /usr/local/bin/runopenvpn.sh

Then, you basically run the script with your .ovpn config file as a parameter, and it “just works”.
So, given the script should be in our $PATH, we can do
runopenvpn.sh my-config-file.ovpn

This then prints out all the connection information and connects.
And that’s it. You are connected to your certificate-only openvpn server.
To disconnect, press CTRL-c to exit the script.

Additional notes

I did also do the following, which may be helpful to you.
On the openvpn server, I added the following into /etc/openvpn/server.conf to push my local proxy settings to the client (which also surprisingly worked for android 10, solving a different problem… 😉 )

# 20200212 https://forum.ipfire.org/viewtopic.php?t=22503
push “dhcp-option PROXY_HTTP 10.0.0.1:3128”
push “dhcp-option PROXY_HTTPS 10.0.0.1:3128”


This is because we want the VPN traffic to go through the internal (transparent) proxy to ease accessing internal servers. Your setup may or may not need this, but it helped me.
If you’re also using Linux containers on chromeOS, you may want to append your internal domain to the search parameter in the local /etc/resolv.conf file so that you don’t have to type the FQDN when connecting to other machines/services from a  terminal.

So now I can properly access my internal services when out and about, from whichever OS I happen to be using. Which is great.
But Google still need to fix their implementation to allow the use of standard .ovpn config files in the GUI!!! (please)
Many thanks to the people who actually worked out how to fix the ChromeOS tun0 issue so that I didn’t have to 🙂