Subject: [alpine-devel] Updated: Multiple OpenVPN Tunnels

From: Steve Fink <[email-masked]>
Date: Wed, 22 Dec 2010 13:21:13 -0700 (MST)

Ok, I have modified the /etc/init.d/openvpn script to support both the original Gentoo symlinked style and the multiple .conf file style. 

The script is below. 

Best, 

Steve 

#!/sbin/runscript 

# OpenVPN start/stop script 
# Adapted to Gentoo by James Yonan 
# Modified by Steve Fink to support /etc/conf.d/openvpn 
# and to support multiple .conf files or Gentoo style symlinks 

# USAGE: 
# If the file openvpn.conf exists then it is assumed that you are 
# using the Gentoo style symlinking way of starting 
# 
# If the file openvpn.conf does not exist ie you have your files named 
# server.conf client.conf or anythingelse.conf then all tunnels are started 

# This has been modified so it does the following if no openvpn.conf 
# file exists: 
# 
# - Starts an OpenVPN process for each .conf file in $CONFDIR 
# 
# - If /etc/openvpn/xxx.start exists for a xxx.conf file then it executes 
# it before starting OpenVPN (useful for doing openvpn --mktun...). 
# 
# - If /etc/openvpn/xxx.stop exists for a xxx.conf file then it executes 
# it after stopping OpenVPN (useful for doing openvpn --rmtun...). 
# 

# OpenRC options 
opts="start stop restart" 

# Determine which variables to set for Gentoo symlinked or multiple .conf files 
if [ ! -e /etc/openvpn/openvpn.conf ]; then 
# Set variables for multiple .conf files 
# Default location of openvpn 
DEF_OPENVPN=/usr/sbin/openvpn 

# Default pid directory 
DEF_PIDDIR=/var/run/openvpn 

# Default conf directory 
DEF_CONFDIR=/etc/openvpn 
else 
# Set variables for Gentoo symlinked 
VPNDIR="/etc/openvpn" 
VPN="${SVCNAME#*.}" 
if [ -n "${VPN}" ] && [ "${SVCNAME}" != "openvpn" ]; then 
VPNPID="/var/run/openvpn.${VPN}.pid" 
else 
VPNPID="/var/run/openvpn.pid" 
fi 
VPNCONF="${VPNDIR}/${VPN}.conf" 
fi 

depend() { 
need net 
use dns 
after sshd 
} 

chkconfd() { 
if [ -z $PIDDIR ]; then 
PIDDIR=$DEF_PIDDIR 
einfo "No pid file directory defined in /etc/conf.d/openvpn using default $PIDDIR." 
fi 
if [ -z $OPENVPN ]; then 
OPENVPN=$DEF_OPENVPN 
einfo "No path to OpenVPN defined in /etc/conf.d/openvpn using default $OPENVPN." 
fi 
if [ -z $CONFDIR ]; then 
CONFDIR=$DEF_CONFDIR 
einfo "No config file directory defined in /etc/conf.d/openvpn using default $CONFDIR." 
fi 

} 

chktundev() { 
if [ ! -e /dev/net/tun ]; then 
if ! modprobe tun ; then 
eerror "TUN/TAP module unable to load into kernel" 
return 1 
fi 
fi 
if [ -h /dev/net/tun ] && [ -c /dev/misc/net/tun ]; then 
ebegin "Detected broken /dev/net/tun symlink, fixing..." 
rm -f /dev/net/tun 
ln -s /dev/misc/net/tun /dev/net/tun 
eend $? 
fi 
} 

