How-to OpenVPN over SSH

Introduction

This how-to would allow you to set up an encrypted tunnel between two LANs, using OpenVPN and SSH.

This document uses Gentoo only to refer to installation procedures. It should be used in other distributions with minimal effort.

The !OpenVPN project contains documentation which I found pretty straight-forward to follow. If you find problems setting OpenVPN up, I recommend its website1 and man pages.

Context

  1. You want an encrypted tunnel between two separate LANs, across another LANs or internet itself.
  2. You cannot define rules for outgoing traffic in one of the LANs (server´s), but can definitely define rules for both incoming and outgoing traffic in the other (client´s).
  3. You have a public port available (or else can enable it) for public service (across the hetereogeneous networks in between) in the client network, and such port is accessible by the server LAN.

Solution

The proposed solution is to

  1. Set up a SSH server listening to the enabled port of the client LAN's public IP address.
  2. Generate server and client certificates (PKI stuff).
  3. Copy the client certificates to the client´s OpenVPN configuration.
  4. Set up the OpenVPN server ensuring it only cares about TCP traffic.
  5. Connect to the SSH service in the client from the server, redirecting OpenVPN port to the client.
  6. Set up the OpenVPN client for communicating to the redirecting server port on localhost, again using just TCP traffic.
  7. Automate the tunnel

SSH service on the client

In case you haven't already done so (pretty unlikely):

emerge -v openssh

In /etc/ssh/sshd_config, either change the port, define a xinetd wrapper, in case the firewall of the server´s LAN filters out TCP connections to external SSH ports. In any case, probably you'd need to do a little port forwarding to make your router handling external traffic and the box running the SSH service.

PKI stuff

This section is just a summary of what is well documented in OpenVPN´s site 1.

First of all, install OpenVPN on both sides.

USE="doc" emerge -v openvpn

Then, for the server, and following OpenVPN instructions 2, we need to copy the default scripts to perform our changes without affecting the package defaults:

mkdir /etc/openvpn
cp /usr/share/openvpn/easy-rsa/* /etc/openvpn

Edit /etc/openvpn/vars file and customize it.

cd /etc/openvpn
source vars
./clean-all
./build-ca
./build-key-server server
./build-key [client]
./build-dh

Copy required certificates

scp -P [port] /etc/openvpn/keys/[client].crt [client-public-ip]:/etc/openvpn/
scp -P [port] /etc/openvpn/keys/[client].key [client-public-ip]:/etc/openvpn/
scp -P [port] /etc/openvpn/keys/ca.cert [client-public-ip]:/etc/openvpn/
rm -f /etc/openvpn/keys/[client].crt
rm -f /etc/openvpn/keys/[client].key

Set up the OpenVPN server

We'll take a sample configuration as template:

bzcat /usr/share/doc/openvpn-2.0.6/examples/sample-config-files/server.conf.bz2 >> /etc/openvpn/openvpn.conf

Now, edit such file to make sure it sticks to TCP, and sets up the correct routes.

Connect to the client´s SSH from the server

ssh -N -g -p [port] -R 1194:localhost:1194 [client-public-ip]

Set up the OpenVPN client

It's simpler to start with a default template as before:

bzcat /usr/share/doc/openvpn-2.0.6/examples/sample-config-files/client.conf.bz2 >> /etc/openvpn/openvpn.conf

Now edit the file making sure it specifies TCP traffic explicitly, and the server points to localhost.

/etc/init.d/openvpn start

Automate the tunnel

Both in the client and the server, autostart the services on boot:

rc-update add openvpn default

Also, you can use AutoSSH to automatically restart the SSH tunnel if necessary (on the server, needless to say).

emerge -v autossh

Then, make sure the connection is set-up when the box boots:

cat <<EOF>> /etc/conf.d/local.start
autossh -M 21000 -N -g -p [port] -R 1194:localhost:1194 [client-public-ip] &
EOF