OpenVPN for IoT : Linux Server, Various Clients including RaspiZero

Using a AWS Linux server, and Raspberry Pi Zero 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 OpenVPN Server and CA

  • 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/

Setup of Raspi Client

Coming soon. Spoiler: write a long script to do a million little things to get a key.

Leave a Reply

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