start() { 

# Determine whether it's Gentoo symlinked or multiple .conf files 
if [ ! -e /etc/openvpn/openvpn.conf ]; then 
# Start multiple .conf files 
chkconfd 
chktundev || return 1 
ebegin "Starting OpenVPN" 

# Load the TUN/TAP module 
/sbin/modprobe tun >/dev/null 2>&1 

if [ ! -d $PIDDIR ]; then 
mkdir $PIDDIR 
fi 

cd $CONFDIR 

# Start every .conf file in $CONFDIR and run .start if available 
local errors=0 
local successes=0 
local retstatus=0 
for c in `/bin/ls *.conf 2>/dev/null`; do 
VPN=${c%%.conf} 
ebegin "Starting VPN: $VPN" 
if [ -f "$VPN.start" ]; then 
. $VPN.start 
fi 
rm -f $PIDDIR/$VPN.pid 
$OPENVPN --daemon OpenVPN-$VPN --writepid $PIDDIR/$VPN.pid --config $CONFDIR/$c --cd $CONFDIR 
result=$? 
if [ $result = 0 ]; then 
successes=1 
else 
errors=1 
FAILED="$FAILED $VPN" 
fi 
eend $result 
done 

# Decide status based on errors/successes. 
# If at least one tunnel succeeded, we return success. 
# If some tunnels succeeded and some failed, we return success but give a warning. 
if [ $successes = 1 ]; then 
if [ $errors = 1 ]; then 
ewarn "The VPN$FAILED failed to start" 
fi 
else 
retstatus=1 
if [ $errors = 0 ]; then 
ewarn "Note: No OpenVPN configuration files were found in $CONFDIR" 
fi 
fi 
eend $retstatus "Error starting OpenVPN" 
else 
# Start Gentoo symlinked openvpn.conf 
ebegin "Starting ${SVCNAME}" 

chktundev || return 1 

if [ ! -e "${VPNCONF}" ]; then 
eend 1 "${VPNCONF} does not exist" 
return 1 
fi 

local args="" 
# If the config file does not specify the cd option, we do 
# But if we specify it, we override the config option which we do not want 
if ! grep -q "^[ \t]*cd[ \t].*" "${VPNCONF}" ; then 
args="${args} --cd ${VPNDIR}" 
fi 

start-stop-daemon --start --exec /usr/sbin/openvpn --pidfile "${VPNPID}" \ 
-- --config "${VPNCONF}" --writepid "${VPNPID}" --daemon ${args} 
eend $? "Check your logs to see why startup failed" 
fi 
} 

stop() { 
# Determine if it's Gentoo symlinked or multiple .conf files 
if [ ! -e /etc/openvpn/openvpn.conf ]; then 
# Stop multiple .conf files 
ebegin "Stopping OpenVPN" 
for PIDF in `find $PIDDIR -name '*.pid' 2>/dev/null`; do 
if [ -s $PIDF ]; then 
VPN=${PIDF%%.pid} 
VPN=${VPN##$PIDDIR/} 
einfo "Stopping VPN: $VPN ..." 
kill `cat $PIDF` >/dev/null 2>&1 
if [ -f "${CONFDIR}/${VPN}.stop" ]; then 
. ${CONFDIR}/${VPN}.stop 
fi 
eend $? 
rm -rf $PIDF >/dev/null 2>&1 
if [ `ls -A "$PIDDIR"|wc -w` = 0 ]; then 
rm -rf "$PIDDIR" 
fi 
fi 
done 
eend 0 
else 
# Stop Gentoo symlinked 
ebegin "Stopping ${SVCNAME}" 
start-stop-daemon --stop --exec /usr/sbin/openvpn --pidfile "${VPNPID}" 
eend $? 
fi 
}

---

From: Natanael Copa <[email-masked]>
Date: Thu, 6 Jan 2011 10:58:45 +0100

On Wed, 22 Dec 2010 13:21:13 -0700 (MST)
Steve Fink <[email-masked]> wrote:

> Ok, I have modified the /etc/init.d/openvpn script to support both
> the original Gentoo symlinked style and the multiple .conf file
> style. 
> 
> The script is below. 

Thanks!

Finally I took some time to look at it. I still think the script needs
some work.

> # and to support multiple .conf files or Gentoo style symlinks 

I'm not sure you really understand how the gentoo symlink approach
works. Gentoo style symlinks means you can have multiple .conf files.

ln -s openvpn /etc/init.d/openvpn.server
ln -s openvpn /etc/init.d/openvpn.client

will use server.conf and client.conf in /etc/openvpn dir.

You start the server.conf setup with '/etc/init.d/openvpn.server start',
you start the client.conf with '/etc/init.d/openvpn.client start' and
stop them similarily.

This works prefectly fine without any /etc/openvpn/openvpn.conf

> # If the file openvpn.conf does not exist ie you have your files
> named # server.conf client.conf or anythingelse.conf then all tunnels
> are started 

you could have a gentoo link style system
with no /etc/openvpnc/openvpn.conf file
at all, a /etc/openvpn/anythingelse.conf and a
'openvpn.anythingelse' symlink in /etc/init.d that points to 'openvpn'

Then you 'rc-update add openvpn.anythingelse' and on boot only the
anythingelse.conf will be started.

> # This has been modified so it does the following if no openvpn.conf 

Checking for openvpn.conf is bad since you could have a gentoo style
symlink without any openvpnc.conf.

> # - If /etc/openvpn/xxx.start exists for a xxx.conf file then it
> executes # it before starting OpenVPN (useful for doing openvpn
> --mktun...). # 
> # - If /etc/openvpn/xxx.stop exists for a xxx.conf file then it
> executes # it after stopping OpenVPN (useful for doing openvpn
> --rmtun...). # 
> 
> # OpenRC options 
> # Determine which variables to set for Gentoo symlinked or
> multiple .conf files if [ ! -e /etc/openvpn/openvpn.conf ]; then 

