58

How can I associate a script to OpenVPN so that it runs when the VPN is connected successfully?

Lekensteyn
  • 171,743
  • 65
  • 311
  • 401
Oxwivi
  • 17,589
  • 53
  • 136
  • 197

6 Answers6

75

network-manager-openvpn does not provide such functionality, you have to use openvpn directly.

Pass --script-security 2 --up /path/to/your/script to it when connecting. If you're using a configuration file located at /etc/openvpn/, append the next lines to your configuration file:

script-security 2
# run /etc/openvpn/up.sh when the connection is set up
up /etc/openvpn/up.sh

From the OpenVPN manpage:

--script-security level [method]
              This  directive offers policy-level control over OpenVPN’s usage
              of external programs and scripts.  Lower level values  are  more
              restrictive,  higher  values  are more permissive.  Settings for
              level:

              0 -- Strictly no calling of external programs.
              1 -- (Default) Only call built-in executables such as  ifconfig,
              ip, route, or netsh.
              2  --  Allow  calling  of  built-in executables and user-defined
              scripts.
              3 -- Allow passwords to be passed to scripts  via  environmental
              variables (potentially unsafe).
       --up cmd
              Shell  command  to run after successful TUN/TAP device open (pre
              --user UID change).  The up  script  is  useful  for  specifying
              route  commands  which  route  IP  traffic  destined for private
              subnets which exist at the other end of the VPN connection  into
              the tunnel.
Script Order of Execution
       --up   Executed after TCP/UDP socket bind and TUN/TAP open.
       --down Executed after TCP/UDP and TUN/TAP close.

There are more events for script execution, those can be found on the manual page.

Create /etc/openvpn/up.sh, and give it execute permissions (say, 755 or 700). Example content for adding an IPv6 address and route (shown for educational purposes, do not copy it directly):

#!/bin/sh
# add an IPv6 address to device $dev (environment variable)
ip -6 addr add 2001:db8::1:2/112 dev $dev
# and the IPv6 route for this net using gateway 2001:db8::1
ip -6 route add 2001:db8::1:0/112 via 2001:db8::1 dev $dev

Note that this up script is run as root. If you have not specified a User and Group setting, OpenVPN will run scripts like down as root too.

