Skip to Content
Skip Breadcrumb

I have asked me several times which scripts can I call in OpenVPN. The documentation is very detailed but it’s big and not intend to be a step by step tutorial, AFAIS (=As far as I see). I write this blog post for me and all others which have the same issue.

Introduction

OpenVPN is a great tool for VPN’s from my point of view. It’s open source, it’s mature, it’s flexible and just great 😍 .

I use it for several solutions and therefore the scripting options are quiet important for me. I read the manual Openvpn24ManPage serveral times and always see some new possibilies like start/stop some process when a route/interface goes up or down.

OpenVPN Script hooks

I will describe here how you can run a NFS mount and unmount when a VPN Connection will be created and more important when the connections goes down for reconnect.

There are several sections in the Openvpn24ManPage which are important for scripts.

  • Script Order of Execution
  • Environmental Variables
config context script_type Info
--up cmd init up this script will be called when the tunnel will be created
--up-restart restart up this script will be called when the tunnel will be recreated
--route-pre-down cmd init route-pre-down this script will be called when routes are removed
--down cmd init down this script will be called when the tunnel goes down
--up-restart restart down this script will be called when the tunnel goes down and up
--route-up cmd not defined route-up this script will be called when the route is created
--ipchange cmd not defined ipchange see https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage and search for ipchange
--learn-address cmd not defined learn-address see https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage and search for learn-address
--client-connect cmd not defined client-connect see https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage and search for client-connect
--client-disconnect cmd not defined client-disconnect see https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage and search for client-disconnect
--tls-verify cmd not defined tls-verify see https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage and search for tls-verify
--auth-user-pass-verify cmd method not defined auth-user-pass-verify see https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage and search for auth-user-pass-verify

With all this hooks I was not able to mount the NFS Share at OpenVPN startup time.

Setup

First of all you will need to create a working openvpn setup. The setup depends on your Plattform and use case so please search for the right solution in the internet Search startpage.

check and mount script

After a successful VPN connection can you run the following script to mount the NFS share

#!/usr/bin/env bash

OPENVPN_ROOT=/etc/openvpn
SCRIPT_ROOT="${OPENVPN_ROOT}/scripts"

if [[ ! -s "${SCRIPT_ROOT}/vpn2server.txt" ]]; then
  echo "Can't read config file"
  exit 1
fi

CONFIG="${SCRIPT_ROOT}/vpn2server.txt"

MNT_EXEC=/bin/mount
# This doesen't work as expected
MNT_ARGS=" -v -t nfs -o proto=tcp,noatime,nodev,noexec,hard"

UMOUNT_EXEC="/bin/umount"
# This doesen't work as expected
UMOUNT_ARGS=" -f "

SYSTEMCTL_EXEC="/bin/systemctl"
LOGGER_EXEC="/usr/bin/logger"
EGREP_EXEC="/bin/egrep"
SLEEP_EXEC="/bin/sleep"

function log {
  ${LOGGER_EXEC} "check_mount $(date "+%Y-%m-%d %H:%M:%S") $1"
}

if [[ ${DEBUG} == "true" ]]; then
  log "$0 start"
fi

function mymount {
  log "Mount ${1}":"${2} to ${3}"
  ${MNT_EXEC} -v -t nfs -o proto=tcp,noatime,nodev,noexec,hard,clientaddr=${1},addr=${1} ${1}":"${2} ${3}
}

function myumount {
  log "Umount ${1}"
  ${UMOUNT_EXEC} -f ${1}
}

for i in $(< "${SCRIPT_ROOT}/vpn2server.txt" ); do

  set -- ${i}
  
  # change here the delimiter for the config file
  IFS=_ ; declare -a MYLINE=($*)

  SIP=$(awk -F"," '/^10.*'${MYLINE[0]}'/{print $1}' < ${OPENVPN_ROOT}/openvpn-status.log)
  echo "test"|curl -sS --max-time 3 telnet://${SIP}:2049

  if [[ $? -eq 0 ]] ; then
    if [[ ${DEBUG} == "true" ]]; then
      log "Server Reachable"
    fi

    ${MNT_EXEC} | ${EGREP_EXEC} -q ${SIP}

    if [[ $? -eq 0 ]] ; then
      if [[ ${DEBUG} == "true" ]]; then
        log "NFS Mounted"
      fi
      break 5
    else
      mymount ${SIP} ${MYLINE[1]} ${MYLINE[2]}
      break 5
    fi
  else

    myumount ${MYLINE[2]}
    log "Stop openvpn@${MYLINE[3]}.service"
    ${SYSTEMCTL_EXEC} stop openvpn@${MYLINE[3]}.service
    ${SLEEP_EXEC} 5
    log "Start openvpn@${MYLINE[3]}.service"
    ${SYSTEMCTL_EXEC} start openvpn@${MYLINE[3]}.service

    counter=0
    # 120 s / 4 s = 30 iterations
    while [[ ${counter} -lt 30 ]] ; do

      echo "test"|curl -sS --max-time 3 telnet://${SIP}:2049

      if [[ $? -eq 0 ]] ; then
        if [[ ${DEBUG} == "true" ]]; then
          log "Server Reachable after restart"
        fi
        mymount ${SIP} ${MYLINE[1]} ${MYLINE[2]}
        break 5
      else
        ${SLEEP_EXEC} 4
        (( counter++ ))
      fi
    done

    exit 0
  fi
