OpenVPN Tunnels and Bridges

Simon Matter

Tom Eastep

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover, and with no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.

2009/06/12


Table of Contents

Preliminary Reading
Bridging two Masqueraded Networks
Roadwarrior
Bridging Two Networks

Caution

This article applies to Shorewall 3.0 and later and to OpenVPN 2.0 and later. If you are running a version of Shorewall earlier than Shorewall 3.0.0 then please see the documentation for that release.

OpenVPN is a robust and highly configurable VPN (Virtual Private Network) daemon which can be used to securely link two or more private networks using an encrypted tunnel over the Internet. OpenVPN is an Open Source project and is licensed under the GPL. OpenVPN can be downloaded from http://openvpn.net/.

Unless there are interoperability issues (the remote systems do not support OpenVPN), OpenVPN is my choice any time that I need a VPN.

  1. It is widely supported -- I run it on both Linux and Windows XP.

  2. It requires no kernel patching.

  3. It is very easy to configure.

  4. It just works!

Preliminary Reading

I recommend reading the VPN Basics article if you plan to implement any type of VPN.

Bridging two Masqueraded Networks

Suppose that we have the following situation:

We want systems in the 192.168.1.0/24 subnetwork to be able to communicate with the systems in the 10.0.0.0/8 network. This is accomplished through use of the /etc/shorewall/tunnels file and the /etc/shorewall/policy file and OpenVPN.

While it was possible to use the Shorewall start and stop script to start and stop OpenVPN, I decided to use the init script of OpenVPN to start and stop it.

On each firewall, you will need to declare a zone to represent the remote subnet. We'll assume that this zone is called “vpn” and declare it in /etc/shorewall/zones on both systems as follows.

/etc/shorewall/zones — Systems A & B

#ZONE   TYPE   OPTIONS                 IN                      OUT
#                                      OPTIONS                 OPTIONS
vpn     ipv4

On system A, the 10.0.0.0/8 will comprise the vpn zone.

In /etc/shorewall/interfaces on system A:

#ZONE      INTERFACE        BROADCAST     OPTIONS
vpn        tun0

In /etc/shorewall/tunnels on system A, we need the following:

#TYPE         ZONE           GATEWAY        GATEWAY ZONE
openvpn       net            134.28.54.2

This entry in /etc/shorewall/tunnels opens the firewall so that OpenVPN traffic on the default port 1194/udp will be accepted to/from the remote gateway. If you change the port used by OpenVPN to 7777, you can define /etc/shorewall/tunnels like this:

/etc/shorewall/tunnels with port 7777:

#TYPE             ZONE           GATEWAY         GATEWAY ZONE
openvpn:7777      net            134.28.54.2

Similarly, if you want to use TCP for your tunnel rather than UDP (the default), then you can define /etc/shorewall/tunnels like this:

/etc/shorewall/tunnels using TCP:

#TYPE             ZONE           GATEWAY         GATEWAY ZONE
openvpn:tcp       net            134.28.54.2

Finally, if you want to use TCP and port 7777:

/etc/shorewall/tunnels using TCP port 7777:

#TYPE             ZONE           GATEWAY         GATEWAY ZONE
openvpn:tcp:7777  net            134.28.54.2

This is the OpenVPN config on system A:

dev tun
local 206.162.148.9
remote 134.28.54.2
ifconfig 192.168.99.1 192.168.99.2
route 10.0.0.0 255.0.0.0 192.168.99.2
tls-server
dh dh1024.pem
ca ca.crt
cert my-a.crt
key my-a.key
comp-lzo
verb 5

Similarly, On system B the 192.168.1.0/24 subnet will comprise the vpn zone

In /etc/shorewall/interfaces on system B:

#ZONE      INTERFACE        BROADCAST     OPTIONS
vpn        tun0 

In /etc/shorewall/tunnels on system B, we have:

#TYPE         ZONE           GATEWAY        GATEWAY ZONE
openvpn       net            206.191.148.9

And in the OpenVPN config on system B:

dev tun
local 134.28.54.2
remote 206.162.148.9
ifconfig 192.168.99.2 192.168.99.1
route 192.168.1.0 255.255.255.0 192.168.99.1
tls-client
ca ca.crt
cert my-b.crt
key my-b.key
comp-lzo
verb 5

You will need to allow traffic between the “vpn” zone and the “loc” zone on both systems -- if you simply want to admit all traffic in both directions, you can use the policy file:

/etc/shorewall/policy on systems A & B

#SOURCE        DEST          POLICY          LOG LEVEL
loc            vpn           ACCEPT
vpn            loc           ACCEPT

On both systems, restart Shorewall and start OpenVPN. The systems in the two masqueraded subnetworks can now talk to each other.

Roadwarrior

OpenVPN 2.0 provides excellent support for roadwarriors. Consider the setup in the following diagram:

On the gateway system (System A), we need a zone to represent the remote clients — we'll call that zone “road”.

/etc/shorewall/zones — System A:

#ZONE   TYPE   OPTIONS                 IN                      OUT
#                                      OPTIONS                 OPTIONS
road    ipv4

On system A, the remote clients will comprise the road zone.

In /etc/shorewall/interfaces on system A:

#ZONE      INTERFACE        BROADCAST     OPTIONS
road       tun+

