OpenVPN – Bridging two net

**UPDATE**

You will need bridge-tools … `yum install bridge-utils tunctl`

So, I have finally conquered the bridging of two networks. Well, I should refine that. I have managed to get an OpenVPN server configured correctly to have my VPN client be on my VPN server’s network – not some vpn-only network. Here’s what it looks like:

Internet
|
(dhcp address from Cable)
DD-Wrt router
192.168.0.1
|
[ all of the 192.168.0.x network ]
|
192.168.0.10
Server (with OpenVPN)

On the client side I have:

Internet
|
(dhcp address from generic ISP)
Gateway
192.168.1.1
|
Client device
192.168.1.100

So what I did was – I created a tap0 device on the server and built a bridge device that bridges the eth device with the virtual device.

For the OpenVPN server, I am running Fedora 9 running kernel 2.6.25-14.fc9.i686
There are a number of places out there that help you get the stupid package installed. However, there aren’t that many that help you actually get something working when it comes to the configurations. I found that the bridge-start and bridge-stop scripts were PAINFULLY undocumented. However, their role is extremely critical when doing this in bridged mode. I will leave it to you for installing openvpn in a non-bridged fashion. Once you get that working, come back here and use my scripts to help you get it working in a bridged manner.

Here’s what my /etc/openvpn/server.conf file looks like:

port 1194
proto udp
dev tap0
;dev-node MyTap
ca keys/ca.crt
cert keys/server.crt
key keys/server.key  # This file should be kept secret
dh keys/dh1024.pem
ifconfig-pool-persist ipp.txt
server-bridge 192.168.0.10 255.255.255.0 192.168.0.21 192.168.0.29
;push "route 192.168.0.0 255.255.255.0"
;client-config-dir ccd
;route 192.168.40.128 255.255.255.248
;learn-address ./script
;push "redirect-gateway"
push "dhcp-option DNS 192.168.0.1"
push "dhcp-option WINS 192.168.0.1"
client-to-client
;duplicate-cn
keepalive 10 120
;tls-auth ta.key 0 # This file is secret
;cipher BF-CBC        # Blowfish (default)
;cipher AES-128-CBC   # AES
;cipher DES-EDE3-CBC  # Triple-DES
comp-lzo
max-clients 5
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
log         openvpn.log
verb 3
;mute 20

Here’s an example of a client.conf

client
dev tap
;dev-node MyTap
proto udp
remote my-server 1194
resolv-retry infinite
nobind
;user nobody
;group nobody
persist-key
persist-tun
ca keys/ca.crt
cert keys/client6.crt
key keys/client6.key
ns-cert-type server
;tls-auth keys/ta.key 1
;cipher x
comp-lzo
verb 3
;mute 20

I found that the originial bridge-start script did not include the default gateway. Since I only use a single network card on my server, this is a necessary addition. Also, my one eth interface is eth1. I normally have it just pull DHCP from my router. On my router, I have it set to always give it 192.168.0.10 based on its MAC address ( I <3 dd-wrt and host-specific dhcpd services)
Here’s my bridge-start script:

#!/bin/bash

#################################
# Set up Ethernet bridge on Linux
# Requires: bridge-utils
#################################

# Define Bridge Interface
br="br0"

# Define list of TAP interfaces to be bridged,
# for example tap="tap0 tap1 tap2".
tap="tap0"

# Define physical ethernet interface to be bridged
# with TAP interface(s) above.
eth="eth1"
eth_ip="192.168.0.10"
eth_netmask="255.255.255.0"
eth_broadcast="192.168.10.255"
eth_gateway="192.168.0.1"

for t in $tap; do
 openvpn --mktun --dev $t
 sleep 1
done

brctl addbr $br
sleep 1
brctl addif $br $eth
sleep 1

for t in $tap; do
 brctl addif $br $t
 sleep 1
done

ifconfig $eth 0.0.0.0 promisc up
sleep 1

ifconfig $br $eth_ip netmask $eth_netmask broadcast $eth_broadcast
sleep 1
route add default gw $eth_gateway

Again, since eth1 is typically dhcp – I had to add the following to make sure that when the bridge gets turned off – it still pulls dhcp. (I do not use NetworkManager – instead, I have the setting files maintained in /etc/sysconfig/network-scripts/ifcfg-eth1)
Here’s my bridge-stop script:

#!/bin/bash

####################################
# Tear Down Ethernet bridge on Linux
####################################

# Define Bridge Interface
br="br0"

# Define list of TAP interfaces to be bridged together
tap="tap0"

ifconfig $br down
brctl delbr $br

for t in $tap; do
 openvpn --rmtun --dev $t
done

ifdown eth1
ifup eth1

I wanted to automatically generate a new client certificate. I also wanted to tarball up all of the necessary files that a client would need. So I came up with this file. For now -it resides in /root/bin So does bridge-start and bridge-stop
Here’s my addvpnclient.sh script

client=$1
tar=$2

if [ ! -d /etc/openvpn/dist/$client ]; then
        mkdir -p /etc/openvpn/dist/$client/keys
fi

if [ "$tar" != "no" ]; then
        cd /etc/openvpn/easy-rsa/2.0
        source ./vars
        ./pkitool $client
fi

cp /etc/openvpn/keys/ca.crt /etc/openvpn/dist/$client/keys
cp /etc/openvpn/keys/$client.key /etc/openvpn/dist/$client/keys
cp /etc/openvpn/keys/$client.crt /etc/openvpn/dist/$client/keys
cp /etc/openvpn/README /etc/openvpn/dist/$client

/etc/openvpn/client.sh $client > /etc/openvpn/dist/$client/$client.conf
cd /etc/openvpn/dist/$client
tar czvf $client-vpn.tgz *

I wanted to dynamically generate the client config file – so I also have /etc/openvpn/client.sh

client=$1
echo "
client
dev tap
;dev-node MyTap
proto udp
remote my-server 1194
resolv-retry infinite
nobind
;user nobody
;group nobody
persist-key
persist-tun
ca keys/ca.crt
cert keys/$client.crt
key keys/$client.key
ns-cert-type server
;tls-auth keys/ta.key 1
;cipher x
comp-lzo
verb 3
;mute 20
"

Finally, when you do a “service openvpn start” or “service openvpn stop” it automatically finds *.conf in your /etc/openvpn folder. Also, it automatically runs scripts named “openvpn-startup” and “openvpn-shutdown” respectively. So I did the following:

ln -s /root/bin/bridge-stop /etc/openvpn/openvpn-shutdown
ln -s /root/bin/bridge-start /etc/openvpn/openvpn-startup

So now – all I have to do is hand a tgz file to a buddy and they can connect to my network and be ON THE network – not some funky vpn network that is only on the vpn devices. Sweet if you ask me … sweet. Now I’m off to apply this knowledge to my pfSense device. It is currently grabbing my neighbors open wifi on one radio and broadcasting it on a different radio. My broadcast radio is bridged to the LAN. The wifi is also encrypted – so as to protect my network. The thing that started this whole need for the VPN was the fact that I can’t set port-forwarding on the neighbor’s router. They were smart enough to change the default password, but not add encryption?!?! … anyhow, now with the pfSense box, I will have a permanent VPN tunnel back to my server which will allow me to access the network behind the pfSense box from anywhere in the world – via my server’s network. Muahaha… evil.

I forgot to mention … I added open ports to my firewall.
Here’s my current /etc/sysconfig/iptables file:

# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i tap0 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 1194 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 137 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 138 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 139 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 445 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 53 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 904 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 53 -j ACCEPT
-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -p icmp -j ACCEPT
-A FORWARD -i lo -j ACCEPT
-A FORWARD -i tap0 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

Also – my router that is between my openvpn server and the internet – I have port 1194 port forwarded to 192.168.0.10 (my server’s IP address).

4 Responses to “OpenVPN – Bridging two net”

  1. jr Says:

    Great tutorial. I did the exact same thing a while back and ran into many of the catches you did.
    The bridge-start script did not include a default route, so adding an extra line to this script is necessary. I also had to incorporate some sleep commands for it to work properly. To have the bridge interface created before openvpn starts add:
    post-up $PATH/bridge-start
    to your /etc/network/interfaces file. This will save you from starting the bridge on reboot.

  2. zzzmaestro Says:

    See this from above:

    Finally, when you do a “service openvpn start” or “service openvpn stop” it automatically finds *.conf in your /etc/openvpn folder. Also, it automatically runs scripts named “openvpn-startup” and “openvpn-shutdown” respectively. So I did the following:
    view plaincopy to clipboardprint

    1. ln -s /root/bin/bridge-stop /etc/openvpn/openvpn-shutdown
    2. ln -s /root/bin/bridge-start /etc/openvpn/openvpn-startup

    Since I am starting the openvpn service on startup and since the bridge-start is symbolically linked to the openvpn-startup, it actually DOES start up automatically if you had done these steps. Ensure that you are starting the openvpn service on startup by checking your chkconfig (Type `chkconfig –list | grep openvpn` … it should say “on” for run-levels 2-5)

  3. rrangopw Says:

    thanks for an awsome tutoril. 2 weeks later I found your tutorial and it is the best one yet.
    I have succesfully connected client to server but I am unable to ping

    192.168.1.0—-Lan1
    192.168.1.200–OpenVPN server on LAN1
    connecting to
    192.168.5.0—Lan2

    I think it is a router setting.
    Can you give me some pointers as to the router settings? I have a D-Link 665

    • zzzmaestro Says:

      There could be a couple different problems if you can’t ping from one network to the other. First thing to do is check your route table on your client (in the 192.168.5.x network) and make sure you have a route for the 192.168.1.x network. You should also have a separate adapter, one for the physical connection and a second for the tap device (made by openvpn). If you do `ifconfig tap0` (assuming tap0), the IP address it has should be something in the 192.168.1.x network. If there is no IP there … then you need to check line 10 of the server.conf:
      server-bridge 192.168.0.10 255.255.255.0 192.168.0.21 192.168.0.29 The first IP address is the IP that the server listens on. The second is the netmask. Third IP is the starting IP of the DHCP pool dedicated to the OpenVPN service. Fourth IP is the ending IP dedicated to the OpenVPN service. So, for my example, my clients get IP addresses starting with 192.168.0.21 and they increase with each one that connects until I get up to 192.168.0.29.

      For your setup, that line should look something like:
      server-bridge 192.168.1.200 255.255.255.0 192.168.1.21 192.168.1.29
      You will also want to make sure that on your D-Link router that it is using a DHCP pool that does not interfere with this one. In my example — my router hands out x.x.x.100-200 for the generic pool. I use x.x.x.1-9 for network equipment, 10-19 for servers, over 200 is for printers … etc, you get the idea.

      If everything is setup right, then your clients should have an IP address in the DHCP pool described above. The gateway should be your server’s IP address. Your client will be able to ping anything in the server’s subnet. But, your server will only know your clients by the IP in the same subnet. What I mean is … in your example: ClientA for example would naturally have an IP on its physical address of … lets say 192.168.5.100. It’s Tun0 device should get an IP of 192.168.1.21 (from openvpn .. after connecting) and a default gateway of 192.168.1.200. This client should be able to ping anything on the 192.168.1.x network. However, if you are on the Server’s network, the only way you will be able to reach the ClientA machine is through its IP of 192.168.1.21 — it won’t respond to 192.168.5.100. The only way to get that to work would be … if on your 192.168.1.1 router (assuming that’s where the router is) would be to add a static route … saying the 192.168.5.x network has a gateway of 192.168.1.21. Even then, I’ve found it doesn’t always work perfect.

      But if the OpenVPN client is connecting, you should be pretty good. That means you already have port 1194 outbound open on the 192.168.5.x router already…. and you have the firewall on the 192.168.1.x allowing inbound port 1194 … and you have it port forwarding port 1194 from WAN to 192.168.1.200. That should be all you need.

Leave a Reply