[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 506
  • Last Modified:

Need a script to re-initiate a OpenSwan VPN tunnel when it fails

I need to initiate the following commands if a ping fails to an IP address.

sudo ipsec whack --name sonicwall --delete
sudo ipsec auto --add sonicwall
sudo ipsec whack --name sonicwall --initiate

Open in new window


The last command prompts for a username and password (as displayed below.)  The script will need to provide the username and password.
[ec2-user@ip-10-170-95-135 ~]$ sudo ipsec whack --name sonicwall --initiate
002 "sonicwall" #41: initiating Aggressive Mode #41, connection "sonicwall"
112 "sonicwall" #41: STATE_AGGR_I1: initiate
003 "sonicwall" #41: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 Standard?)]
003 "sonicwall" #41: ignoring unknown Vendor ID payload [5b362bc820f60007]
003 "sonicwall" #41: received Vendor ID payload [Dead Peer Detection]
003 "sonicwall" #41: received Vendor ID payload [XAUTH]
002 "sonicwall" #41: Aggressive mode peer ID is ID_FQDN: '@0017C5120524'
002 "sonicwall" #41: transition from state STATE_AGGR_I1 to state STATE_AGGR_I2
004 "sonicwall" #41: STATE_AGGR_I2: sent AI2, ISAKMP SA established {auth=OAKLEY_PRESHARED_KEY cipher=oakley_3des_cbc_192 prf=oakley_sha group=modp1024}
041 "sonicwall" #41: sonicwall prompt for Username:
Enter username:   amazoncloudCA
040 "sonicwall" #41: sonicwall prompt for Password:
Enter passphrase: 

Open in new window


I don't particularly care what scripting tools are used to get this done.

Thanks!
Phil
0
hypervisor
Asked:
hypervisor
  • 12
  • 11
  • +1
1 Solution
 
MikeOM_DBACommented:
Use "expect" command.
;)
0
 
