Skip to contentSkip to conversation

Exec scripts at sigusr1 and established tunnel

PATCH In review Richard Mueller 2 participants 4 messages Dec 18, 2002 – Dec 19, 2002

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Exec scripts at sigusr1 and established tunnel

Hello openvpn-developers,

I needed two more places in openvpn where to exec some scripts because I wanted to build a "fail-over" solution between two tuns.

1.) Situation:

  +---------+       tun0 (ISP0)    +---------+
  | BOX 1   +----------------------+ BOX 2   |
  |         |                      |         |
  |         +----------------------+         |
  +---------+       tun1 (ISP1)    +---------+

tun0 is prefered but if tun0 fails tun1 should do
the job.

Linux advanced routing has a usable solution for this:
Two routing tables with one prefered.

Because of this I needed to add/delete routes at this points:

- After the first "answer" from the peer (add route for tun?)
- At a SIGUSR1 == "peer dead" (del route for tun?)

2.) I used following configs:

[BOX1: tun0]

# interface configuration
dev tun0

# Peer connect configuartion
remote 172.16.90.4

# float

persist-tun
persist-key
ping 7
ping-restart 21

# 10.255.253.8 is our local VPN endpoint
# 10.255.253.9 is our remote VPN endpoint
ifconfig 10.255.254.122 10.255.254.121

# TSL-Client
tls-client
ca /etc/openvpn/certs/ca.crt
cert /etc/openvpn/certs/box1.crt
key /etc/openvpn/certs/box1.key
tls-verify "/usr/local/sbin/verify-cn box2"

# Routen setzen
peerinit /etc/openvpn/scripts/tun0.up
sigusr1 /etc/openvpn/scripts/tun0.down

lport 5006
rport 5007

comp-lzo
#daemon

reneg-sec 600

verb 5

[BOX1: tun1]

# interface configuration
dev tun1

# Peer connect configuartion
remote 172.16.90.4

# float

persist-tun
persist-key
ping 7
ping-restart 21

# 10.255.253.8 is our local VPN endpoint
# 10.255.253.9 is our remote VPN endpoint
ifconfig 10.255.253.122 10.255.253.121

# TSL-Client
tls-client
ca /etc/openvpn/certs/ca.crt
cert /etc/openvpn/certs/box1.crt
key /etc/openvpn/certs/box1.key
tls-verify "/usr/local/sbin/verify-cn box2"

# Routen setzen
peerinit /etc/openvpn/scripts/tun1.up
sigusr1 /etc/openvpn/scripts/tun1.down

lport 5506
rport 5507

comp-lzo
#daemon

reneg-sec 600

verb 5

[BOX2: tun0]

# interface configuration
dev tun0

# Peer connect configuartion
remote 172.16.90.1

# float

persist-tun
persist-key
ping 7
ping-restart 21

ifconfig 10.255.254.121 10.255.254.122

# TSL-Client
tls-client
ca /etc/openvpn/certs/ca.crt
cert /etc/openvpn/certs/box2.crt
key /etc/openvpn/certs/box2.key
tls-verify "/usr/local/sbin/verify-cn box1"

# Routen setzen
peerinit /etc/openvpn/scripts/tun0.up
sigusr1 /etc/openvpn/scripts/tun0.down

lport 5007
rport 5006

comp-lzo
#daemon

reneg-sec 600

verb 5

[BOX1: tun1]

# interface configuration
dev tun1

# Peer connect configuartion
remote 172.16.90.1

# float

persist-tun
persist-key
ping 7
ping-restart 21

ifconfig 10.255.253.121 10.255.253.122

# TSL-Client
tls-client
ca /etc/openvpn/certs/ca.crt
cert /etc/openvpn/certs/box2.crt
key /etc/openvpn/certs/box2.key
tls-verify "/usr/local/sbin/verify-cn box1"

peerinit /etc/openvpn/scripts/tun1.up
sigusr1 /etc/openvpn/scripts/tun1.down

lport 5507
rport 5506

comp-lzo
#daemon

reneg-sec 600

verb 5

4.) Here is the patch:

[PATCH START]

