After handing in my MacBook Pro
at the end of my last job,
I needed a new setup to
code on.
I had an old Lenovo IdeaPad
that I had repurposed as a home server.
I also had an HP Chromebook 11
that I hadn’t used much in a while.
I spent a bit of time trying to
make the Lenovo usable as a
“desktop” again,
but I found it was too much work
to configure an environment
minimal enough for my tastes.
Instead, I slid it back on the shelf
and started exploring other options.
What I’ve settled on
for now
is a stack of OpenVPN, SSH and tmux.
Chrome Secure Shell
The built-in
crosh shell of Chrome OS
includes an SSH client,
but it is very tedious
to make connections with,
since it requires
entering the user, host, and SSH key
every time.
Luckily, there is a Chrome app named
Secure Shell,
which exposes a much nicer interface.
It saves connection information
and remembers your SSH keys,
although you still have
to generate them beforehand.
It is still in beta,
but the only thing that seems to be missing
is a more usable settings page.
Generating Keys
Generating SSH keys
for Secure Shell
works much the same way as usual:
ssh-keygen -t rsa -C 'comment' -f chromebook.id_rsa
This will write the private key
to chromebook.id_rsa
and the public key
to chromebook.id_rsa.pub
.
I then served these files
over local HTTP
and downloaded them
on my Chromebook.
They can then be imported
from the Secure Shell connection dialog.
Colours
Secure Shell works great,
but the default colour scheme
isn’t exactly pretty to look at.
Since there isn’t much of a settings interface,
you have to enter a JSON object
in the color-pallete-overrides
field.
I based mine on the Gruvbox Generalized
XResources file:
{
"0": "#282828", "8": "#928374",
"1": "#cc241d", "9": "#fb4934",
"2": "#98971a", "10": "#b8bb26",
"3": "#d79921", "11": "#fadb2f",
"4": "#458588", "12": "#83a598",
"5": "#b16286", "13": "#d3869b",
"6": "#689d6a", "14": "#8ec07c",
"7": "#a89984", "15": "#ebdbb2"
}
I also set background-color
to #1d2021
(hard contrast),
and foreground-color
and cursor-color
both to #ebdbb2
.
Dynamic DNS
In order to easily access
my home server from anywhere,
I need a domain pointing to
my home connection.
The Arch Wiki lists many options
for Dynamic DNS.
I use CloudFlare
for my domains,
so I use wimpunk’s ddclient fork (AUR),
which has support for CloudFlare
and other services.
The relevant part of
my ddclient configuration (/etc/ddclient/ddclient.conf
)
looks like this:
protocol=cloudflare, \
zone=cmcenroe.me, \
server=www.cloudflare.com, \
login=redacted, \
password=redacted, \
home.cmcenroe.me
Note that it was necessary
to manually create an A record
for home.cmcenroe.me
before
ddclient could update it.
On Arch,
it is then as simple as
enabling and starting ddclient
I found a guide
for creating .onc
files
for OpenVPN connections,
which covers creation pretty well.
with systemd:
sudo systemctl enable ddclient
sudo systemctl start ddclient
OpenVPN Server
In order to access my home server securely
from anywhere,
I decided to set up a VPN
using OpenVPN.
Arch Wiki has an excellent page page on OpenVPN,
with thorough setup instructions.
I did, however,
run into one problem
with the server configuration.
When connecting to the VPN
from my Chromebook
on another wifi connection,
the DNS configuration would break.
I fixed this by having the server
send DNS configuration to the client explicitly,
using this option in /etc/openvpn/server.conf
:
push "dhcp-option DNS 8.8.8.8"
Chrome OS & OpenVPN
Although the Chrome OS “Private Network” interface
in Settings supports OpenVPN,
it does not support using
an HMAC secret key (ta.key
),
which greatly enhances security.
There is also a misinterpretation
of the OpenVPN protocol
on the part of Chrome OS,
which causes breakage
when not tunneling all traffic
through the VPN.
A flag needs to be used,
which is not available
from the interface,
to prevent this behaviour.
As an alternative to the interface,
Chrome OS supports “Open Network Config” files (.onc
)
in JSON format,
which can be imported
through chrome://net-internals/#chromeos
.
I found a guide
for importing certificates
and creating and importing .onc
files
for OpenVPN.
I would suggest
using the uuidgen
command line utility
(from util-linux
)
to generate UUIDs.
The other,
more important change,
is the addition
of the IgnoreDefaultRoute
flag.
This prevents the buggy behaviour
mentioned above.
In the end, my home.onc
file ended up looking like this:
{
"Type": "UnencryptedConfiguration",
"Certificates": [
{
"GUID": "{0fac9c63-a364-407a-b680-5525b19437ab}",
"Type": "Authority",
"X509": "redacted"
}
],
"NetworkConfigurations": [
{
"GUID": "{c3be34ff-94f5-43cb-bc42-99d19a0ae307}",
"Name": "Home",
"Type": "VPN",
"VPN": {
"Type": "OpenVPN",
"Host": "home.cmcenroe.me",
"OpenVPN": {
"ServerCARef": "{0fac9c63-a364-407a-b680-5525b19437ab}",
"AuthRetry": "interact",
"ClientCertType": "Pattern",
"ClientCertPattern": {
"IssuerCARef": ["{0fac9c63-a364-407a-b680-5525b19437ab}"]
},
"CompLZO": true,
"Port": 1194,
"Proto": "udp",
"RemoteCertTLS": "server",
"RemoteCertEKU": "TLS Web Server Authentication",
"SaveCredentials": true,
"ServerPollTimeout": 10,
"Username": "june",
"KeyDirection": 1,
"IgnoreDefaultRoute": true,
"TLSAuthContents": "redacted"
}
}
}
]
}
After importing this .onc
file,
I could select the “Home” private connection
from the interface.
When prompted,
I entered a fake password
and checked “Save identity and password”.
To check that I was properly connected,
I used Secure Shell
to SSH to 10.8.0.1
.
I also made sure I could connect
to everything else
as normal.
tmux
I had never used tmux before,
but it quickly became clear
that it is an invaluable tool
when doing work over SSH.
I created a configuration
that very closely mimics VIM window management,
which can be found in my dotfiles repository.
I also wrote some shell functions
for quickly getting into tmux:
tn() { [ -n "$1" ] && tmux new -s "$1" || tmux new }
ta() { [ -n "$1" ] && tmux attach -t "$1" || tmux attach }
End Result
Here is me editing this post on my Chromebook,
with OpenVPN, SSH, tmux, VIM and zsh:
Bonus: OpenVPN & iPhone
I also wanted to be able
to SSH into my home server
from my phone
if I ever needed to.
I use the ServerAuditor
SSH client on iOS.
It can generate its own keys
and export them.
For VPN, there is the OpenVPN Connect app.
This app uses .ovpn
files
for client configuration.
These files are just regular OpenVPN .conf
files
with a different extension.
The only complicated part
of creating one is
adding the certificates and keys inline,
using HTML-like tags.
After generating a new certificate for my phone,
my .ovpn
file looked like this:
client
dev tun
proto udp
remote home.cmcenroe.me 1194
resolv-retry infinite
nobind
persist-key
persist-tun
<ca>
-----BEGIN CERTIFICATE-----
redacted
-----END PRIVATE KEY-----
</ca>
<key>
-----BEGIN CERTIFICATE-----
redacted
-----END PRIVATE KEY-----
</key>
remote-cert-tls server
key-direction 1
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
redacted
-----END OpenVPN Static key V1-----
</tls-auth>
comp-lzo
I then imported the .ovpn
by emailing it to myself
and opening it in OpenVPN Connect
from the Mail app.
This is what the end result looks like on iPhone: