Using expect to log into VPN from a bash script - bash

I connect to a VPN from console using something like:
sudo openvpn my.conf
[sudo] password for user:
Enter Auth Username:my_user
Enter Auth Password:
I don't care about entering the admin pwd manually but I want to automate the vpn auth, I think expect is what I need to do this but I don't know how to use it and I never coded a bash script.
Could someone show me a simple bash script using expect so I can use it for this?

Something like that (untested)
#!/bin/usr/expect -f
spawn sudo openvpn my.conf
expect -r "\[sudo\] .*\: " {
send "my_ownpassword\n"
}
expect "Enter Auth Username:" {
send "my_user\n"
}
expect "Enter Auth Password:" {
send "my_vpnpassword\n"
}
interact

Or maybe like this:
#!/usr/bin/expect -f
# Constants
set user "my_user"
set pass "blablabla"
set sudo_pass "blablabla"
set timeout -1
# Options
match_max 100000
log_user 0
# Access to device
spawn sudo openvpn my.conf
expect "[sudo]*"
send -- "$sudo_pass\r"
expect "*?sername:*"
send -- "$user\r"
expect "*?assword:*"
send -- "$pass\r"
interact
close

This script will work with OTP authentication too, but you need to install oathtool.
#!/usr/bin/expect
set USERNAME your_username
set PASSWORD your_password
set KEY YOUR_OTP_KEY
set OVPN_PATH /path_to_your_config_file
set OTP [exec oathtool --totp -b $KEY]
eval spawn openvpn --config $OVPN_PATH
set prompt ":|#|\\\$"
interact -o -nobuffer -re $prompt return
send "$USERNAME\r"
interact -o -nobuffer -re $prompt return
send "$PASSWORD\r"
interact -o -nobuffer -re $prompt return
send "$OTP\r"
interact

#!/usr/bin/expect -f
# creditability
set user "username"
set pass "password"
spawn openvpn file.ovpn
expect "*?sername:*"
send -- "$user\r"
expect "*?assword:*"
send -- "$pass\r"
interact
close

Related

Setting variables in expect script has no effect

I'm trying to write a script to get a password from my Mac keychain and use it to add a password protected key to the keychain (using ssh-add). It's meant to be part of a collection of scripts that get sourced by zsh. Currently my scripts looks like this
cat <<EOF | expect -d
set password [exec /usr/bin/security find-generic-password -s SSH -w]
puts "$password"
spawn -noecho /usr/bin/ssh-add $::env(HOME)/.ssh/id_ecdsa
expect -timeout 3 "Enter passphrase for"
send "$password\r"
interact
EOF
The puts "$password" is purely there for debug purposes. And I get the following results
$ source .zshrc.d/090_ssh_keys
Password:
Enter passphrase for /Users/james.dominy/.ssh/id_ecdsa:
$ ssh-add -l
The agent has no identities.
As you can see, the password variable isn't being set; I've tried changing the variable name, and as a debugging effort, I've tried setting it to a number (set password 1) and to a string literal (set password "a") but those don't work either. However, if I cut and paste this into an interactive expect session, everything works as expected
expect1.1> set password [exec /usr/bin/security find-generic-password -s SSH -w]
**********
expect1.2> puts $password
**********
expect1.3> spawn -noecho /usr/bin/ssh-add $::env(HOME)/.ssh/id_ecdsa
89080
expect1.4> expect -timeout 3 "Enter passphrase for"
Enter passphrase for /Users/sirlark/.ssh/id_ecdsa: expect1.5> send "$password\r"
expect1.6> interact
Identity added: /Users/sirlark/.ssh/id_ecdsa (sirlark main ssh key)
expect1.7> %
Password obscured obviously, but this works. Why?

executing rsync from local that ssh to remote and copys to secondary remote

Ok, so what I am trying to do is have a script(s) that I execute from local(1) that ssh into remote(1) and rsync /path/to/file to remote(2) /path/to/file
#!/usr/bin/expect
set oldIP "[lrange $argv 0 0]"
set newIP "[lrange $argv 1 1]"
set password "123..."
set admin "User"
set host localhost
spawn ssh '$admin'#'$oldIP'
expect -exact "Password: "
sleep 3
send -- "$password\r"
expect -exact "$host:~ user# "
send -- "rsync -azvH --numeric-ids -W --force /path/ '$newIP':/path/"
expect -exact "Password: "
sleep 3
send -- "$password\r"
sleep 1
send -- quit\n"
I would suggest you instead of using expect command better to create password less login from remote 1 server to remote 2 server and then setup a cron job which would do it automatically.
You can refer to this below link on how to setup password less login :
https://www.tecmint.com/ssh-passwordless-login-using-ssh-keygen-in-5-easy-steps/

ssh connect and commands programmatically