openvpn.c Wed Dec 18 19:18:12 2002 renamed from openvpn.c Mon Oct 21 03:46:52 2002 +10 -1
diff -u openvpn-1.3.2/openvpn.c openvpn-1.3.2-droute/openvpn.c
@@ -341,7 +341,7 @@
                     options->local_port, options->remote_port,
                     options->bind_local, options->remote_float,
                     options->inetd,
-                    udp_socket_addr, options->ipchange,
+                    udp_socket_addr, options->ipchange, options->peerinit_script,
                     options->resolve_retry_seconds);
 
 #ifdef USE_CRYPTO
@@ -1406,6 +1406,15 @@
       run_script (options->down_script, tuntap_actual, MAX_RW_SIZE_TUN (&frame),
                  max_rw_size_udp, options->ifconfig_local, options->ifconfig_remote);
     }
+   /*
+    * Execute sigusr1 script 
+    */
+  if ( !(signal_received == SIGUSR1 && !options->sigusr1_script ) )
+    {
+     msg (M_INFO, "Executing sigusr1 script %s",options->sigusr1_script);
+     system_check (options->sigusr1_script, "sigusr1 command failed", false);
+    }
+
  done:
   /* pop our garbage collection level */
   gc_free_level (gc_level);
options.c Wed Dec 18 18:52:24 2002 renamed from options.c Sat Oct 19 23:26:11 2002 +13 -0
diff -u openvpn-1.3.2/options.c openvpn-1.3.2-droute/options.c
@@ -316,6 +316,9 @@
   SHOW_STR (writepid);
   SHOW_STR (up_script);
   SHOW_STR (down_script);
+  SHOW_STR (peerinit_script);
+  SHOW_STR (sigusr1_script);
+  SHOW_STR (down_script);
   SHOW_BOOL (daemon);
   SHOW_BOOL (inetd);
   SHOW_INT (nice);
@@ -726,6 +729,16 @@
     {
       ++i;
       options->down_script = p2;
+    }
+  else if (streq(p1, "peerinit") && p2) 
+    {
+      ++i;
+      options->peerinit_script = p2;
+    }
+  else if (streq(p1, "sigusr1") && p2) 
+    {
+      ++i;
+      options->sigusr1_script = p2;
     }
   else if (streq (p1, "daemon"))
     {
options.h Wed Dec 18 18:25:46 2002 renamed from options.h Sat Oct 19 22:25:46 2002 +2 -0
diff -u openvpn-1.3.2/options.h openvpn-1.3.2-droute/options.h
@@ -87,6 +87,8 @@
   const char *writepid;
   const char *up_script;
   const char *down_script;
+  const char *peerinit_script;
+  const char *sigusr1_script;
   bool daemon;
   bool inetd;
   int nice;
socket.c Wed Dec 18 18:56:18 2002 renamed from socket.c Sat Oct 19 23:23:19 2002 +18 -0
diff -u openvpn-1.3.2/socket.c openvpn-1.3.2-droute/socket.c
@@ -105,6 +105,7 @@
                 bool inetd,
                 struct udp_socket_addr *usa,
                 const char *ipchange_command,
+                const char *peerinit_command,
                 int resolve_retry_seconds)
 {
   CLEAR (*sock);
@@ -112,6 +113,7 @@
   sock->remote_float = remote_float;
   sock->addr = usa;
   sock->ipchange_command = ipchange_command;
+  sock->peerinit_command = peerinit_command;
 
   /* were we started by inetd or xinetd? */
   if (inetd)
@@ -190,6 +192,22 @@
          sock->set_outgoing_initial = true;
          mutex_unlock (L_SOCK);
          msg (M_INFO, "Peer Connection Initiated with %s", print_sockaddr (&usa->actual));
+
+         if (sock->peerinit_command) 
+           {
+             char command[256];
+             struct buffer out;
+
+             msg (M_INFO, "Executing peerinit_script %s",sock->peerinit_command);
+
+             buf_set_write (&out, command, sizeof (command));
+             buf_printf (&out, "%s %s",
+                         sock->peerinit_command,
+                         print_sockaddr_ex (&usa->actual, true, " "));
+             msg (D_TLS_DEBUG, "executing ip-change command: %s", command);
+             system_check (command, "peerinit command failed", false);
+            }
+
          if (sock->ipchange_command)
            {
              char command[256];
socket.h Wed Dec 18 18:49:01 2002 renamed from socket.h Sat Oct 19 23:26:10 2002 +2 -0
diff -u openvpn-1.3.2/socket.h openvpn-1.3.2-droute/socket.h
@@ -42,6 +42,7 @@
   bool remote_float;
   struct udp_socket_addr *addr;
   const char *ipchange_command;
+  const char *peerinit_command;
   int sd;                      /* file descriptor for socket */
 };
 
@@ -56,6 +57,7 @@
                 bool inetd,
                 struct udp_socket_addr *addr,
                 const char *ipchange_command,
+                 const char *peerinit_command,
                 int resolve_retry_seconds);
 
 void