In /etc/shorewall/tunnels on system A, we need the following:

#TYPE         ZONE           GATEWAY        GATEWAY ZONE
openvpn:1194  net            0.0.0.0/0

If you are running Shorewall 2.4.3 or later, you might prefer the following in /etc/shorewall/tunnels on system A. Specifying the tunnel type as openvpnserver has the advantage that the VPN connection will still work if the client is behind a gateway/firewall that uses NAT.

#TYPE               ZONE           GATEWAY        GATEWAY ZONE
openvpnserver:1194  net            0.0.0.0/0

We want the remote systems to have access to the local LAN — we do that with an entry in /etc/shorewall/policy (assume that the local LAN comprises the zone “loc”).

#SOURCE      DESTINATION        POLICY
road         loc                ACCEPT

The OpenVPN configuration file on system A is something like the following:

dev tun

server 192.168.2.0 255.255.255.0

dh dh1024.pem

ca /etc/certs/cacert.pem

crl-verify /etc/certs/crl.pem

cert /etc/certs/SystemA.pem
key /etc/certs/SystemA_key.pem

port 1194

comp-lzo

user nobody

group nogroup

ping 15
ping-restart 45
ping-timer-rem
persist-tun
persist-key

verb 3

Configuration on the remote clients follows a similar line. We define a zone to represent the remote LAN:

/etc/shorewall/zones — System B:

#ZONE   TYPE   OPTIONS                 IN                      OUT
#                                      OPTIONS                 OPTIONS
home    ipv4

On system A, the hosts accessible through the tunnel will comprise the home zone.

In /etc/shorewall/interfaces on system B:

#ZONE      INTERFACE        BROADCAST     OPTIONS
home       tun0

In /etc/shorewall/tunnels on system B, we need the following:

#TYPE         ZONE           GATEWAY        GATEWAY ZONE
openvpn:1194  net            206.162.148.9

Again, if you are running Shorewall 2.4.3 or later, in /etc/shorewall/tunnels on system B you might prefer:

#TYPE               ZONE           GATEWAY        GATEWAY ZONE
openvpnclient:1194  net            206.162.148.9

We want the remote client to have access to the local LAN — we do that with an entry in /etc/shorewall/policy.

#SOURCE      DESTINATION        POLICY
$FW          home               ACCEPT

The OpenVPN configuration on the remote clients is along the following line:

dev tun
remote 206.162.148.9
up /etc/openvpn/home.up

tls-client
pull

ca /etc/certs/cacert.pem

cert /etc/certs/SystemB.pem
key /etc/certs/SystemB_key.pem

port 1194

user nobody
group nogroup

comp-lzo

ping 15
ping-restart 45
ping-timer-rem
persist-tun
persist-key

verb 3

If you want multiple remote clients to be able to communicate openly with each other then you must:

  1. Include the client-to-client directive in the server's OpenVPN configuration; and

  2. Specify the routeback option on the tun+ device in /etc/shorewall/interfaces.

If you want to selectively allow communication between the clients, then see this article by Marc Zonzon

Bridging Two Networks

Occasionally, the need arises to have a single LAN span two different geographical locations. OpenVPN allows that to be done easily.

Consider the following case:

Part of the 192.168.1.0/24 network is in one location and part in another. The two LANs can be bridged with OpenVPN as described in this section. This example uses a fixed shared key for encryption.

OpenVPN configuration on left-hand firewall:

remote 130.252.100.109
dev tap0
secret /etc/openvpn/bridgekey

OpenVPN configuration on right-hand firewall:

remote 206.124.146.176
dev tap0
secret /etc/openvpn/bridgekey

The bridges can be created by manually makeing the tap device tap0 and bridgeing it with the local ethernet interface. Assuming that the local interface on both sides is eth1, the following stanzas in /etc/network/interfaces (Debian and derivatives) will create the bridged interfaces.

/etc/network/interfaces on the left-hand firewall:

iface br0 inet static
      pre-up /usr/sbin/openvpn --mktun --dev tap0
      pre-up /usr/sbin/brctl addbr br1
      address 192.168.1.254
      network 192.168.1.0
      broadcast 192.168.1.255
      netmask 255.255.255.0
      post-up /sbin/ip link set tap0 up
      post-up /usr/sbin/brctl addif br0 tap0
      post-up /sbin/ip link set eth1 up
      post-up /usr/sbin/brctl addif br0 eth1
      post-down /usr/sbin/brctl delbr br0
      post-down /usr/sbin/tunctl -d tap0
      post-down /sbin/ip link set eth1 down      

/etc/network/interfaces on the right-hand firewall:

iface br0 inet static
      pre-up /usr/sbin/openvpn --mktun --dev tap0
      pre-up /usr/sbin/brctl addbr br1
      address 192.168.1.253
      network 192.168.1.0
      broadcast 192.168.1.255
      netmask 255.255.255.0
      post-up /sbin/ip link set tap0 up
      post-up /usr/sbin/brctl addif br0 tap0
      post-up /sbin/ip link set eth1 up
      post-up /usr/sbin/brctl addif br0 eth1
      post-down /usr/sbin/brctl delbr br0
      post-down /usr/sbin/tunctl -d tap0
      post-down /sbin/ip link set eth1 down      

The Shorewall configuration is just a Simple Bridge.