eXistenZ | Stefan

Remote Kodi video playback (Part 1 – OpenVPN)

Recently, the situation arose where I wanted to make it possible that the media on my NAS could be watched not only by Kodi instances on my local network, but on external Kodi instances as well.

The system I intend on watching my videos on is a Raspberry Pi 2 Model B running OpenELEC 6.0 with Kodi 15.2 and the media is stored on is a self built NAS featuring a AMD X2 BE-2400 processor and 5 GiB of RAM, running Debian 8.2.

Accessing the media

I started thinking about how this should be set up, and decided that blindly sharing all of my recorded cat videos across the internet is a no-no because of privacy (cats have feeling too, you know!), so some kind of tunneling was needed.

Some of the options are VPNs and SSH tunnels, but since OpenELEC seemed to support VPN tunnels right out of the gate, I decided to go with setting up a VPN.

openelec-vpn

My experience with VPN tunnels is that they seem to be divided into two main categories, namely binding multiple networks together, for which IPsec is commonly used, and client to server VPNs, for which OpenVPN is mostly used. Because we try to establish a client-server VPN here (the Pi needs to be able to access the resources on my NAS), I decided to give OpenVPN a spin.

By the way, a lot of nice OpenVPN clients exist (e.g. Viscosity) so if you want to use OpenVPN, check that out!

Setting up the VPN

I started by setting up OpenVPN on my NAS as described here, and once that was all set and done I ended up with a single .ovpn client profile, which I was able to import in Viscosity on my Windows 10 machine. After a bit of fiddling, the VPN worked and I was able to ping the other side!

This is the server config that I came up with, running on the NAS:

port 1194
proto udp
dev tun

ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/server.crt
key /etc/openvpn/easy-rsa/keys/server.key
dh /etc/openvpn/dh2048.pem

server 10.20.30.0 255.255.255.0
keepalive 10 120

comp-lzo

user nobody
group nogroup

persist-key
persist-tun

sndbuf 393216
rcvbuf 393216
tun-mtu 1500
fragment 1300

status /var/log/openvpn-status.log
log /var/log/openvpn.log
verb 3

and here is the client config:

client

remote my.server.com 1194
proto udp
dev tun

resolv-retry infinite
nobind

comp-lzo

user nobody
group nogroup

persist-key
persist-tun

sndbuf 393216
rcvbuf 393216
tun-mtu 1500
fragment 1300

ns-cert-type server

verb 3
mute 20

<ca>
// CA here...
</ca>

<cert>
// CA here...
</cert>

<key>
// Key here...
</key>

Mind you, there are some performance tweaks in here, that increased the maximum troughput by around 25% from the stock settings.

Putting it all together

Now that the VPN was working on my Windows box, it was time to shove everything into OpenELEC.
Around this time I found out that the graphical interface for managing VPNs was seemingly removed from Kodi, but we could still add OpenVPN as a binary to the system by going to System > Addons > Install from repository > All repositories and from there install the following add-ons, in order:

  1. Add-on repository > Unofficial OpenELEC (RPi2 / ARM) Add-ons
  2. Program add-ons > openvpn

This provides us with /storage/.kodi/addons/network.openvpn/bin/openvpn.

After that I created a systemd startup file:

[Unit]
Description=VPN-NAS
After=network-online.service
Requires=network-online.service

[Service]
Type=forking
ExecStart=/storage/.kodi/addons/network.openvpn/bin/openvpn --daemon --config /storage/.config/openvpn/nas.ovpn
TimeoutStopSec=1
Restart=always
RestartSec=2
StartLimitInterval=0

[Install]
WantedBy=multi-user.target

and asked systemd nicely to start the VPN when the Pi booted with the command systemctl enable openvpn-nas.service.

Now we had a VPN from our OpenELEC Pi to our NAS! After adding and configuring the sources in Kodi I ended up with tons of happy playful cats to enjoy on my Pi.

Bandwidth issues

A bit of video playback later and it turned out that the 720p cats were all happily annoying their owners, wheras the 1080p cats just couldn’t play very smooth on the Pi.

Searching on the interwebs taught me that OpenVPN is sadly a single threaded application, and was thus maxing out one of the cores in the Pi with decrypting the VPN traffic.
After various optimizations I am stuck with around 3.5MiB/s of data troughput, which makes 1 of the 4 cores get stuck at 100% cpu time.

Fiddling with OpenVPNs cipher settings didn’t bring me any luck, as the default cipher is one of the least CPU intensive of the ones available, and my only option was to switch to RC4, which is known as a weak cipher as of 2015.

Since I don’t want any cats to escape the VPN tunnel and going rampant on the internet, I decided I will have to miss out on the 1080p media for now and stick with the default encryption of OpenVPN (BlowFish).

More exploring

For now, the story ends here, but a lot is still left to explore later on. Amongst the options I have left at my disposal are SSH tunnels (which max out at 9MiB/s on the Pi2 since they do support multithreading but are harder to secure), IPsec tunnels, WebDAV, etc.

Also the sharing protocol can be investigated. This is currently being done by Samba but I might look into stuff like NFS or other alternatives that might provide less overhead and thus better results.

I am certain that cats will rule the world and thus my TV screen, and will not be stopped a by pesky VPN tunnel.