The return of the Linux router... (from pfSense to Debian, part 3: OpenVPN P2P mode setup)

Hey, hi again people... let's continue with the series of articles I have in mind, just as I have (just this week!) removed the last pfSense appliance at job and have it replaced with a Linux/Debian one.
On this article I'm going to show a proposal, based on my notes, on a way to setup OpenVPN to get a point to point tunnel between two locations.

Much like layer2 (tap) tunnel mode on the previous article, p2p mode is somehow a bit hard to find recipes, guides or howtos to set it up. It is simply not as popular as the tipical layer3 read-warrior remote-access setup, but it is definitely the way to go if you want to interconnect sites

The overall scenario is a follow up of the one described on the previous article of this series, so you may take a look at it to have a full idea of it.
Here let's talk about why do we need P2P tunnels, what do we get doing that, and well... how do I made it!

 

Scenario and goals

So, long history short (or read previous article) we got our mixed physical / virtual private cloud infrastructure at OVH. We got cross-datacenter private, virtual networks, and the ability for our customers to have fully redundant, VPN remote access to their cloud assets.

Now but, we want to be able to connect our local premises to the remote, hybrid cloud premises at OVH. This means permanent connection, and, in order to keep for redundancy, we want to establish multiple tunnels, to multiple virtual routers connected to remote networks.
This obviously creates a 'multipath' scenario ... but that's what routing protocols such as OSPF are meant to deal for :-)

So, we are creating several client P2P OpenVPN instances on our local appliance, towards multiple virtual routers. Every P2P connection results in a /30 network, and all this networks are configured on OSPF. The local appliance gets an OSPF adjacency link per remote router (neighbor), so connectivity to remote networks are available on local networks fully transparent to local users and machines.

NOTES:

  • I'm not going to discuss about Quagga OSPF, since OSPF it is very well documented around.
  • We use PROXMOX at OVH, with amazing results, and we do use the cluster integrated PVE-firewall, but take this advice: at this moment, pve-firewall doesn't like asymmetric traffic (and that tends to happen when having redundant paths)... it simply drops frames silently... so, I had to disable PROXMOX pve-firewall as early layer firewall on routing VMs (which, at the end... they're firewalls on its own).
  • As in previous articles, I'm not going to deal with the SSL/TLS RSA certificates and keys creation and management... there're plenty of articles, posts, howtos around in the internet... we don't need yet another one.
    So, I simply asume we do have our necessary certs and keys set up and in place.
  • The paths, ports, and settings I write on the configuration are, of course, just for example... the important thing is more what configuration options are needed, than which values do they take.

 

Server Setup

If you read my previous article about layer2 Remote Access OpenVPN setup you may have noticed we have hero no 'Server network setup' section... This is correct, since we DO NOT need to make any network setup preparation when using layer3 VPN end devices, either in P2P mode or in Remote Access mode.

Upon starting the server (and same on the remote end), a virtual tunX network interface will be spawn.
Naming of the interface (the actual X value), addressing and so on is entirely controlled on OpenVPN settings.

Traffic from the remote end of the tunnel will be 'dropped' by local VPN instance on that tunX interface ... and conversely, traffic entering that interface will be pick-up by local OpenVPN instance and send to the remote end.
All this is at layer3 level, and, therefore is not meant to be bridged ... So, in order to traffic going to/from remote ends reaching locally connected networks on both ends, you have to allow traffic forwarding (i.e routing) at Operating System level (I guess you've it already done... if not... it is very easy and very well documented... just google around about enabling ip forwarding on Debian).

Finally, let's clarify that I'm using the tunnel just to make both ends negotiate OSPF adjacency, and therefore, you'll see commented the config parts dealing with routing... but it is important to note (that's why I decided to let that lines there, but commented) that it is entirely possible to setup your routes manually, at OpenVPN configuration, stating which routes will be pushed/pulled to/from the ends, and it works great!!!! ... the reason why I'm using OSPF is beacuse I went forward and have redundant links, and then, a routing protocol handling traffic automatically is the best way to go.

Most settings, such as IP, port, ciphering, eventual pushed routes and so on are just for filling the configuration stanzas with an example of valid data... those values should be changed as needed.
Also, some specific P2P details will be expanded after the config... so here it is:

mode p2p
local 1.2.3.4
port 11100
proto udp
dev tun10
user nobody
group nogroup

tls-server
ca /etc/openvpn/easy-rsa/keys/ca-cert.crt
cert /etc/openvpn/easy-rsa/keys/fooserver.crt
key /etc/openvpn/easy-rsa/keys/fooserver.key
dh /etc/openvpn/server/dh1024.pem
cipher AES-128-CBC
auth SHA1

persist-tun
persist-key

;float
keepalive 10 60
ping-timer-rem
explicit-exit-notify 1

status /etc/openvpn/server/P2P/status.log
log /var/log/openvpn/P2P_server_openvpn.log
verb 3

ifconfig 10.0.0.65 10.0.0.66
persist-local-ip
;push "route 10.0.10.0 255.255.255.0 10.0.10.65"

passtos
comp-lzo adaptive

 
Things to consider about this config:

  • Note we're explicitly stating the tunnel as P2P mode in the first line.
  • We may take control of which virtual device is created (tun10) but it is optional... by just putng 'tun' an interface with lowest free possible value will be created (tun0, tun1, etc)
  • Note the line 'ifconfig 10.0.0.65 10.0.0.66' .. it is very important: it involves that we're using in this example the 10.0.0.64/30 P2P network, where 10.0.0.65 is THIS END IP address, and, 10.0.10.66 (the remaining free host address on this /30 network) is the address of the remote peer. This setup has to be used accordingly on the other end client config!!!

So let's see how the remote end, the client, connecting to this server and stablishing a P2P tunnel would look like.

 

Client Setup

Let's see it first, then let's talk a little about it...

client
remote 1.2.3.4 11100
lport 11101
proto udp
dev tun1
user nobody
group nogroup
resolv-retry infinite

tls-client
ca /etc/openvpn/easy-rsa/keys/ca-cert.crt
cert /etc/openvpn/easy-rsa/keys/fooclient.crt
key /etc/openvpn/easy-rsa/keys/fooclient.key
cipher AES-128-CBC
auth SHA1

persist-tun
persist-key

;float
keepalive 10 60
ping-timer-rem

log /var/log/openvpn/P2P_fooclient_openvpn.log
verb 3

route-nopull
ifconfig 10.0.0.66 10.0.0.65

passtos
comp-lzo adaptive

 
Things to consider about this config:

  • Apart of the usual matching config between client and server regarding ciphering, compression, keepalive and so on ... note that the ifconfig stanza is the inverse of the one on the server... so, P2P /30 network is the same, 10.0.0.64/30, but now the first address, the local one, is 10.0.0.66, while the remote is the one of the server 10.0.0.65.
  • here, I'm using a somehow 'rare' to see config setting: lport, which is the local, source port, from which connection to the remote server will origin.
    Normally there's no problem with this, the port used being the default 1194 ... but here, since I'm stablishing several of these P2P connections simultaneously (for redundancy), if not manually setting local port, only the first one would start, failing the rest due to port already in use.

 
And that's it ... easy and rock solid!
Now, in my case, having OSPF propperly configured on every end regarding authentication, keeapliving and so on ... ensuring that those tun devices are not passive, I had to just declare the network 10.0.0.64/30 .... new adjacency stablished!!!!