ComputingInternet Of Things

OpenVPN for IoT

Using a AWS Linux server, and Raspberry Pi, Ubuntu or Robustel router clients

Situation

  • Lots of linux devices (and embedded devices) behind firewalls without public IP address
  • Publicly accessible computer (AWS)

Goals

  • Connect from the server (or office PC) to these devices
  • Something easier than ssh port forwarding
  • Ability to connect a publicly accessible site (e.g. MyIoT.com/device1) to the device1 network (private) on arbitrary port. This will allow viewing of devices from the internet.
  • Secure, robust and expandable

Solution

  • OpenVPN (this post)
  • Other options are SSH tunnels, IPSec, propriety VPN, etc

Details

Setup

  • Setup OpenVPN CA, clients and server with excellent linux tutorial.
  • Use nc to test UDP ports and firewall
  • Modifed some scripts to facilitate key creation

add_client.sh

Run on the openvpa server to create a new client

#!/bin/bash

#
# Create a OpenVPN client configuration, wait for CA signing, then configure the client machine with it
#
# Requires "client" to be ssh accessible to setup client machine
#

# First argument: Client identifier
if [ $# -ne 1 ] then
        echo Wrong args - supply name like "client3"
        exit 1
fi

EASY_RSA_DIR=~/easyrsa3/
KEY_DIR=~/client-configs/keys
OUTPUT_DIR=~/client-configs/files
BASE_CONFIG=~/client-configs/base.conf

# make keys
cd "$EASY_RSA_DIR"
./easyrsa --batch --req-cn="$1" gen-req "$1" nopass

# copy req to CA
read -p "Run 'make_client $1' on the CA machine,copy back '$1.crt' and then press enter"

# put everything in KEY_DIR
cp pki/private/$1.key ~/client-configs/keys/

# package up
cat ${BASE_CONFIG} \
    <(echo -e '<ca>') \
    ${KEY_DIR}/ca.crt \
    <(echo -e '</ca>\n<cert>') \
    ${KEY_DIR}/${1}.crt \
    <(echo -e '</cert>\n<key>') \
    ${KEY_DIR}/${1}.key \
    <(echo -e '</key>\n<tls-auth>') \
    ${KEY_DIR}/ta.key \
    <(echo -e '</tls-auth>') \
    | sudo tee ${OUTPUT_DIR}/${1}.ovpn 1>/dev/null

# copy client openvpn config to client. It includes everything required for the client.
scp $OUTPUT_DIR/$1.ovpn $1:.

# install openvpn on client and start
scp install_openvpn_client.sh $1.ovpn
ssh $1

install_openvpn_client.sh

Run on the client machine to start openvpn


#!/bin/sh
# run on the client 
# First argument: Client identifier

if [ $# -ne 1 ]
 then
        echo Wrong args - supply name of .ovpn file like "client1.ovpn"
        exit 1
fi

sudo apt install openvpn openvpn-systemd-resolved
sudo cp $1 /etc/openvpn/client.ovpn
sudo systemctl enable openvpn@client
sudo systemctl start openvpn@client

make_client_cert.sh

Run on the CA machine to sign the certificate request

#!/bin/bash
 # First argument: Client identifier
if [ $# -ne 1 ]; then
        echo Wrong args - supply name like "client3"
        exit 1
fi

SERVER=live.openvpnserver-changeme.com
KEY_DIR=$SERVER:client-configs/keys
REQ_DIR=$SERVER:easyrsa3/pki/reqs

EASY_RSA_DIR=~/easyrsa3/

cd "$EASY_RSA_DIR"

# get .req from openvpn server
scp $REQ_DIR/$1.req /tmp

# process request
./easyrsa --batch import-req /tmp/$1.req $1
./easyrsa --batch sign-req client $1

# put client cert to openvpn server
scp pki/issued/$1.crt $KEY_DIR/

Robustel Router OpenVPN

The above clients are linux boxes. Sometimes I use a R1510-4L Robustel Wifi/3G router. This is the setup to connect to the OpenVPN server configured above.

  • OpenVPN tunnel tab: edit connection and set to match your OpenVPN server.conf:
    • Auth Type: x509CA
    • Mode: Client
    • Encrypt Algo: AES-256
    • Auth Algo: SHA256
    • Enable compression: OFF(1)
    • Enable HMAC Firewall: ON (2)

(1) ensure this is on at the server. Symptom was “unknown IP version=15” openvpn server log indicating compression problems. Also not contactable even if connected.

(2) sympton was HMAC errors in the openvpn server log

  • x509 tab: upload your files
    • Root CA: ca.crt : the CA’s certificate
    • Certificate File: client1.crt : the client’s certificate
    • Private Key: client1.key : the client’s key
    • TLS-Auth Key: ta.key
    • PKCS#12: not required (was possible to create with openssl but didn’t need)

Saving data:

  • A resting router with an active open seems to use a lot of data (5 Mb/hour = 100 Mb/day!)
  • I increased ping and openvpn keep alive (60 ping : 600 failed)
  • New test with computer disconnected and openvpn running
    • RX:8224KiB TX:15511KiB ALL:23MiB @ 21:55
    • RX:8489KiB TX:15762KiB ALL:23MiB @ 12:00 next day
    • Hence 516kB/hour or ~1Mb/day or 26Mb/month
  • Test with not openvpn, just a Rpi running autossh
    • TX:10420KiB TX:18037KiB ALL:27MiB @ 14:00

Connecting Remotely

  • Can’t connect via OpenVPN from a client’s browser.
  • But CAN ping and wget the index.html page. WTF?
  • Tried some route -nand interface priority stuff: no luck.
  • Tried on windows : no luck.
  • Maybe a local proxy or SOCKs server: no luck
  • Cannot connect. Giving up. Use a openvpn client behind the router on a pizero instead.

Leave a Reply

Your email address will not be published. Required fields are marked *