[PATCH START]

5.) If it is interesting for you, James, you are free to clean the
code and fix the documentation and merge it in your branch. Just write a Creditline in the changelog. ;-)

6.) Feel free to ask, if you have some questions.

bye
richard

Signature · 7 lines
Richard Mueller     mailto:[email protected]...  Fon: +49 9171 896287
Teamix GmbH         http://www.teamix.de       Fax: +49 9171 896286

PGP Public Key      http://www.teamix.net/pgp/rm_public_key_2048
Fingerprint:        ea 50 21 6c a5 39 e9 03 a6 59 af e3 c5 1f 63 8e

Networks - Consulting - Training - Software Development - eCommerce
#1 lore raw

Hi Richard,

The failover idea is interesting. I have a couple comments on the patch:

* How is --peerinit different from --ipchange?

* Shouldn't
if ( !(signal_received == SIGUSR1 && !options->sigusr1_script ) )
...
be
if (signal_received == SIGUSR1 && options->sigusr1_script)
...
?

James

Quoted 186 lines · Richard Mueller

Hello openvpn-developers,

I needed two more places in openvpn where to exec some scripts because I wanted to build a "fail-over" solution between two tuns.

1.) Situation:

  +---------+       tun0 (ISP0)    +---------+
  | BOX 1   +----------------------+ BOX 2   |
  |         |                      |         |
  |         +----------------------+         |
  +---------+       tun1 (ISP1)    +---------+

tun0 is prefered but if tun0 fails tun1 should do
the job.

Linux advanced routing has a usable solution for this:
Two routing tables with one prefered.

Because of this I needed to add/delete routes at this points:

- After the first "answer" from the peer (add route for tun?)
- At a SIGUSR1 == "peer dead" (del route for tun?)

2.) I used following configs:

[BOX1: tun0]

# interface configuration
dev tun0

# Peer connect configuartion
remote 172.16.90.4

# float

persist-tun
persist-key
ping 7
ping-restart 21

# 10.255.253.8 is our local VPN endpoint
# 10.255.253.9 is our remote VPN endpoint
ifconfig 10.255.254.122 10.255.254.121

# TSL-Client
tls-client
ca /etc/openvpn/certs/ca.crt
cert /etc/openvpn/certs/box1.crt
key /etc/openvpn/certs/box1.key
tls-verify "/usr/local/sbin/verify-cn box2"

# Routen setzen
peerinit /etc/openvpn/scripts/tun0.up
sigusr1 /etc/openvpn/scripts/tun0.down

lport 5006
rport 5007

comp-lzo
#daemon

reneg-sec 600

verb 5

[BOX1: tun1]

# interface configuration
dev tun1

# Peer connect configuartion
remote 172.16.90.4

# float

persist-tun
persist-key
ping 7
ping-restart 21

# 10.255.253.8 is our local VPN endpoint
# 10.255.253.9 is our remote VPN endpoint
ifconfig 10.255.253.122 10.255.253.121

# TSL-Client
tls-client
ca /etc/openvpn/certs/ca.crt
cert /etc/openvpn/certs/box1.crt
key /etc/openvpn/certs/box1.key
tls-verify "/usr/local/sbin/verify-cn box2"

