rachelproelec
rachelproelec

Reputation: 41

Bash Script for automated OpenVPN logon

I am very new to bash scripting, so I apologize in advance for being vague. I have a varied number of OpenVPN configuration profiles I need to connect too on a daily basis, and would like to make this a little easier by introducing automation.

So I am able to get to the authorization part of the process and that's where I get stuck:

  Your IP is xx.xx.xx.xx
Mon Oct 13 09:57:14 2014 OpenVPN 2.2.1 i486-linux-gnu [SSL] [LZO2] [EPOLL] [PKCS11] [eurephia] [MH] [PF_INET6] [IPv6 payload 20110424-2 (2.2RC2)] built on Jun 19 2013
Enter Auth Username:

I would like to know how I can use bash to automatically log on using my username and password. So the script would populate and confirm the 2 authorization fields.

Enter Auth Username: username

Enter Auth Password: password

Then once populated and confirmed, I will be connected to the VPN.

I appreciate any help, and please let me know if more information is required.

My current script I am working with is this:

#!/bin/sh
expect_path="$(which expect)"
"$expect_path" "$0" "$@"

#!/bin/usr/expect -f

spawn sudo openvpn /root/Desktop/my.conf #Path to Openvpn config file (.ovpn)
expect -r "\[sudo\] .*\: " {
    send "my_ownpassword\n"
}
expect "Enter Auth Username:" {
    send "my_user\n"
}
expect "Enter Auth Password:" {
    send "my_vpnpassword\n"
}
interact

Current error I am getting:

can't read "(which expect)": no such variable
    while executing
"expect_path="$(which expect)""
    (file "./vpn.sh" line 2)
./vpn.sh: 7: ./vpn.sh: spawn: not found
expect: invalid option -- 'r'
usage: expect [-div] [-c cmds] [[-f] cmdfile] [args]
./vpn.sh: 9: ./vpn.sh: send: not found
./vpn.sh: 10: ./vpn.sh: Syntax error: "}" unexpected

Upvotes: 4

Views: 21769

Answers (3)

Naive
Naive

Reputation: 11

working for me on Kali 2020.2 simple and easy.

#!/usr/bin/expect -f

# automatic openvpn login
spawn sudo openvpn FILE.ovpn

# script will enter username/password automatic. 
expect "Enter Auth Username:" 
send "USERNAME\n" 

 "Enter Auth Password:" 
send "PASSWORD\n"

interact

end script

save and run file in map where FILE.ovpn is stored.

Upvotes: 1

linux4fun
linux4fun

Reputation: 43

Could not get your code to work due, I edited it a little and it works fine now...

#!/bin/bash
exec 3<>/dev/tcp/127.0.0.1/3030

username=xxxxxxxxx   # username
password=yyyyyyyyy   # auth password paired with username

# read anything it sends
while read -r -u 3; do

  if [[ $(echo $REPLY | grep ">PASSWORD:Need 'Auth' username/password") ]]; then
    echo "username \"Auth\" $username" >&3
    echo "password \"Auth\" $password" >&3
  else
    echo "Ignoring message: $REPLY" >&2
  fi
done

Upvotes: 0

Charles Duffy
Charles Duffy

Reputation: 295363

See https://openvpn.net/index.php/open-source/documentation/miscellaneous/79-management-interface.html for documentation on the TCP protocol intended for use in programmatically controlling an OpenVPN instance.

Use from bash might look something like the following:

#!/bin/bash
# the above shebang is necessary; much of this will not work with /bin/sh
# also, /dev/tcp support is optional functionality at compile time; be sure your bash
# supports it, or you might need to rewrite using netcat.

# Assuming you start OpenVPN with at least the options:
#   --management 127.0.0.1 3030
#   --management-query-passwords

# connect to OpenVPN management socket on FD 3
exec 3<>/dev/tcp/127.0.0.1/3030

pk_password=secret1 # private key password
username=squirrel   # username
password=secret2    # auth password paired with username

# read anything it sends
while read -r -u 3; do
  # if it asks for a password, then give it one
  if [[ $REPLY = ">PASSWORD: Need 'Private Key' password" ]]; then
    echo 'password "Private Key" '"$pk_password" >&3
  elif [[ $REPLY = ">PASSWORD: Need 'Auth' username/password" ]]; then
    echo 'username "Auth" '"$username" >&3
    echo 'password "Auth" '"$password" >&3
  else
    echo "Ignoring message: $REPLY" >&2
  fi
done

All that said -- storing usernames and passwords in plaintext is a horrible, horrible idea. If you actually want your VPN to be secure, and you don't have a user available to enter a password that's something they know (vs something they have stored on the computer), you should be using strong private key auth -- ideally, with that key stored on a hardware token that doesn't allow it to be read out, not a (weak, trivially stolen) password.


Of course, given as this question presupposes that you're willing to do silly, insecure things, you can also make this easier on yourself:

Recompile OpenVPN with the ENABLE_PASSWORD_SAVE flag set (configure --enable-password-save on UNIX), and then --auth-user-pass in your config file will accept a filename as an optional argument giving the location on disk where username and password are stored.

That's actually more secure than the management-interface approach, since it means you aren't giving out your password to any other user who sets up a service on port 3030 pretending to be OpenVPN's management interface.

Upvotes: 4

Related Questions