Using VRFs on Linux enables a whole new set of network setups.
As described in the previous post about VRFs on Linux, VRFs allow to isolate different interfaces at layer 3. In the Freifunk Hochstift network we chose to consider the main or default VRF as the internal network and move any internet facing interfaces into an external VRF. Chosing this concept allows, to safely contain traffic within the internal network and only at designated border routers leak eligible traffic into the internet.
In an distributed environment like the Freifunk Hochstift network, it is inevitable to connect different islands using VPN tunnels over the Internet. This could be done by the means of GRE tunnels as shown in the previous article about the border routers, or by means of encrypted VPNs like OpenVPN, IPsec or Wireguard. As the old infrastructure quite heavily relied on OpenVPN tunnels, and they worked quite well, the new setup should keep this building block in place.
Using an external VRF for any Internet facing interface presents a challenge: The tap (or tun) device should be part of the default VRF so internal routing protocols can connect all parts of the network, but OpenVPN should use the external interface/VRF for the encrypted VPN traffic to other islands.
With upstream OpenVPN as of today this isn’t possible, but the solution is just a small patch (PR #65) away. All that needs to be done, is to bind the socket opened by OpenVPN to the external VRF device and the Linux kernel will route any encrypted tunnel packet using the routing table associated with that VRF.
This works fine since kernel 4.7 (from Debian Jessie backports) and has been tested with kernel 4.9 up to 4.17 (from Debian Stretch backports). Debian packages of OpenVPN including the above patch for Jessie and Stretch are available at apt.ffho.net.
Update: The patch has been merged for a while now and is part of OpenVPN >= 2.5.0. As of today OpenVPN 2.5.0 is available in Debian buster-backports.