# Routen setzen
peerinit /etc/openvpn/scripts/tun1.up
sigusr1 /etc/openvpn/scripts/tun1.down

lport 5506
rport 5507

comp-lzo
#daemon

reneg-sec 600

verb 5

[BOX2: tun0]

# interface configuration
dev tun0

# Peer connect configuartion
remote 172.16.90.1

# float

persist-tun
persist-key
ping 7
ping-restart 21

ifconfig 10.255.254.121 10.255.254.122

# TSL-Client
tls-client
ca /etc/openvpn/certs/ca.crt
cert /etc/openvpn/certs/box2.crt
key /etc/openvpn/certs/box2.key
tls-verify "/usr/local/sbin/verify-cn box1"

# Routen setzen
peerinit /etc/openvpn/scripts/tun0.up
sigusr1 /etc/openvpn/scripts/tun0.down

lport 5007
rport 5006

comp-lzo
#daemon

reneg-sec 600

verb 5

[BOX1: tun1]

# interface configuration
dev tun1

# Peer connect configuartion
remote 172.16.90.1

# float

persist-tun
persist-key
ping 7
ping-restart 21

ifconfig 10.255.253.121 10.255.253.122

# TSL-Client
tls-client
ca /etc/openvpn/certs/ca.crt
cert /etc/openvpn/certs/box2.crt
key /etc/openvpn/certs/box2.key
tls-verify "/usr/local/sbin/verify-cn box1"

peerinit /etc/openvpn/scripts/tun1.up
sigusr1 /etc/openvpn/scripts/tun1.down

lport 5507
rport 5506

comp-lzo
#daemon

reneg-sec 600

verb 5

4.) Here is the patch:

[PATCH START]
diff -u openvpn-1.3.2/openvpn.c openvpn-1.3.2-droute/openvpn.c

openvpn.c Wed Dec 18 19:18:12 2002 line 344

Quoted 5 lines
openvpn.c Wed Dec 18 19:18:12 2002 renamed from openvpn.c Mon Oct 21 03:46:52 2002 +1 -1
@@ -341,7 +341,7 @@
                     options->local_port, options->remote_port,
                     options->bind_local, options->remote_float,
                     options->inetd,
-                    udp_socket_addr, options->ipchange,
+                    udp_socket_addr, options->ipchange,

options->peerinit_script,

openvpn.c Wed Dec 18 19:18:12 2002 line 1406

Quoted 5 lines
openvpn.c Wed Dec 18 19:18:12 2002 renamed from openvpn.c Mon Oct 21 03:46:52 2002 +0 -0
                     options->resolve_retry_seconds);
 
 #ifdef USE_CRYPTO
@@ -1406,6 +1406,15 @@
       run_script (options->down_script, tuntap_actual, MAX_RW_SIZE_TUN

(&frame),

openvpn.c Wed Dec 18 19:18:12 2002 line 1407

Quoted 1 line
openvpn.c Wed Dec 18 19:18:12 2002 renamed from openvpn.c Mon Oct 21 03:46:52 2002 +0 -0
                  max_rw_size_udp, options->ifconfig_local,

options->ifconfig_remote);

Quoted 75 lines
openvpn.c Wed Dec 18 19:18:12 2002 renamed from openvpn.c Mon Oct 21 03:46:52 2002 +9 -0
     }
+   /*
+    * Execute sigusr1 script 
+    */
+  if ( !(signal_received == SIGUSR1 && !options->sigusr1_script ) )
+    {
+     msg (M_INFO, "Executing sigusr1 script %s",options->sigusr1_script);
+     system_check (options->sigusr1_script, "sigusr1 command failed", false);
+    }
+
  done:
   /* pop our garbage collection level */
   gc_free_level (gc_level);

diff -u openvpn-1.3.2/options.c openvpn-1.3.2-droute/options.c

options.c Wed Dec 18 18:52:24 2002 renamed from options.c Sat Oct 19 23:26:11 2002 +13 -0
@@ -316,6 +316,9 @@
   SHOW_STR (writepid);
   SHOW_STR (up_script);
   SHOW_STR (down_script);