Duncan RoeSoftware DeveloperCommented:
I agree you can best solve this with expect. Please verify that it is installed on your system: in a command window enter expect and verify you get a prompt. Use control-D (end of file) to exit.
Since you asked this Q I imagine you have not used expect before. Try this little script and post back the results (I can't try it myself, not having ipsec)
#!/bin/sh
# expect treats the next line as a comment continuation \
exec expect -f "$0"
spawn sudo ipsec whack --name sonicwall --initiate
expect {Enter username:   }
exp_send amazoncloudCA\r
expect {Enter passphrase: }
exp_send "Your passphrase\r"

Open in new window

Depending on whether you have non-alphanumerics in your passphrase, you may have to pay attention to how you send it. I assumed you might have spaces, which are reasonably benign.
Strings that contain spaces need to be quoted. You either quote with double-quotes or curly brackets. The curly brackets work a bit like single quote in shell: no substitution or interpretation of backslash escapes occurs inside them.
Double-quotes work similarly to shell: escapes are recognized but characters that are special to expect itself have to be escaped. Unlike shell, specials include square brackets [].
0
 
hypervisorAuthor Commented:
How do I add the logic in there to start only if a ping to a host fails?  (Thanks so much for the help!)
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
Duncan RoeSoftware DeveloperCommented:
Are you looking to ping really frequently, like every second or few seconds? And many hosts or just 1? Example below pings 1 host every second (I can test this one :)
#!/bin/sh
# \
exec expect -f "$0"
spawn /bin/bash
expect -re {[$#] }
# ping can take a long time to fail -default 10s timeout is too short
set timeout 60
# Guard against unset variable if timeout happens 1st time anyway
set num_received 0

# Loop doing a ping every second
while {1} \
{
  exp_send {ping -c1 dullstar.local.net};exp_send \r
  expect -re {([01]) received}
  set num_received $expect_out(1,string)
  expect -re {[$#] }
  if {$num_received == 0} \
  {
    #exp_send {path_to_your_ipsec_script >/dev/null 2>&1 &};exp_send \r
    #expect -re {[$#] }
    exp_send exit\r
    expect eof
    exit
  }
  sleep 1
}

Open in new window

This script has a hard-coded host name which you will need to change. You could get the host off the command line - post back if you really want to. If you have multiple hosts the command line is better anyway - post back if you need that too.
Un-comment the send / expect pair and put in the proper path to your script (which will do the 1st 2 ipsec commands then call the script I posted last time). This script should then re-start the script above.
The script exits once it has fired off your script. That's to avoid starting your script again should the next ping fail. That's why your script should restart this script when it's finished. Yes it's possible to combine the entire works into a single expect script but in the absence of being able to test the completed system and in the interests of simplicity I've done it the way I have.
0
 
ahoffmannCommented:
a bit off-topic:
but if you don't care about password 'cause you hardcode it in a script, why not simply configure your ipsec without password?
you get a simple oneley for restart then

KISS - keep it stupid (un)secure
0
 
hypervisorAuthor Commented:
Duncan, it doesn't seem to enter the password.  Works up until that point.

I also need to execute the following commands first:

sudo ipsec whack --name sonicwall --delete
sudo ipsec auto --add sonicwall
0
 
Duncan RoeSoftware DeveloperCommented:
I meant for you to have a shell script which would issue the --delete and --add commands and then invoke the separate expect script to issue the --initiate. But you can combine them as below
#!/bin/sh
# expect treats the next 3 lines as comment continuations \
sudo ipsec whack --name sonicwall --delete; \
sudo ipsec auto --add sonicwall ; \
exec expect -f "$0"
spawn sudo ipsec whack --name sonicwall --initiate
expect {Enter username:   }
exp_send amazoncloudCA\r
expect {Enter passphrase: }
exp_send "Your passphrase\r"

Open in new window

Please try this to satisfy yourself that your 1st 2 commands are issued. For password see next post.
0
 
hypervisorAuthor Commented:
That works perfectly.  Just need the password piece......
0
 
Duncan RoeSoftware DeveloperCommented:
Sorry I have to go now. Will post later.
0
 
Duncan RoeSoftware DeveloperCommented:
To debug the problem with sending password, please follow the following steps

1. Replace the passwords in your script with dummy values

I need you to do this so you don't have to edit passwords out of the log file you will create from the following steps. The log file may contain very long lines which some editors might corrupt.

2. Edit the script to produce a debug log file

Insert
exp_internal -f log.txt 1

Open in new window

after the line beginning exec expect.

3. Run the script to populate [i]log.txt[/i]

Run the script by hand. Expect to see a lot of output - it will all go into log.txt as well as coming to the screen. After the password is not sent, terminate the script using Control-C.

4. Post [i]log.txt[/i]

Post log.txt by clicking on Attach File below and at left of text entry area.
0
 
hypervisorAuthor Commented:
spawn sudo ipsec whack --name sonicwall --initiate
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {22921}

expect: does "" (spawn_id exp5) match glob pattern "Enter username:   "? no
002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"

expect: does "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n" (spawn_id exp5) match glob pattern "Enter username:   "? no
112 "sonicwall" #5: STATE_AGGR_I1: initiate

expect: does "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n112 "sonicwall" #5: STATE_AGGR_I1: initiate\r\n" (spawn_id exp5) match glob pattern "Enter username:   "? no
003 "sonicwall" #5: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 Standard?)]

expect: does "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n112 "sonicwall" #5: STATE_AGGR_I1: initiate\r\n003 "sonicwall" #5: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 St$
003 "sonicwall" #5: ignoring unknown Vendor ID payload [5b362bc820f60007]

expect: does "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n112 "sonicwall" #5: STATE_AGGR_I1: initiate\r\n003 "sonicwall" #5: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 St$
003 "sonicwall" #5: received Vendor ID payload [Dead Peer Detection]

expect: does "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n112 "sonicwall" #5: STATE_AGGR_I1: initiate\r\n003 "sonicwall" #5: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 St$
003 "sonicwall" #5: received Vendor ID payload [XAUTH]

expect: does "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n112 "sonicwall" #5: STATE_AGGR_I1: initiate\r\n003 "sonicwall" #5: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 St$
002 "sonicwall" #5: Aggressive mode peer ID is ID_FQDN: '@0017C5120524'

expect: does "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n112 "sonicwall" #5: STATE_AGGR_I1: initiate\r\n003 "sonicwall" #5: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 St$
002 "sonicwall" #5: transition from state STATE_AGGR_I1 to state STATE_AGGR_I2

expect: does "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n112 "sonicwall" #5: STATE_AGGR_I1: initiate\r\n003 "sonicwall" #5: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 St$
004 "sonicwall" #5: STATE_AGGR_I2: sent AI2, ISAKMP SA established {auth=OAKLEY_PRESHARED_KEY cipher=oakley_3des_cbc_192 prf=oakley_sha group=modp1024}

expect: does "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n112 "sonicwall" #5: STATE_AGGR_I1: initiate\r\n003 "sonicwall" #5: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 St$
041 "sonicwall" #5: sonicwall prompt for Username:

expect: does "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n112 "sonicwall" #5: STATE_AGGR_I1: initiate\r\n003 "sonicwall" #5: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 St$
Enter username:
expect: does "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n112 "sonicwall" #5: STATE_AGGR_I1: initiate\r\n003 "sonicwall" #5: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 St$
expect: set expect_out(0,string) "Enter username:   "
expect: set expect_out(spawn_id) "exp5"
expect: set expect_out(buffer) "002 "sonicwall" #5: initiating Aggressive Mode #5, connection "sonicwall"\r\n112 "sonicwall" #5: STATE_AGGR_I1: initiate\r\n003 "sonicwall" #5: ignoring Vendor ID payload [Soni$
send: sending "amazoncloudCA\r" to { exp5 }

expect: does "" (spawn_id exp5) match glob pattern "Enter passphrase: "? no
amazoncloudCA

expect: does "amazoncloudCA\r\n" (spawn_id exp5) match glob pattern "Enter passphrase: "? no
040 "sonicwall" #5: sonicwall prompt for Password:

expect: does "amazoncloudCA\r\n040 "sonicwall" #5: sonicwall prompt for Password:\r\n" (spawn_id exp5) match glob pattern "Enter passphrase: "? no
Enter passphrase:
expect: does "amazoncloudCA\r\n040 "sonicwall" #5: sonicwall prompt for Password:\r\nEnter passphrase: " (spawn_id exp5) match glob pattern "Enter passphrase: "? yes
expect: set expect_out(0,string) "Enter passphrase: "
expect: set expect_out(spawn_id) "exp5"
expect: set expect_out(buffer) "amazoncloudCA\r\n040 "sonicwall" #5: sonicwall prompt for Password:\r\nEnter passphrase: "
send: sending "Your passphrase\r" to { exp5 }

Open in new window

0
 
Duncan RoeSoftware DeveloperCommented:
The script worked fine. It sent the string Your passphrase followed by a carriage return when asked. You were supposed to substitute your actual pass-phrase in the script but you haven't done so.
Or am I missing something?
0
 
Duncan RoeSoftware DeveloperCommented:
I asked you to post the output as a file attachment. As I feared, the long lines in the output are truncated, presumably because you tried to select and paste into the output window. As it happens, it doesn't matter this time because the script worked but if it hadn't then the missing data might have been important.
0
 
Duncan RoeSoftware DeveloperCommented:
Since you have all the ipsec commands in a single script now, you will want that script to start another instance of the ping script when it is done. This would have been simpler if we had kept to having 2 scripts, but this should work
#!/bin/sh
# expect treats the next 3 lines as comment continuations \
sudo ipsec whack --name sonicwall --delete; \
sudo ipsec auto --add sonicwall ; \
exec expect -f "$0"
spawn /bin/bash
expect -re {[$#] }
exp_send {sudo ipsec whack --name sonicwall --initiate};exp_send \r
expect {Enter username:   }
exp_send amazoncloudCA\r
expect {Enter passphrase: }
exp_send "Your passphrase\r"
expect -re {[$#] }
exp_send {path_to_your_ping_script >/dev/null 2>&1 &};exp_send \r
expect -re {[$#] }
exp_send exit\r
expect eof

Open in new window

As before, substitute your actual values for Your passphrase and path_to_your_ping_script.
0
 
hypervisorAuthor Commented:
This is the output of the commands when run manually:
[root@ip-10-170-95-135 scripts]# ipsec whack --name sonicwall --initiate
002 "sonicwall" #10: initiating Aggressive Mode #10, connection "sonicwall"
112 "sonicwall" #10: STATE_AGGR_I1: initiate
003 "sonicwall" #10: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 Standard?)]
003 "sonicwall" #10: ignoring unknown Vendor ID payload [5b362bc820f60007]
003 "sonicwall" #10: received Vendor ID payload [Dead Peer Detection]
003 "sonicwall" #10: received Vendor ID payload [XAUTH]
002 "sonicwall" #10: Aggressive mode peer ID is ID_FQDN: '@0017C5120524'
002 "sonicwall" #10: transition from state STATE_AGGR_I1 to state STATE_AGGR_I2
004 "sonicwall" #10: STATE_AGGR_I2: sent AI2, ISAKMP SA established {auth=OAKLEY_PRESHARED_KEY cipher=oakley_3des_cbc_192 prf=oakley_sha group=modp1024}
041 "sonicwall" #10: sonicwall prompt for Username:
Enter username:   amazoncloudCA
040 "sonicwall" #10: sonicwall prompt for Password:
Enter passphrase: 
002 "sonicwall" #10: XAUTH: Answering XAUTH challenge with user='amazoncloudCA'
002 "sonicwall" #10: transition from state STATE_XAUTH_I0 to state STATE_XAUTH_I1
004 "sonicwall" #10: STATE_XAUTH_I1: XAUTH client - awaiting CFG_set
003 "sonicwall" #10: ignoring informational payload, type IPSEC_INITIAL_CONTACT msgid=00000000
003 "sonicwall" #10: received and ignored informational message
002 "sonicwall" #10: XAUTH: Successfully Authenticated
002 "sonicwall" #10: transition from state STATE_XAUTH_I0 to state STATE_XAUTH_I1
004 "sonicwall" #10: STATE_XAUTH_I1: XAUTH client - awaiting CFG_set
002 "sonicwall" #11: initiating Quick Mode PSK+ENCRYPT+TUNNEL+UP+AGGRESSIVE+IKEv2ALLOW+SAREFTRACK {using isakmp#10 msgid:549a5568 proposal=3DES(3)_192-SHA1(2)_160 pfsgroup=no-pfs}
117 "sonicwall" #11: STATE_QUICK_I1: initiate
002 "sonicwall" #11: transition from state STATE_QUICK_I1 to state STATE_QUICK_I2
004 "sonicwall" #11: STATE_QUICK_I2: sent QI2, IPsec SA established tunnel mode {ESP=>0x469d3ccd <0x4810e17c xfrm=3DES_0-HMAC_SHA1 NATOA=none NATD=none DPD=none}

Open in new window


This is the output of the script that was provided:
[root@ip-10-170-95-135 scripts]# ./startup.sh 
002 "sonicwall": deleting connection
002 "sonicwall" #11: deleting state (STATE_QUICK_I2)
002 "sonicwall" #10: deleting state (STATE_XAUTH_I1)
/usr/libexec/ipsec/addconn Non-fips mode set in /proc/sys/crypto/fips_enabled
spawn sudo ipsec whack --name sonicwall --initiate
002 "sonicwall" #12: initiating Aggressive Mode #12, connection "sonicwall"
112 "sonicwall" #12: STATE_AGGR_I1: initiate
003 "sonicwall" #12: ignoring Vendor ID payload [Sonicwall 1 (TZ 170 Standard?)]
003 "sonicwall" #12: ignoring unknown Vendor ID payload [5b362bc820f60007]
003 "sonicwall" #12: received Vendor ID payload [Dead Peer Detection]
003 "sonicwall" #12: received Vendor ID payload [XAUTH]
002 "sonicwall" #12: Aggressive mode peer ID is ID_FQDN: '@0017C5120524'
002 "sonicwall" #12: transition from state STATE_AGGR_I1 to state STATE_AGGR_I2
004 "sonicwall" #12: STATE_AGGR_I2: sent AI2, ISAKMP SA established {auth=OAKLEY_PRESHARED_KEY cipher=oakley_3des_cbc_192 prf=oakley_sha group=modp1024}
041 "sonicwall" #12: sonicwall prompt for Username:
Enter username:   amazoncloudCA
040 "sonicwall" #12: sonicwall prompt for Password:
Enter passphrase: [root@ip-10-170-95-135 scripts]# 

Open in new window


This is why I'm struggling...
0
 
Duncan RoeSoftware DeveloperCommented:
The pass phrase is not echoed, that is normal. Please be really sure you have the exact right pass phrase in your script. What happens if you manually enter a bad one?

Aargh! Just saw it. You must have the line expect -re {[$#] } after sending the pass phrase, otherwise expect will terminate and kill your job
0
 
hypervisorAuthor Commented:
That's it!

If I want to add a quick function before this script to check a host - if the host ping fails, then run the script, otherwise end... any suggestions?

#!/bin/sh
# expect treats the next 3 lines as comment continuations \
sudo ipsec whack --name sonicwall --delete; \
sudo ipsec auto --add sonicwall ; \
exec expect -f "$0"
spawn sudo ipsec whack --name sonicwall --initiate
expect {Enter username:   }
exp_send amazoncloudCA\r
expect {Enter passphrase: }
exp_send "xxxxxxxr"
expect -re {[$#] }

Open in new window


Edited by SouthMod
0
 
Duncan RoeSoftware DeveloperCommented:
Did you notice I posted a new script this morning? My idea was either the pinger is running or the ipsec script is running. But here's a modified ipsec script that does a ping
#!/bin/sh
# \
exec expect -f "$0"
spawn /bin/bash
expect -re {[$#] }
exp_send {ping -c1 dullstar.local.net};exp_send \r
expect -re {([01]) received}
set num_received $expect_out(1,string)
expect -re {[$#] }
if {$num_received == 1} {exit}
exp_send {sudo ipsec whack --name sonicwall --delete; \};exp_send \r
expect -re {[$#] }
exp_send {sudo ipsec auto --add sonicwall ; \};exp_send \r
expect -re {[$#] }
exp_send {sudo ipsec whack --name sonicwall --initiate};exp_send \r
expect {Enter username:   }
exp_send amazoncloudCA\r
expect {Enter passphrase: }
exp_send "Your passphrase\r"
expect -re {[$#] }

Open in new window

As before, substitute for dullstar.local.net.
(you might want to change your password)
0
 
hypervisorAuthor Commented:
I've requested that this question be deleted for the following reason:

We posted a password in this thread and need to remove it.
0
 
hypervisorAuthor Commented:
ID: 39197248 - Need comment removed as it includes a password.  Moderator, can you help?
0
 
hypervisorAuthor Commented:
Getting close -


[ec2-user@ip-10-170-95-135 scripts]$ ./new.sh
spawn /bin/bash
[ec2-user@ip-10-170-95-135 scripts]$ ping -c1 192.168.179.1
PING 192.168.179.1 (192.168.179.1) 56(84) bytes of data.
can't read "expect_out(1,string)": no such element in array
    while executing
"set num_received $expect_out(1,string)"
    (file "./new.sh" line 8)

Open in new window


This is the error I get with your new script...
0
 
Duncan RoeSoftware DeveloperCommented:
I copied from my earlier script http:#a39178121 but not too well. Try this
#!/bin/sh
# \
exec expect -f "$0"
spawn /bin/bash
expect -re {[$#] }
# ping can take a long time to fail -default 10s timeout is too short
set timeout 60
# Guard against unset variable if timeout happens anyway
set expect_out(1,string) 0
exp_send {ping -c1 dullstar.local.net};exp_send \r
expect -re {([01]) received}
set num_received $expect_out(1,string)
# Back to default timeout
set timeout 10
expect -re {[$#] }
if {$num_received == 1} {exit}
exp_send {sudo ipsec whack --name sonicwall --delete; \};exp_send \r
expect -re {[$#] }
exp_send {sudo ipsec auto --add sonicwall ; \};exp_send \r
expect -re {[$#] }
exp_send {sudo ipsec whack --name sonicwall --initiate};exp_send \r
expect {Enter username:   }
exp_send amazoncloudCA\r
expect {Enter passphrase: }
exp_send "Your passphrase\r"
expect -re {[$#] }

Open in new window

As always, substitute for dullstar.local.net
0
 
hypervisorAuthor Commented:
hmm, here's what I get now:

[ec2-user@ip-10-170-95-135 scripts]$ ./new.sh 
spawn /bin/bash
[ec2-user@ip-10-170-95-135 scripts]$ ping -c1 192.168.179.1
PING 192.168.179.1 (192.168.179.1) 56(84) bytes of data.

--- 192.168.179.1 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 10000ms

[ec2-user@ip-10-170-95-135 scripts]$ missing close-brace
    while executing
"exp_send {sudo ipsec whack --name sonicwall --delete; \};exp_send \r
expect -re {[$#] }
exp_send {sudo ipsec auto --add sonicwall ; \};exp_send \r
exp..."
    (file "./new.sh" line 17)

Open in new window

0
 
Duncan RoeSoftware DeveloperCommented:
It really would have been simpler if you'd gone with having 2 scripts. I can't test this increasingly complex composite one, but I think I fixed the immediate problem
#!/bin/sh
# \
exec expect -f "$0"
spawn /bin/bash
expect -re {[$#] }
# ping can take a long time to fail -default 10s timeout is too short
set timeout 60
# Guard against unset variable if timeout happens anyway
set expect_out(1,string) 0
exp_send {ping -c1 192.168.179.1};exp_send \r
expect -re {([01]) received}
set num_received $expect_out(1,string)
# Back to default timeout
set timeout 10
expect -re {[$#] }
if {$num_received == 1} {exit}
exp_send {sudo ipsec whack --name sonicwall --delete};exp_send \r
expect -re {[$#] }
exp_send {sudo ipsec auto --add sonicwall};exp_send \r
expect -re {[$#] }
exp_send {sudo ipsec whack --name sonicwall --initiate};exp_send \r
expect {Enter username:   }
exp_send amazoncloudCA\r
expect {Enter passphrase: }
exp_send "Your passphrase\r"
expect -re {[$#] }

Open in new window

0
 
hypervisorAuthor Commented:
duncan_roe was incredibly helpful.
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

  • 12
  • 11
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now