Why not use same pid directory for both gentoo style all-or-nothing
style?

> VPNCONF="${VPNDIR}/${VPN}.conf" 

Why does it need to start after sshd?
Why did you remove the "before netmount" (which i assume is needed if
you want mount a network filesystem over openvpn tunnels)
 
> if [ -z $PIDDIR ]; then 

I think script will choke here if PIDDIR is really zero. (maybe not but
older versions of ash did so. should be in "": if [ -z "$PIDDIR" ]....

> PIDDIR=$DEF_PIDDIR 
> einfo "No pid file directory defined in /etc/conf.d/openvpn using
> default $PIDDIR." fi 

I dont think that info is useful. You normally dont mess with pid file
locations (why would you?).

> if [ -z $OPENVPN ]; then 
> OPENVPN=$DEF_OPENVPN 
> einfo "No path to OpenVPN defined in /etc/conf.d/openvpn using
> default $OPENVPN." fi 
> if [ -z $CONFDIR ]; then 
> CONFDIR=$DEF_CONFDIR 
> einfo "No config file directory defined in /etc/conf.d/openvpn using
> default $CONFDIR." fi 

I dont think we need to tell that defaults are beeing used.

> $OPENVPN --daemon OpenVPN-$VPN --writepid $PIDDIR/$VPN.pid --config
> $CONFDIR/$c --cd $CONFDIR result=$? 
> if [ $result = 0 ]; then 
> successes=1 
> else 
> errors=1 
> FAILED="$FAILED $VPN" 
> fi 
> eend $result 
> done 
> 
> # If some tunnels succeeded and some failed, we return success but
> give a warning. if [ $successes = 1 ]; then 
> if [ $errors = 1 ]; then 
> # But if we specify it, we override the config option which we do not
> want if ! grep -q "^[ \t]*cd[ \t].*" "${VPNCONF}" ; then 
> start-stop-daemon --start --exec /usr/sbin/openvpn --pidfile
> "${VPNPID}" \ -- --config "${VPNCONF}" --writepid "${VPNPID}"
> --daemon ${args} eend $? "Check your logs to see why startup failed" 
> fi 
> } 
> 
> stop() { 
> start-stop-daemon --stop --exec /usr/sbin/openvpn --pidfile
> "${VPNPID}" eend $? 
> fi 
> } 
> 
> 

---
Unsubscribe:  [email-masked]
Help:         [email-masked]
---

---

From: Steve Fink <[email-masked]>
Date: Thu, 6 Jan 2011 09:46:23 -0700 (MST)

Natanael, 

Thanks for the feed back. 

I believe I do understand the Gentoo symlink approach. I tested it with this script and multiple VPN symlinks and it works fine, provided that the main openvpn file is openvpn.conf. 

I chose to look for the openvpn.conf because the default file is openvpn.conf and acf-openvpn creates openvpn.conf when the system is configured via the web browser. If you have a better method, please advise. 

I was thinking we would have to modify the documentation on the wiki to explain the two different methodologies and how to configure both for multiple tunnels. Currently the wiki shows only the method I use which does not work for the original init.d script. 

I created a pid directory for openvpn when using the non-symlink method for the purpose of organization of the .pid files and keep /var/run from having potentially dozens of openvpn .pid's strewn about. I was trying to make the symlink method as close to what was currently happening as possible, this can be changed to /var/run/openvpn as well if you like. 

I moved it after sshd because I've seen times where OpenVPN failed and stopped anything further from starting. Failing to start before sshd would lock an admin out of sshd, therefore unable to connect and fix the problem. I believe removing before netmount was an oversight. 

Best, 

Steve 

Thanks!