Bridging in OpenVPN
OpenVPN allows two different modes of operation: routed mode and bridged mode. This article is about the latter.
Bridged mode means that the VPN tunnel encapsulates full ethernet frames (up to 1514 bytes long), rather than IP packets (up to 1500 bytes). In itself, this would just add some overhead to the VPN traffic; but in practice, together with some special configuration in the OS (described later), this allows to connect the VPN and its users to a real, physical ethernet network at the data-link level, effectively turning the whole system (ethernet network + VPN) into a single broadcast domain.
Do you need bridging?
This question comes up regularly when somebody asks for advice in configuring a bridged VPN. Bridged mode has a higher traffic overhead, since it works at layer 2 and as such broadcasts are sent into the VPN, and also, as already mentioned, data packets can be up to 1514 bytes. Normally bridged mode is needed only in two cases:
- You really need to create a layer 2 domain. This may be because you need to use protocols that rely on broadcasts or multicasts (eg netBIOS, LAN games)
- You need to transport non-IP traffic (eg IPX, AppleTalk?)
If you don't have any of those requirements, you can almost certainly use routed mode. Otherwise, read on.
Bridge setup
For this example, we will assume the following scenario:
+---------+ | client1 +--------\ +--------------------------------- +---------+ \ +-------------+ / LAN \ + + / 192.168.111.0/24 +---------+ + + +---------+ | client2 +-----------+ INTERNET +---- ppp0 + gateway +eth0 +---------+ + + +---------+ (192.168.111.254/24) / + + \ +---------+ / +-------------+ \ | clientN +---------/ +--------------------------------- +---------+
We want VPN clients to connect and feel as if they were physically on the ethernet network, including using IP addresses in the 192.168.111.0/24 range, just like the stations in the LAN.
The first step to achieve this goal is to create a special interface on the VPN gateway. This interface (also known as a bridge) is what connects, or bridges, together the "real" layer 2 domain (ie the LAN) and the layer 2 VPN. Basically a bridge like this can be thought as a mini-ethernet switch internal to the OS, whose ports are connected to ethernet interfaces on the host. So for example, on a host with two ethernet interfaces (eth0 and eth1), a two-ports bridge could be created by enslaving eth0 and eth1 into the special bridge interface (let's call it br0). The enslaved interfaces can usually be added and removed dynamically from the bridge. The bridge interface behaves like an ethernet switch (well, because it effectively is an ethernet switch): it learns which MAC addresses are on each ports, and forwards frames accordingly (broadcasts and unknown MACs are flooded on all ports). The interfaces that are enslaved into the bridge (eth0 and eth1 in our example) operate purely at layer 2, and can not have IP addresses of their own. However, the bridge interface can have an IP address and is otherwise a normal interface, and as such can have firewall rules, routes etc.
To get to OpenVPN: the virtual tap interface that OpenVPN uses in bridged mode is an ethernet interface, and as such can be part of a bridge. This is key: for our scenario, we are going to create a bridge interface that includes the gateway's eth0 LAN interface, and OpenVPN's tap0 interface. This is what bridges the VPN with the LAN.
While the concept of a bridge interface is common, the methods used to actually create a bridge interface are OS dependent. In the following paragraphs instructions are provided for the most common systems, using the addresses and interface names from the above example.
Permanent vs. transient bridge
There are two ways to use a bridge with OpenVPN. One is to create the bridge on the fly just before OpenVPN starts, adding eth0 and tap0 to it, and destroy it when OpenVPN terminates. The second way is to have a permanent bridge interface comprising just eth0, to which OpenVPN's tap0 is added during the time OpenVPN is running.
The first method has several drawbacks: the biggest one is that it involves removing the IP address from the eth0 interface and assigning it to the bridge interface (and the reverse when the bridge is destroyed). On most systems, deleting an IP address from an interface has the effect of removing all routes pointing out that interface, which means that these routes have to be recreated to point to the bridge when it is set up, and again recreated to point to eth0 again when the bridge is destroyed. Also, in some operating systems, there is a delay of some seconds when bringing up the bridge due to STP, and this is turn delays the start of the OpenVPN daemon. Thus setting up a transient bridge is not only complicated to get right, but it also disrupts connectivity for some time.
So, having a permanent bridge created at boot time and only adding/removing tap0 is largely preferable, and this is what the following instructions do.
Windows
Under Windows, the tap interface exists as soon as OpenVPN is installed, even if OpenVPN is not running, and so the bridge can permanently include both interfaces. Also, interfaces are not named "eth0" and "tap0" under Windows, but it should be possible to tel which is which by their descriptions.
Under Windows, open the network interface screen, and select (using CTRL-click) the interfaces that you want to bridge (in our example, the LAN interface and the tap-32 adapter). When they are selected, right-click on the selection and choose "Bridge...". The configuration dialog for the bridge interface will appear, complete it with the information that was previously applied to the regular ethernet interface (ie IP address 192.168.111.254/24 and so).
(to be verified and completed)
Linux
Under Linux, the tool needed to manage bridge interfaces is brctl, which is usually provided in a package called bridge-utils. If we want to use the network configuration facilities provided by the distribution, then the details vary. Here are instructions for Debian-like and Redhat-like distros.
Debian-like (Debian, Ubuntu and derivatives)
Install bridge-utils:
apt-get install bridge-utils
The actual configuration is done in the file /etc/network/interfaces
auto br0 iface br0 inet static address 192.168.111.254 netmask 255.255.255.0 network 192.168.111.0 broadcast 192.168.111.255 bridge_ports eth0
Redhat-like (RHEL, CentOS, Fedora)
Install bridge-utils
yum install bridge-utils
File: /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0 ONBOOT=yes TYPE=Ethernet BRIDGE=br0
File: /etc/sysconfig/network-scripts/ifcfg-br0
DEVICE=br0 TYPE=Bridge ONBOOT=yes STP=on IPADDR=192.168.111.254 NETMASK=255.255.255.0
If the resulting network topology has no loops (which is probably likely), STP can be disabled.
Mac OS X
(to be completed - need info)
FreeBSD
(to be completed - need info)
Solaris
(to be completed - need info)
OpenVPN configurations
Once the bridge interface is in place, here are sample configurations for the server and for the client(s).
Server configuration
port 1194 proto udp dev tap # Windows needs the TAP-Win32 adapter name # from the Network Connections panel if you # have more than one. # Non-Windows systems usually don't need this. ;dev-node MyTap # script used to add the tap interface to the bridge # windows servers comment this out up up.sh ca ca.crt cert server.crt key server.key dh dh1024.pem ifconfig-pool-persist ipp.txt # addresses from .100 to .200 are reserved for VPN clients. # Obviously, they should not be used by real LAN clients. server-bridge 192.168.111.254 255.255.255.0 192.168.111.100 192.168.111.200 # Certain Windows-specific network settings # can be pushed to clients, such as DNS # or WINS server addresses. CAVEAT: # http://openvpn.net/faq.html#dhcpcaveats ;push "dhcp-option DNS 192.168.111.1" ;push "dhcp-option WINS 192.168.111.2" # can clients see each other? (regardless of firewalling on the server) ;client-to-client keepalive 10 120 comp-lzo persist-key persist-tun status openvpn-status.log verb 3
Following are sample up.sh scripts for UNIX systems (in Windows it's not needed since the bridge permanently include both interfaces)
Linux
#!/bin/sh # the tap interface name is passed as first argument bridge=br0 brctl addif "$bridge" "$1"
Mac OS X
(to be completed, need info)
FreeBSD
(to be completed, need info)
Solaris
(to be completed, need info)
Client configuration
client dev tap # Windows needs the TAP-Win32 adapter name # from the Network Connections panel # if you have more than one. ;dev-node MyTap proto udp remote my-server-1 1194 resolv-retry infinite nobind persist-key persist-tun ca ca.crt cert client.crt key client.key ns-cert-type server comp-lzo verb 3