+  SHOW_STR (peerinit_script);
+  SHOW_STR (sigusr1_script);
+  SHOW_STR (down_script);
   SHOW_BOOL (daemon);
   SHOW_BOOL (inetd);
   SHOW_INT (nice);
@@ -726,6 +729,16 @@
     {
       ++i;
       options->down_script = p2;
+    }
+  else if (streq(p1, "peerinit") && p2) 
+    {
+      ++i;
+      options->peerinit_script = p2;
+    }
+  else if (streq(p1, "sigusr1") && p2) 
+    {
+      ++i;
+      options->sigusr1_script = p2;
     }
   else if (streq (p1, "daemon"))
     {

diff -u openvpn-1.3.2/options.h openvpn-1.3.2-droute/options.h

options.h Wed Dec 18 18:25:46 2002 renamed from options.h Sat Oct 19 22:25:46 2002 +2 -0
@@ -87,6 +87,8 @@
   const char *writepid;
   const char *up_script;
   const char *down_script;
+  const char *peerinit_script;
+  const char *sigusr1_script;
   bool daemon;
   bool inetd;
   int nice;

diff -u openvpn-1.3.2/socket.c openvpn-1.3.2-droute/socket.c

socket.c Wed Dec 18 18:56:18 2002 renamed from socket.c Sat Oct 19 23:23:19 2002 +2 -0
@@ -105,6 +105,7 @@
                 bool inetd,
                 struct udp_socket_addr *usa,
                 const char *ipchange_command,
+                const char *peerinit_command,
                 int resolve_retry_seconds)
 {
   CLEAR (*sock);
@@ -112,6 +113,7 @@
   sock->remote_float = remote_float;
   sock->addr = usa;
   sock->ipchange_command = ipchange_command;
+  sock->peerinit_command = peerinit_command;
 
   /* were we started by inetd or xinetd? */
   if (inetd)

socket.c Wed Dec 18 18:56:18 2002 line 194

Quoted 3 lines
socket.c Wed Dec 18 18:56:18 2002 renamed from socket.c Sat Oct 19 23:23:19 2002 +0 -0
@@ -190,6 +192,22 @@
          sock->set_outgoing_initial = true;
          mutex_unlock (L_SOCK);
          msg (M_INFO, "Peer Connection Initiated with %s", print_sockaddr

(&usa->actual));

socket.c Wed Dec 18 18:56:18 2002

Quoted 7 lines
socket.c Wed Dec 18 18:56:18 2002 renamed from socket.c Sat Oct 19 23:23:19 2002 +7 -0
+
+         if (sock->peerinit_command) 
+           {
+             char command[256];
+             struct buffer out;
+
+             msg (M_INFO, "Executing peerinit_script

%s",sock->peerinit_command);

Quoted 63 lines
socket.c Wed Dec 18 18:56:18 2002 renamed from socket.c Sat Oct 19 23:23:19 2002 +9 -0
+
+             buf_set_write (&out, command, sizeof (command));
+             buf_printf (&out, "%s %s",
+                         sock->peerinit_command,
+                         print_sockaddr_ex (&usa->actual, true, " "));
+             msg (D_TLS_DEBUG, "executing ip-change command: %s", command);
+             system_check (command, "peerinit command failed", false);
+            }
+
          if (sock->ipchange_command)
            {
              char command[256];

diff -u openvpn-1.3.2/socket.h openvpn-1.3.2-droute/socket.h

socket.h Wed Dec 18 18:49:01 2002 renamed from socket.h Sat Oct 19 23:26:10 2002 +2 -0
@@ -42,6 +42,7 @@
   bool remote_float;
   struct udp_socket_addr *addr;
   const char *ipchange_command;
+  const char *peerinit_command;
   int sd;                      /* file descriptor for socket */
 };
 
@@ -56,6 +57,7 @@
                 bool inetd,
                 struct udp_socket_addr *addr,
                 const char *ipchange_command,
+                 const char *peerinit_command,
                 int resolve_retry_seconds);
 
 void

[PATCH START]

5.) If it is interesting for you, James, you are free to clean the
code and fix the documentation and merge it in your branch. Just write a Creditline in the changelog. ;-)

6.) Feel free to ask, if you have some questions.