Lekensteyn
  • 171,743
  • 65
  • 311
  • 401
  • If you do not know how to use openvpn directly, add your current configuration details: Connection type (e.g. X509-certificates), Gateway port, LZO-compression, force of TCP, use of tap device, cipher, HMAC and TLS. Mention your IP settings too if they are not automatic. FOr your privacy, leave out your actual addresses. – Lekensteyn Mar 02 '11 at 18:39
  • Okay fine, I decided to use OpenVPN directly (and yes, I do have the .conf file), but will it automatically reconnect if the connection is lost? And how do I make it connect automatically whenever there's internet connection? And finally, I did not understand where I have to add the lines you mentioned in the answer. – Oxwivi Mar 05 '11 at 13:44
  • I have expanded the answer to use `openvpn` directly. When setting up a server, I noticed that OpenVPN will try to reconnect when the server went down. Not sure if OpenVPN continues trying when your network interface goes down. – Lekensteyn Mar 05 '11 at 14:26
  • My issue is not when network interface goes down - it does try to reconnect when internet connection is lost and regained. I just want to connect to the VPN whenever I get internet connection. – Oxwivi Mar 05 '11 at 16:09
  • Oh, and does the script apply to all VPN connection? And *please* tag @Oxwivi when replying, I won't get notified otherwise. – Oxwivi Mar 05 '11 at 16:10
  • @Oxwivi: I just tested it: if network-manager (re-)connects to the Internet, the route to the server gets deleted which causes OpenVPN to fail in connecting to the server (probably because I've configured OpenVPN to encrypt all of my traffic). After manually adding the route to, it works again. I think you could write a trigger for network-manager. To add the route, run: `sudo ip route add /32 via dev `. `` is the IP address of the local gateway, like `192.168.1.1`. `` is your NIC, like `eth0` or `wlan0`. – Lekensteyn Mar 05 '11 at 16:25
  • @Oxwivi: if you meant the `/etc/openvpn/up.sh` script, no. It only applies to the VPN defined in `/etc/openvpn/client.conf`. Other VPNs (e.g. `/etc/openvpn/company.conf`) are unaffected. – Lekensteyn Mar 05 '11 at 16:27
  • For what reason do I add route? – Oxwivi Mar 05 '11 at 16:37
  • @Oxwivi: if you have no full-encrypted connection, you do not have to worry about the route. Otherwise, if you do not add this route, your computer does not know how to reach the server and will respond with a "No route to host" error. As shown in my answer, you can specify a script using `up` (run after establishing a connection). – Lekensteyn Mar 05 '11 at 16:38
  • @Lekensteyn, the VPN in question is a commercial service - I'm using the free version. I do not not the ins and outs of OpenVPN config files well - are you willing to take a look at it for me? And I do not understand `script-security 2`, `up` and `down` stuff. – Oxwivi Mar 06 '11 at 07:59
  • There is a [RTFM](http://manpages.ubuntu.com/manpages/maverick/en/man8/openvpn.8.html): `man openvpn`. Added more details to my answer. – Lekensteyn Mar 06 '11 at 08:24
  • I need to use the first script in this answer: http://askubuntu.com/questions/26870/exempt-programs-from-using-active-vpn-connection/27735#27735 Should I use `up` or `down`? – Oxwivi Mar 06 '11 at 08:57
  • Well, you mentioned "so that it runs when the VPN is connected successfully", so I guess it should be `up`. – Lekensteyn Mar 06 '11 at 09:01
  • Thanks! I'll award you the bounty when it's possible (after 24 hours) for all the trouble. Not that it matters much in real life... Anyway, two last things, I want OpenVPN to start after I boot and found an internet connection, and this VPN requires username/password authentication, how do I set it up? – Oxwivi Mar 06 '11 at 09:05
  • Please read the [manual](http://manpages.ubuntu.com/manpages/maverick/en/man8/openvpn.8.html). You can pass it in two ways, either putting the password plaintext in the command or let OpenVPN read it from file. I recommend the latter. Add `auth-user-pass /etc/openvpn/credentials.txt` to your conffile and create `/etc/openvpn/credentials.txt` with the username on the first line and the password on the second. (I didn't know this before, I read it in the manual :) ) – Lekensteyn Mar 06 '11 at 09:13
  • Well, my point of asking was that if the VPN is going to be automatically connected, I won't get the chance of manually entering the authentication in command line. Thanks for all the help! – Oxwivi Mar 06 '11 at 11:01
  • Just so you know, using `up`, I could not get it to work at all, it said script could not execute external program or something. – Oxwivi Mar 12 '11 at 09:23
  • Make sure the script is executable: `chmod +x script`. Note that exit codes other than 0 indicates a failure. – Lekensteyn Mar 12 '11 at 11:05
  • It worked with `down` though, so I left it like that. – Oxwivi Mar 12 '11 at 11:26
  • @Oxwivi: `down` is called when the connection is lost. The manual describes the order of these events. – Lekensteyn Mar 12 '11 at 11:49
  • Ah, I see... My incompetency's limit is still to be sighted... – Oxwivi Mar 12 '11 at 12:39
6

As that is a quite old thread I'm not sure if still of interest. If you still want to use the NetworkManager to connect to a VPN you can add a simple udev rule like that:

KERNEL=="vpn0", RUN+="/PATH_TO_THE_SCRIPT/SCRIPT_NAME"

This should run any script after the VPN is created.

Thomas
  • 61
  • 1
  • 1
6

To the question: "How can I associate a script to OpenVPN so that it runs when the VPN is connected successfully?" I want to point out that Lekensteyn provided an excellent answer. But, at the time his answer was composed, it lacked a little clarity on how openvpn command line arguments should be provided to start openvpn on an ubuntu machine, especially so that it works the same after reboots.


Openvpn command line arguments on Ubuntu:

Naturally, one can start openvpn from a command line with any avalable legal options. But, on an Ubuntu machine, if one wants to start openvpn with the same command line arguments after a reboot, they should consider editing the file /etc/default/openvpn. Examine following lines:

# Optional arguments to openvpn's command line
OPTARGS="" 

From the community openvpn man page on --script-security

--script-security level
    This directive offers policy-level control over OpenVPN's usage of external 
    programs and scripts. Lower level values are more restrictive, higher
    values are more permissive. Settings for level:
0 -- Strictly no calling of external programs. 
1 -- (Default) Only call built-in executables such as ifconfig, ip, route,
or netsh. 
2 -- Allow calling of built-in executables and user-defined scripts. 
3 -- Allow passwords to be passed to scripts via environmental variables
(potentially unsafe).

OpenVPN releases before v2.3 also supported a method flag which indicated how 
OpenVPN should call external commands and scripts. This could be either execve
or system. As of OpenVPN v2.3, this flag is no longer accepted. In most *nix 
environments the execve() approach has been used without any issues.

Some directives such as --up allow options to be passed to the external script.
In these cases make sure the script name does not contain any spaces or the 
configuration parser will choke because it can't determine where the script 
name ends and script options start.

Combined with an abbreviated section on --up

--up cmd
    Run command cmd after successful TUN/TAP device open (pre --user UID change).
    cmd consists of a path to script (or executable program), optionally followed
    by arguments. The path and arguments may be single- or double-quoted and/or 
    escaped using a backslash, and should be separated by one or more spaces.

Example:

On my machine with a openpvn server.conf, I have the following lines in my /etc/default/openvpn file:

OPTARGS="
    --script-security 2
    --up /etc/openvpn/nat.sh
" 

Incidentally, the nat.sh sets up network address translation for routing private network traffic from openvpn clients to the public internet; which is good for when one does not trust a public WIFI access point.


Aside from allowing to restart as expected after a reboot, when /etc/openvpn/[client or server].conf and /etc/default/openvpn files are properly configured, openvpn can be started or stopped with:

sudo service openvpn start
sudo service openvpn stop

Other useful options available for service openvpn include cond-restart,force-reload,reload, restart,soft-restart, start, status, stop.

mivk
  • 5,082
  • 1
  • 47
  • 56
Keith Reynolds
  • 429
  • 3
  • 8
  • 18
1

I stumbled upon the answer in my research to solve this issue and I found out that the best solution is (using openvpn server) as follows:

Create a script to be executed:

# nano /etc/openvpn/up.sh
<file:contents>
#!/bin/sh

# export >> /var/log/openvpn/openvpn-up.log
D=`date "+%Y-%m-%d %H:%M"`
echo "[$D] ($local_port_1:$proto_1) $X509_0_CN: $trusted_ip => $ifconfig_pool_remote_ip" >> /var/log/openvpn/openvpn-up.log
</file>

Add the following lines into the openvpn configuration (usually /etc/openvpn/server.conf). In the answer above it was used up and down, which are used when the server starts (restarts). The directive client-connect (and client-disconnect) are used when the client connects (disconnects).

# nano /etc/openvpn/server.conf
<file:add>
script-security 2
client-connect /etc/openvpn/up.sh
</file>
ThunderBird
  • 1,915
  • 13
  • 19
  • 31
CozC
  • 11
  • 1
1

Here is the config for OpenVPN, in order to send mail after a successful connection:

  1. Create a directory

    mkdir /mailOpenVPN
    
  2. Make it worldwide accessable

    chmod 777 /mailOpenVPN
    
  3. vim /etc/openvpn/up.sh

    #! /bin/sh
    python3 /mailOpenVPN/sendMail.py $X509_0_CN $trusted_ip $ifconfig_pool_remote_ip
    
  4. Make up.sh executable

    chmod +x /etc/openvpn/up.sh
    
  5. Add in /etc/openvpn/server.conf

    script-security 2
    client-connect /etc/openvpn/up.sh
    
  6. Restart the OpenVPN service

    service openvpn restart
    
  7. vim /mailOpenVPN/sendMail.py

    import sys
    import smtplib
    import datetime
    
    
    smtp_user = "SENDER MAIL"
    smtp_pass = "PASS"
    recipients = "DEST MAIL"
    smtp_server = "smtp.gmail.com" # This is in my case, because sender is gmail
    
    try:
      now = str(datetime.datetime.now())
      subject = "New connection to home VPN"
      msg = "Hello chief,\n\n"
      msg += "New connection detected:\n"
      msg += "User: " + str(sys.argv[1]) + "\n"
      msg += "Public IP: " + str(sys.argv[2]) + "\n"
      msg += "Assigned IP: " + str(sys.argv[3]) + "\n"
      msg += "Timestamp: " + str(now) + "\n\n"
      msg += "Best regards,\n"
      msg += "Your humble Pi"
    
      sender = "OpenVPN Home"
      message = "From: OpenVPN Home\nSubject: {0}\n\n{1}".format(subject, msg)
    
      server = smtplib.SMTP_SSL(smtp_server, 465)
      server.ehlo()
      server.login(smtp_user, smtp_pass)
      server.sendmail(sender, recipients, message)
      server.close()
    except:
      pass
    
zx485
  • 2,249
  • 11
  • 24
  • 34
1

After following multiple suggestions, one problem I have is "--up" and --route-up" are executing before whole "Initialization Sequence Completed".

For me, I have to open ports after full initialization.. So I followed below..

#1) Create up.sh which launches port open script(proxyports.sh) asynchronously

#2) Create down.sh which closes the ports opened asynchronously in proxyports.sh

up.sh content ...

#!/bin/bash
( ( sleep 1 ; ~/proxyports.sh) & echo "Open the ports" )

proxyports.sh content ...

#!/bin/bash
HOME=/home/venkatdesu
PID=$(/usr/sbin/lsof -i :1080 | grep LISTEN|awk '{print $2}'|sort|uniq);
if [[ ! -z "$PID" ]]; then
  echo "SSH Socks Process $PID running with " $(ps "$PID");
  kill -9 $PID;
  sleep 1;
fi;
ssh -D 1080 -Nf iamdvr@10.0.0.94 
PID=$(/usr/sbin/lsof -i :1080 | grep LISTEN|awk '{print $2}'|sort|uniq);
echo "Socks running at $PID"

down.sh content ...

#!/bin/bash
PID=$(/usr/sbin/lsof -i :1080 | grep LISTEN|awk '{print $2}'|sort|uniq);
if [[ ! -z "$PID" ]]; then
 echo "SSH Socks Process $PID running with " $(ps "$PID");
 kill -9 $PID;
fi;