Hi All,
Spent this afternoon working on some scripts to provide better control of OpenVPN connections and wanted to share and get some feed back. First a DISCLAMER! This is the first time I've really done any shell scripting so let me know of any style improvements I can make you wont offend me. Hope some other people find this useful! let me know if you've got any other feature ideas as well!
Thanks!
Quick Feature overview.
*init.d script that will start openvpn servers and clients on bootup (with appropriate /etc/rc.d/ link)
*Ability to control which individual connections start on boot up so not all connections have to always start
*ovpnctl script to control connections on a running router. (stop, start, list, status)
All the scripts assume that the openvpn configuration is stored in /etc/openvpn/ with each connection having a config file [connectionName].conf
So first the init.d script. It's primary purpose is to scan the connections (/etc/openvpn/*.conf) for files that have the execute bit set and start them. Only configs with the execute bit set will be started at boot time. All others can be manually started later with the ovpnctl script below.
/etc/init.d/openvpn
#!/bin/sh /etc/rc.common
# Copyright (C) 2007 OpenWrt.org
# Copyright (C) 2007 CICAT Networks (joe@cicat.com)
. /lib/network/openvpn.sh
start () {
local connList=$(ovpn_conn_list)
local connName
for conn in $connList
do
if [ -x "$conn" ]
then
connName=`echo "$conn" | cut -d '/' -f 4 | cut -d '.' -f 1`
ovpn_conn_start "$connName"
fi
done
}
stop () {
killall /usr/bin/openvpn && rm /var/run/*.ovpn.pid
}
Second is the ovpnctl script which allows you to stop, start, list, and retrieve status on the connections. So some sample executions.
root@OpenWrt:/etc/init.d# ovpnctl help
Syntax ./ovpnctl [command]
Available commands:
start Starts a openvpn connection.
example: ./ovpnctl start tunnel_name
stop Bring down a openvpn connection.
example: ./ovpnctl stop tunnel_name
list List available connections.
example: ./ovpnctl list
status Display the status of each connection.
example: ./ovpnctl status
root@OpenWrt:/etc/init.d# ovpnctl status
Connection Status PID
cicats2s running 1207
testtest down
And the code
/sbin/ovpnctl
#!/bin/sh
# Copyright (C) 2007 OpenWrt.org
# Copyright (C) 2007 CICAT Networks (joe@cicat.com)
. /lib/network/openvpn.sh
start() {
local CONN="$1"
if [ -e "/etc/openvpn/${CONN}.conf" ]
then
ovpn_conn_start "$CONN"
else
echo "Unable to find connection ${CONN}"
echo "try running 'ovpnctl list' to see a list of available connections"
fi
}
stop() {
local CONN="$1"
if [ -e "/var/run/${CONN}.ovpn.pid" ]
then
ovpn_conn_stop "$CONN"
else
echo "${CONN} does not appear to be running"
echo "try running 'ovpnctl status' to see a list of running connections"
fi
}
list() {
for i in `ls /etc/openvpn/*.conf`
do
name=`echo "$i" | cut -d '/' -f 4 | cut -d '.' -f 1`
echo "$name"
done
}
status() {
cat <<EOF
Connection Status PID
EOF
for i in `ls /etc/openvpn/*.conf`
do
name=`echo "$i" | cut -d '/' -f 4 | cut -d '.' -f 1`
if [ -e "/var/run/${name}.ovpn.pid" ]
then
echo "${name} running $(ovpn_get_pid ${name})"
else
echo "${name} down"
fi
done
}
help () {
cat <<EOF
Syntax ./ovpnctl [command]
Available commands:
start Starts a openvpn connection.
example: ./ovpnctl start tunnel_name
stop Bring down a openvpn connection.
example: ./ovpnctl stop tunnel_name
list List available connections.
example: ./ovpnctl list
status Display the status of each connection.
example: ./ovpnctl status
EOF
}
ACTION="$1"
case "$ACTION" in
start) start "$2";;
stop) stop "$2";;
list) list;;
status) status;;
*) help;;
esac
Finally the helper functions. they provide ways to stop and start connections, get a list of connections, and get a PID for a connection.
/lib/network/openvpn.sh
#!/bin/sh
# Copyright (C) 2007 OpenWrt.org
# Copyright (C) 2007 CICAT Networks (joe@cicat.com)
ovpn_conn_start() {
local CONN="$1"
if [ -e "/etc/openvpn/${CONN}.conf" ]
then
/usr/sbin/openvpn --daemon "${CONN}" --config "/etc/openvpn/${CONN}.conf" --writepid "/var/run/${CONN}.ovpn.pid"
fi
}
ovpn_conn_stop() {
local CONN="$1"
if [ -e "/var/run/${CONN}.ovpn.pid" ]
then
kill -TERM "$(ovpn_get_pid $CONN)" && rm "/var/run/${CONN}.ovpn.pid"
fi
}
ovpn_conn_list() {
for i in `ls /etc/openvpn/*.conf`
do
list="$list $i"
done
echo "$list"
}
ovpn_get_pid() {
local CONN="$1"
if [ -e "/var/run/${CONN}.ovpn.pid" ]
then
echo "$(head -n1 -q /var/run/${CONN}.ovpn.pid 2>/dev/null)"
fi
}