bye
richard

Signature · 19 lines
Richard Mueller     mailto:[email protected]...  Fon: +49 9171 896287
Teamix GmbH         http://www.teamix.de       Fax: +49 9171 896286

PGP Public Key      http://www.teamix.net/pgp/rm_public_key_2048
Fingerprint:        ea 50 21 6c a5 39 e9 03 a6 59 af e3 c5 1f 63 8e

Networks - Consulting - Training - Software Development - eCommerce



-------------------------------------------------------
This SF.NET email is sponsored by: Order your Holiday Geek Presents Now!
Green Lasers, Hip Geek T-Shirts, Remote Control Tanks, Caffeinated Soap,
MP3 Players,  XBox Games,  Flying Saucers,  WebCams,  Smart Putty.
T H I N K G E E K . C O M       http://www.thinkgeek.com/sf/
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
#2 lore raw

Hello James,

Thursday, December 19, 2002, 3:59:16 PM, you wrote:

JY> * How is --peerinit different from --ipchange? Good question. None. sh*t Please see below. :)

JY> * Shouldn't
JY> if ( !(signal_received == SIGUSR1 && !options->sigusr1_script ) )
JY> ...
JY> be
JY> if (signal_received == SIGUSR1 && options->sigusr1_script)
JY> ...
JY> ?
d*mn. yes. this is the sprit of "cut'n'paste" coding. Think I pasted the condition some lines above.

I wrote it short afer visiting "Lord of the Rings II" and a 18h workday without any coffee (I am allergic).
So sorry for the bad code, I won't do it again. ;-(
I took the conclusion for me:

$ patch && test && sleep && test && submit

JY> The failover idea is interesting.
It works quite good in my enviroment here (even better after fixing the patch ;) ).

- If openvpn is stopped on both sides, the alternative route is taken immediateley.

- If the link between the two tun-endpoints breaks it takes as long --ping-restart. The prefered route is taken immediateley when the tunnel returns.

Best regards and sorry again for the bad code,

Richard Mueller

#3 lore raw
Quoted 17 lines · Richard Mueller

Hello James,

Thursday, December 19, 2002, 3:59:16 PM, you wrote:

JY> * How is --peerinit different from --ipchange? Good question. None. sh*t Please see below. :)

JY> * Shouldn't
JY> if ( !(signal_received == SIGUSR1 && !options->sigusr1_script ) )
JY> ...
JY> be
JY> if (signal_received == SIGUSR1 && options->sigusr1_script)
JY> ...
JY> ?
d*mn. yes. this is the sprit of "cut'n'paste" coding. Think I pasted the condition some lines above.

Quoted 2 lines

I wrote it short afer visiting "Lord of the Rings II" and a 18h workday without any coffee (I am allergic).

Hey, that's an interesting excuse... Tolkien had a great sense of foreboding about the advancing march of technology and industrialization and he would probably have taken some pleasure in knowing that his storyweaving would throw a wrench into the workings of someone's machinery... not to mention being under the influence of a lack of caffeine :)

Quoted 5 lines

So sorry for the bad code, I won't do it again. ;-( I took the conclusion for me:

$ patch && test && sleep && test && submit
Quoted 8 lines

JY> The failover idea is interesting.
It works quite good in my enviroment here (even better after fixing the patch ;) ).

- If openvpn is stopped on both sides, the alternative route is taken immediateley.

- If the link between the two tun-endpoints breaks it takes as long

--ping-restart.

Quoted 1 line

The prefered route is taken immediateley when the tunnel returns.

So it looks like all we need is a --sigusr1-script option. That seems pretty reasonable. After you've tested it somewhat, would you mind writing an entry for the HOWTO that explains how to use the ipchange and sigusr1 scripts to set up a failover configuration? Probably just a restatement of what you've described in your emails, but maybe with a bit more detail such as how to set up the Linux Advanced Routing component of the setup. I think people would find it very useful, and this is certainly a case where the code itself (i.e. the script patch) is fairly trivial but the documentation on how to do it is the far more essential component.

Thanks,
James

Quoted 6 lines

Best regards and sorry again for the bad code,

Richard Mueller