The problem I have run into in the past and very recently is that the documentation for configuring OVPN in bridged mode on the server side is very incomplete. Most of the scripts on the internet simply do not work the way I need them to in my setup... My personal server has only one NIC and sits behind the router. Additionally, most of the instructions do not include the facts that IP forwarding and default gateway settings need to be enabled in order to use the VPN to securely browse the Internet.
To get started, I highly recommend reading this guide. Complete the installation and "Public Key Infrastructure Setup" sections, then come back here. Refer back to that guide for client setup later on.
The OpenVPN documentation page also has excellent information on client and server setup for anything not covered here. This guide will focus mostly on the network setup part, which was the most challenging part for me to accomplish.
What this guide covers:
- Network setup for a single NIC server to run OpenVPN
- Scripts to configure the network and OPVN services
What this guide does NOT cover:
- Installing OpenVPN from source or repo
- Installing OVPN on Windows
- Nice GUIs to do all this for you
- Setting up the PKI for the server
On my home server I chose to run Ubuntu 12.04 LTS server edition as the OS. Keep in mind that it has no GUI out-of-the-box, so everything is done in terminal. Also note that this configuration should be done locally, not over SSH remotely, as connections will inevitably fail upon changing the network configs.
Starting from a fresh install of OVPN from repository, we will make the script required to create a tap device, a network bridge, and bridge the tap and ethernet devices together.
Copy the script below into a file called openvpn-bridge and place it inside the /etc/openvpn/ directory. The items highlighted in pink are values that you will need to change according to your setup. Make the script executable by running a chmod 755 openvpn-bridge inside the openvpn directory after you make the 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="eth0"
eth_ip="10.1.1.31"
eth_netmask="255.0.0.0"
eth_broadcast="10.255.255.255"
#The "gw" setting is crucial here. This should be the IP address of your #network's router. This setting makes it possible to reach the internet through #the VPN instead of just local resources.
gw="10.1.1.1"
gw="10.1.1.1"
case "$1" in
start)
for t in $tap; do
openvpn --mktun --dev $t
done
brctl addbr $br
brctl addif $br $eth
for t in $tap; do
brctl addif $br $t
done
for t in $tap; do
ifconfig $t 0.0.0.0 promisc up
done
ifconfig $eth 0.0.0.0 promisc up
ifconfig $br $eth_ip netmask $eth_netmask broadcast $eth_broadcast
route add default gw $gw
;;
stop)
ifconfig $br down
brctl delbr $br
for t in $tap; do
openvpn --rmtun --dev $t
done
ifconfig $eth $eth_ip netmask $eth_netmask broadcast $eth_broadcast
route add default gw $gw
;;
*)
echo "usage openvpn-bridge {start|stop}"
exit 1
;;
esac
exit 0
########################################################################
Next you will need to replace the default init script for OVPN with this one modified to include the bridge starting script. You should backup the original init script just in case something goes wrong. Run a cp /etc/init.d/openvpn /home/$USER/openvpn to backup the script. ( $USER will be replaced with your username.) After you backup the original script, then copy and paste this one in its place.
I did not create the following script. Credits for the script are included within the script itself.
#########################################################################
#!/bin/sh -e
#
# Original version by Robert Leslie
# <rob@mars.org>, edited by iwj and cs
# Modified for openvpn by Alberto Gonzalez Iniesta <agi@inittab.org>
# Modified for restarting / starting / stopping single tunnels by Richard Mueller <mueller@teamix.net>
# Modified to add bridge control by Josh Vickery <vickeryj@freeshell.org>
test $DEBIAN_SCRIPT_DEBUG && set -v -x
DAEMON=/usr/sbin/openvpn
DESC="virtual private network daemon"
CONFIG_DIR=/etc/openvpn
BRIDGE_CTL=/etc/openvpn/openvpn-bridge
test -x $DAEMON || exit 0
test -d $CONFIG_DIR || exit 0
# Source defaults file; edit that file to configure this script.
AUTOSTART="all"
STATUSREFRESH=10
if test -e /etc/default/openvpn ; then
. /etc/default/openvpn
fi
start_vpn () {
if grep -q '^[ ]*daemon' $CONFIG_DIR/$NAME.conf ; then
# daemon already given in config file
DAEMONARG=
else
# need to daemonize
DAEMONARG="--daemon ovpn-$NAME"
fi
if grep -q '^[ ]*status ' $CONFIG_DIR/$NAME.conf ; then
# status file already given in config file
STATUSARG=""
elif test $STATUSREFRESH -eq 0 ; then
# default status file disabled in /etc/default/openvpn
STATUSARG=""
else
# prepare default status file
STATUSARG="--status /var/run/openvpn.$NAME.status $STATUSREFRESH"
fi
$BRIDGE_CTL start
$DAEMON --writepid /var/run/openvpn.$NAME.pid \
$DAEMONARG $STATUSARG --cd $CONFIG_DIR \
--config $CONFIG_DIR/$NAME.conf || echo -n " FAILED->"
echo -n " $NAME"
}
stop_vpn () {
kill `cat $PIDFILE` || true
rm $PIDFILE
[ -e /var/run/openvpn.$NAME.status ] \
&& rm /var/run/openvpn.$NAME.status
$BRIDGE_CTL stop
}
case "$1" in
start)
echo -n "Starting $DESC:"
# autostart VPNs
if test -z "$2" ; then
# check if automatic startup is disabled by AUTOSTART=none
if test "x$AUTOSTART" = "xnone" -o -z "$AUTOSTART" ; then
echo " Autostart disabled."
exit 0
fi
if test -z "$AUTOSTART" -o "x$AUTOSTART" = "xall" ; then
# all VPNs shall be started automatically
for CONFIG in `cd $CONFIG_DIR; ls *.conf 2> /dev/null`; do
NAME=${CONFIG%%.conf}
start_vpn
done
else
# start only specified VPNs
for NAME in $AUTOSTART ; do
if test -e $CONFIG_DIR/$NAME.conf ; then
start_vpn
else
echo -n " (failure: No such VPN: $NAME)"
fi
done
fi
#start VPNs from command line
else
while shift ; do
[ -z "$1" ] && break
if test -e $CONFIG_DIR/$1.conf ; then
NAME=$1
start_vpn
else
echo -n " (failure: No such VPN: $1)"
fi
done
fi
echo "."
;;
stop)
echo -n "Stopping $DESC:"
if test -z "$2" ; then
for PIDFILE in `ls /var/run/openvpn.*.pid 2> /dev/null`; do
NAME=`echo $PIDFILE | cut -c18-`
NAME=${NAME%%.pid}
stop_vpn
echo -n " $NAME"
done
else
while shift ; do
[ -z "$1" ] && break
if test -e /var/run/openvpn.$1.pid ; then
PIDFILE=`ls /var/run/openvpn.$1.pid 2> /dev/null`
NAME=`echo $PIDFILE | cut -c18-`
NAME=${NAME%%.pid}
stop_vpn
echo -n " $NAME"
else
echo -n " (failure: No such VPN is running: $1)"
fi
done
fi
echo "."
;;
# We only 'reload' for running VPNs. New ones will only start with 'start' or 'restart'.
reload|force-reload)
echo -n "Reloading $DESC:"
for PIDFILE in `ls /var/run/openvpn.*.pid 2> /dev/null`; do
NAME=`echo $PIDFILE | cut -c18-`
NAME=${NAME%%.pid}
# If openvpn if running under a different user than root we'll need to restart
if egrep '^( |\t)*user' $CONFIG_DIR/$NAME.conf > /dev/null 2>&1 ; then
stop_vpn
sleep 1
start_vpn
echo -n "(restarted)"
else
kill -HUP `cat $PIDFILE` || true
echo -n " $NAME"
fi
done
echo "."
;;
restart)
shift
$0 stop ${@}
sleep 1
$0 start ${@}
;;
cond-restart)
echo -n "Restarting $DESC:"
for PIDFILE in `ls /var/run/openvpn.*.pid 2> /dev/null`; do
NAME=`echo $PIDFILE | cut -c18-`
NAME=${NAME%%.pid}
stop_vpn
sleep 1
start_vpn
done
echo "."
;;
*)
echo "Usage: $0 {start|stop|reload|restart|force-reload|cond-restart}" >&2
exit 1
;;
esac
exit 0
# vim:set ai sts=2 sw=2 tw=0:
############################################################################
Lastly, configure the server.conf file found in /etc/openvpn/. Mine looks like this. You will of course need to provide your own values for the IP address fields highlighted.
###############################################
port 1194
proto udp
dev tap0
ca easy-rsa/ca.crt
cert easy-rsa/server.crt
key easy-rsa/server.key # This file should be kept secret
dh easy-rsa/dh1024.pem
ifconfig-pool-persist ipp.txt
#The first IP address is your server's IP. The next is of course the subnet mask
#the final two addresses are the range of IP addresses your server will
#assign to VPN clients. These should be outside the normal DHCP range
#of your network.
#assign to VPN clients. These should be outside the normal DHCP range
#of your network.
server-bridge 192.168.17.20 255.255.255.0 192.168.17.50 192.168.17.100
;client-to-client
keepalive 10 120
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
# Set the appropriate level of log
# file verbosity.
#
# 0 is silent, except for fatal errors
# 4 is reasonable for general usage
# 5 and 6 can help to debug connection problems
# 9 is extremely verbose
verb 3
# Silence repeating messages. At most 20
# sequential messages of the same message
# category will be output to the log.
;mute 20
######################################################################
The operation to perform is to enable IP forwarding permanently. Edit /etc/sysctl.conf and change the line net.ipv4.ip_forward = 0 from 0 to 1. If the line does not exist, add it.
Now, if everything was set up properly, you should be able to run OVPN by typing service openvpn start. Check ifconfig to ensure that all the network adapters came online. Yours should look like this if everything went right. The network bridging script creates the tap0 device and the br0 device.
br0 Link encap:Ethernet HWaddr 1e:27:63:75:bb:06
inet addr:192.168.17.20 Bcast:192.168.17.255 Mask:255.255.255.0
inet6 addr: fe80::1c27:63ff:fe75:bb06/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:95060 errors:0 dropped:0 overruns:0 frame:0
TX packets:63227 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:73829583 (73.8 MB) TX bytes:26425634 (26.4 MB)
eth0 Link encap:Ethernet HWaddr 6c:62:6d:40:59:40
inet6 addr: fe80::6e62:6dff:fe40:5940/64 Scope:Link
UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1
RX packets:133544 errors:0 dropped:0 overruns:0 frame:0
TX packets:73376 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:98037746 (98.0 MB) TX bytes:27640334 (27.6 MB)
Interrupt:41
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:7685 errors:0 dropped:0 overruns:0 frame:0
TX packets:7685 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:825616 (825.6 KB) TX bytes:825616 (825.6 KB)
tap0 Link encap:Ethernet HWaddr 1e:27:63:75:bb:06
inet6 addr: fe80::1c27:63ff:fe75:bb06/64 Scope:Link
UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1
RX packets:10753 errors:0 dropped:0 overruns:0 frame:0
TX packets:58635 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:1333362 (1.3 MB) TX bytes:22906209 (22.9 MB)
Once you have verified the server's network setup, try connecting a client to it. If the client is unable to connect with ~15 seconds, you may need to check the OVPN logs on the server and client. If your server is behind a router like mine, don't forget to forward port 1194 on the router to the LAN IP address of your server. If you still have problems, be patient and ask Google for help.
Please email me with any suggestions, omissions, comments or concerns.
Please email me with any suggestions, omissions, comments or concerns.
I got an error on line 21 for openvpn-bridge script. Syntax error: word unexpected (expecting "in")
ReplyDeleteSorry it is line 26
ReplyDelete