I'm trying to make a script connecting via an SSH connection to a server and executing some commands. The first part works:
#!/usr/bin/expect -f
spawn ssh address
expect "password:"
send "password\r"
interact
but after that I want to execute some more commands, e.g cd to directory, launch some more scripts etc. Is there any way to implement these things ?
try following:
#!/usr/bin/expect
set login "any_user"
set addr "some_address"
set pw "any_pwd"
spawn ssh -t $login#$addr
expect "$login#$addr\'s password:"
send "$pw\r"
expect "~" ; # put here string from your server prompt
send "mkdir some_dir\r"
interact
This is one of the command, you could try other commands like cd, any other scripts too in it and let us know if any queries.

sftp file download script

I am trying to download a from from a remote sftp location so for this I am using below script.
#!/bin/bash
expect -c "
spawn sftp remoteUser#xx.xx.xx.xx
expect \"password\"
send \"User#123\r\"
interact "
The problem is in the remote server some information msg configure when you login the server, so because of this password send before this text comes on screen.
Try this -
#!/usr/bin/expect
export PASSD="User#123"
expect -c 'spawn sftp user#xxxxxx.com;
expect "*Password: ";
send "$env(PASSD)\r";
expect "sftp>";
send "cd /home/user \r";
expect "sftp>";
send "get file.txt \r";
expect "sftp>";
send "bye \r"'

SSH in the most convenient way without typing in the ssh command everytime

I constantly need to log into a remote server and do all kinds of work. I am using my Mac and every time I have to type in a long command to do that.
ssh -i ~/key.pem ubuntu#255.255.255.255
I am wondering what would be the easiest way to log into the remote server without typing in the command everyday.
Handy apple apps are also welcome
Updated:
1> Thanks to Matt Bryant's answer. I successfully avoided typing in the whole username and host address by modifying ~/.ssh/config (doesn't exist as default) to
Host <ShortName>
User <UserName>
HostName <HostIP>
IdentityFile <KeyPath>
then I could just type this command to avoid typing in the full name of host and full path of the key:
ssh <ShortName>
2> Anyone knows how to store the pem key or avoid typing in the password if there is no pem key?
Use the ~/.ssh/config file. Try adding the following to it:
Host server
User ubuntu
HostName 255.255.255.255
This will allow you to login using ssh -i ~/key.pem server. If you look up ssh config, there are many other settings that will allow you to simplify and enhance your ssh experience.
Hi B MR W yes I am going to post up an expect script since this comes up a lot:
E2A The instructions are for linux
There is expect on mac https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/expect.1.html
It might be mean messing with the script to meet the criteria of the mac expect I don't have enough knowledge on that but in principal having had a look the below process should work
Which bit was you interested in the ssh-copy-id or a script?
to get a script going you need to
sudo-apt-get install expect or
sudo yum install expect
Once installed
This is a typical script:
#!/usr/bin/expect -f
set force_conservative 1
if {$force_conservative} {
set send_slow {1 .001}
proc send {ignore arg} {
sleep .001
exp_send -s -- $arg
}
}
;# Validate user input - make sure all fields required are given
if {$argc >= 1} {
;# Setting password
set user "MYUSER";
set supass "MYPASSWORD"
set host [lindex $argv 0]
# set command1 [lindex $argv 2]
set prompt "(:|#|%|>|\\\$|% |# |> |\\\$ )"
set prompt1 "(>)"
set timeout -1
;###############################################################
;#connect to specified host given by addstaff or globalstaff.
spawn ssh $user#$host
expect {
"*word:*" {}
"*(yes/no)?*" {
send - "yes\r"
expect "*word:" { }
}
}
send - "$supass\r"
expect eof exit -re $prompt
send - "sudo bash\r"
expect {
"*word:*" {
send "$supass\r"
expect eof exit -re $prompt
}
"*" {
expect eof exit -re $prompt
}
}
send - "whoami\r"
expect eof exit -re $prompt
interact
;#send - "$command\r"
;# expect eof exit -re $prompt
;#Logout of current ssh session
;#send - "exit\r"
;#expect eof exit -re $prompt
;#send - "exit\r"
;#expect eof exit -re $prompt
} else {
send - "echo Sorry require user host command \n\n\r";
exit
}
If you have noticed I have commented out the commands which is not being sent - its using interact mode to allow you to actually log in without a password, user password defined at the top of the script... Once logged in you type as you would per normal ssh
Here is me running it locally:
whoami
myuser
./ssh-connection.exp localhost
spawn ssh myuser#localhost
myuser#localhost's password:
Welcome to Ubuntu 12.04.2 LTS (GNU/Linux XXXX)
* Documentation: https://help.ubuntu.com/
Last login: Sat Sep 7 20:19:53 2013 from localhost
sudo bash
This is BASH 4.2- DISPLAY on localhost:0.0
Sat Sep 7 20:25:09 BST 2013
whoami
[20:25 myuser#myuser-DP ~] > sudo bash
whoami
This is BASH 4.2- DISPLAY on localhost:0.0
Sat Sep 7 20:25:09 BST 2013
[20:25 myuser#myuser-DP ~] > whoami
root
[20:25 myuser#myuser-DP ~] > whoami
root
Within the script it also does a sudo bash which is why it reconnects me to localhost and I become root

Resources