done

if [[ ${DEBUG} == "true" ]]; then
  log "$0 stop"
fi
exit 0

The configuration file looks like this

client-server002_/webroot/nfs-export_/mnt/nfsdata10_openvpn-config

This line have al neccessary information for the script to check and mount the NFS share.

The delimiter for the fields is _

client name remote exported fs local mountpoint openvpn configuration
client-server002 /webroot/nfs-export /mnt/nfsdata10 openvpn-config

Why do I need a extra script

The main reason why you can’t mount the NFS share at OpenVPN start up is that the routing information will not be available after a successful VPN connection was created.

ovpn-openvpn[19858]: xxx:33299 [client-server002] Peer Connection Initiated with [AF_INET]xxx:33299
ovpn-openvpn[19858]: client-server002/xxx:33299 MULTI_sva: pool returned IPv4=10.9.0.2, IPv6=(Not enabled)
root[20642]: openvpn-script 2018-02-11 15:01:49 /etc/openvpn/scripts/openvpn-start-stop.sh start
root[20647]: openvpn-script 2018-02-11 15:01:49 ENV: PWD=/etc/openvpn
             SHLVL=1
             X509_0_C=XX
             X509_0_CN=client-server002
             X509_0_L=xxx
             X509_0_O=xxx
             X509_0_OU=xxx
             X509_0_ST=X
             X509_0_emailAddress=xxx
             X509_0_name=xxx
             X509_1_C=XX
             X509_1_CN=xxx
             X509_1_L=xxx
             X509_1_O=xxx
             X509_1_OU=
             X509_1_ST=X
             X509_1_emailAddress=xxx
             X509_1_name=xxx
             _=/usr/bin/env
             common_name=client-server002
             config=/etc/openvpn/openvpn-xxx.conf
             daemon=1
             daemon_log_redirect=0
             daemon_pid=19858
             daemon_start_time=1518357704
             dev=tun0
             dev_type=tun
             ifconfig_broadcast=10.9.0.255
             ifconfig_local=10.9.0.1
             ifconfig_netmask=255.255.255.0
             ifconfig_pool_netmask=255.255.255.0
             ifconfig_pool_remote_ip=10.9.0.2
             link_mtu=1542
             local_port_1=1194
             proto_1=udp
             redirect_gateway=0
             remote_port_1=1194
             script_context=init
             script_type=client-connect
             time_ascii=Sun Feb 11 15:01:49 2018
             time_unix=1518357709
             tls_digest_0=2c:fb:48:46:e1:3e:f7:db:72:a4:c8:d2:d3:22:2
root[20650]: openvpn-script 2018-02-11 15:01:49 ARGS: /tmp/openvpn_cc_c20c1e44fa27703683ed6f589dc9727f.tmp
root[20846]: openvpn-script 2018-02-11 15:01:51 Mount 10.9.0.2:/webroot/nfs-export
root[20848]: openvpn-script 2018-02-11 15:01:51 /bin/mount  -v -t nfs -o proto=tcp,noatime,nodev,noexec,hard,clientaddr=10.9.0.2,addr=10.9.0.2 10.9.0.2:/webroot/nfs-export /mnt/localdir
root[20850]: openvpn-script 2018-02-11 15:01:51 /etc/openvpn/scripts/openvpn-start-stop.sh stop
ovpn-openvpn[19858]: client-server002/xxx:33299 OPTIONS IMPORT: reading client specific options from: /tmp/openvpn_cc_c20c1e44fa27703683ed6f589dc9727f.tmp
ovpn-openvpn[19858]: client-server002/xxx:33299 MULTI: Learn: 10.9.0.2 -> client-server002/xxx:33299
ovpn-openvpn[19858]: client-server002/xxx:33299 MULTI: primary virtual IP for client-server002/xxx:33299: 10.9.0.2
ovpn-openvpn[19858]: client-server002/xxx:33299 PUSH: Received control message: 'PUSH_REQUEST'
ovpn-openvpn[19858]: client-server002/xxx:33299 send_push_reply(): safe_cap=940

You can contact me for any further questions and orders