Remove requirement for gof5 = just use openconnect for everything.
In theory, VPNs other than cisco/f5 are now supported too.
This commit is contained in:
parent
265f3a5293
commit
42d8999ad0
|
@ -0,0 +1,382 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
. ${HOME}/code/bashtools/bashtools.sh
|
||||||
|
if [[ -z $HAVE_BASHTOOLS ]]; then
|
||||||
|
echo "ERROR: bashtools not installed download from https://git.nethack.net/rob/bashtools" >/dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
CONFDIR=${HOME}/.vpn
|
||||||
|
LOGFILE=${CONFDIR}/log
|
||||||
|
VPNPIDFILE=${CONFDIR}/vpnpid
|
||||||
|
DEFAULTCONF=${CONFDIR}/config
|
||||||
|
CONFFILE=${DEFAULTCONF}
|
||||||
|
|
||||||
|
cp -p "$LOGFILE" "${LOGFILE}.0"
|
||||||
|
cp /dev/null "$LOGFILE"
|
||||||
|
|
||||||
|
err=0
|
||||||
|
OPENCONNECT=$(which openconnect 2>/dev/null)
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
error "Can't find openconnect binary"
|
||||||
|
err=$((err + 1))
|
||||||
|
fi
|
||||||
|
VPNSLICE=$(which vpn-slice 2>/dev/null)
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
error "Can't find vpn-slice binary"
|
||||||
|
err=$((err + 1))
|
||||||
|
fi
|
||||||
|
if [[ $ree -ne 0 ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${CONFDIR}"
|
||||||
|
|
||||||
|
function alias_to_cmd() {
|
||||||
|
local input="$1"
|
||||||
|
local output="$input"
|
||||||
|
|
||||||
|
case $input in
|
||||||
|
"l") output="list";;
|
||||||
|
"ls") output="list";;
|
||||||
|
"start") output="on";;
|
||||||
|
"u") output="on";;
|
||||||
|
"up") output="on";;
|
||||||
|
"stop") output="off";;
|
||||||
|
"d") output="off";;
|
||||||
|
"down") output="off";;
|
||||||
|
"check") output="status";;
|
||||||
|
"stat") output="status";;
|
||||||
|
"info") output="status";;
|
||||||
|
"i") output="status";;
|
||||||
|
esac
|
||||||
|
echo "$output"
|
||||||
|
}
|
||||||
|
|
||||||
|
function load_config() {
|
||||||
|
local CONFLINES line thisprofile thisuser thispw thisgroup thisroutes thisservercert
|
||||||
|
DEFAULTPROFILE=""
|
||||||
|
if [[ -e ${CONFFILE} ]]; then
|
||||||
|
DEFAULTPROFILE=$(grep '^#default:' "${CONFFILE}" | sed 's/^#default://')
|
||||||
|
CONFLINES=$(egrep -v "^#" ${CONFFILE} 2>/dev/null | awk NF)
|
||||||
|
nvpns=0
|
||||||
|
while read line; do
|
||||||
|
[[ $line =~ ^# ]] && continue
|
||||||
|
thisprofile=$(cut -d, -f1 <<< "${line}")
|
||||||
|
thisuser=$(cut -d, -f2 <<< "${line}")
|
||||||
|
thispw=$(cut -d, -f3 <<< "${line}")
|
||||||
|
thisgroup=$(cut -d, -f4 <<< "${line}")
|
||||||
|
thisvpntype=$(cut -d, -f5 <<< "${line}")
|
||||||
|
thisserver=$(cut -d, -f6 <<< "${line}")
|
||||||
|
thisroutes=$(cut -d, -f7 <<< "${line}")
|
||||||
|
thisservercert=$(cut -d, -f8 <<< "${line}")
|
||||||
|
case $thisvpntype in
|
||||||
|
"") thisvpntype="anyconnect";
|
||||||
|
"cisco") thisvpntype="anyconnect";
|
||||||
|
"bigip") thisvpntype="anyconnect";
|
||||||
|
esac
|
||||||
|
if [[ -z $thisserver ]]; then
|
||||||
|
error "Missing server IP for profile '$thisprofile'"
|
||||||
|
cecho -s "$RED" "^bBad line:^p $line"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
profile[$nvpns]="${thisprofile}"
|
||||||
|
user[$nvpns]="${thisuser}"
|
||||||
|
pw[$nvpns]="${thispw}"
|
||||||
|
group[$nvpns]="${thisgroup}"
|
||||||
|
vpntype[$nvpns]="${thisvpntype}"
|
||||||
|
server[$nvpns]="${thisserver}"
|
||||||
|
routes[$nvpns]="${thisroutes}"
|
||||||
|
servercert[$nvpns]="${thisservercert}"
|
||||||
|
nvpns=$((nvpns + 1))
|
||||||
|
done <<< "${CONFLINES}"
|
||||||
|
else
|
||||||
|
error "Config file '$CONFFILE' not found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function usage() {
|
||||||
|
echo "$0 [OPTIONS] on|off|status|list [vpnname]"
|
||||||
|
echo
|
||||||
|
echo "Wrapper for openconnect to support multiple VPN profiles."
|
||||||
|
echo
|
||||||
|
echo " -h show this help"
|
||||||
|
echo " -p profile Use selected connection profile"
|
||||||
|
echo " -c file Use selected config file (default is ${DEFAULTCONF})"
|
||||||
|
echo
|
||||||
|
echo "Config file format:"
|
||||||
|
echo " #Specify default profile like this:"
|
||||||
|
echo " #default:myvpn2"
|
||||||
|
echo " #Profile,Username,Password,VPNGroup,VPNType,ServerIP,VPNRoutes,ServerCert(script will obtain this and auto-update config file)"
|
||||||
|
echo " myvpn1,username_1,password_1,vpngroup_1,anyconnect,3.3.3.3,10.0.0.0/24 192.168.0.0/24,"
|
||||||
|
echo " myvpn2,username_2,password_2,vpngroup_2,anyconnect,1.1.1.1,172.16.0.0/12,"
|
||||||
|
echo " myvpn3,username_3,password_3,,f5,1.1.1.1,172.16.0.0/12,"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_profile_id() { #1=profile_to_check
|
||||||
|
local x lookfor="$1"
|
||||||
|
for x in ${!profile[@]}; do
|
||||||
|
if [[ ${profile[$x],,} == ${lookfor,,} ]]; then
|
||||||
|
echo "${x}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
error "No credentials found for the VPN profile ^b${PROFILE}^p." >&2
|
||||||
|
csecho "$RED" "Add a line of this format to ^b${CONFFILE}^p:" >&2
|
||||||
|
csecho "$RED" "${PROFILE},^iusername^p,^ipassword^p[,^igroup]^p" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_vpn_status() { # populates vprofile vuser vstatus vserver vvpntype, return 0 if vpn up
|
||||||
|
local rv=0 vpnpid pname
|
||||||
|
vprofile=""
|
||||||
|
vuser=""
|
||||||
|
vstatus="Disconnected"
|
||||||
|
vserver=""
|
||||||
|
vvpntype=""
|
||||||
|
|
||||||
|
if [[ -e $VPNPIDFILE ]]; then
|
||||||
|
vpnpid=$(cat $VPNPIDFILE 2>/dev/null)
|
||||||
|
pname=$(ps -p $vpnpid -o command="" 2>/dev/null)
|
||||||
|
vstatus="Connected"
|
||||||
|
vserver=$(echo "$pname" | awk '{ print $NF }')
|
||||||
|
vuser=$(echo "$pname" | sed 's/^.*-u //;s/ .*//g')
|
||||||
|
vvpntype=$(echo "$pname" | sed 's/^.*--protocol=//;s/ .*//g')
|
||||||
|
else
|
||||||
|
rv=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $vstatus == "Connected" ]]; then
|
||||||
|
# find matching profile
|
||||||
|
for x in ${!profile[@]}; do
|
||||||
|
if [[ $vserver == ${server[$x]} ]]; then
|
||||||
|
vprofile="${profile[$x]}"
|
||||||
|
[[ -z $vuser ]] && vuser=${user[$x]}
|
||||||
|
[[ -z $vvpntype ]] && vvpntype=${vvpntype[$x]}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
return $rv
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILE=""
|
||||||
|
|
||||||
|
ARGS="hp:"
|
||||||
|
while getopts "$ARGS" i; do
|
||||||
|
case "$i" in
|
||||||
|
p)
|
||||||
|
profile="$OPTARG";
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
h)
|
||||||
|
usage;
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "invalid argument: $i";
|
||||||
|
usage;
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift $((OPTIND - 1))
|
||||||
|
|
||||||
|
if [[ $# -lt 1 ]]; then
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cmd=$(alias_to_cmd "$1")
|
||||||
|
|
||||||
|
load_config || exit 1
|
||||||
|
|
||||||
|
usingdefault=0
|
||||||
|
PROFILE="$2"
|
||||||
|
if [[ -z $PROFILE ]]; then
|
||||||
|
if [[ -n ${DEFAULTPROFILE} ]]; then
|
||||||
|
PROFILE="${DEFAULTPROFILE}"
|
||||||
|
usingdefault=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $cmd == "list" ]]; then
|
||||||
|
F="%s,%s,%s,%s,%s,%s\n"
|
||||||
|
table=$(
|
||||||
|
(
|
||||||
|
printf "${F}" "Profile" "Username" "Password" "Group" "Server" "Type"
|
||||||
|
for x in ${!profile[@]}; do
|
||||||
|
p="${pw[$x]:0:2}....${pw[$x]: (-2)}"
|
||||||
|
prof="${profile[$x]}"
|
||||||
|
[[ $prof == $DEFAULTPROFILE ]] && prof="*${prof}"
|
||||||
|
printf "${F}" "${prof}" "${user[$x]}" "${p}" "${group[$x]:-(n/a)}" "${server[$x]:-(n/a)}" "${vpntype[$x]}"
|
||||||
|
done
|
||||||
|
) | column -s, -t
|
||||||
|
)
|
||||||
|
table=$(echo "$table" | sed "s/^\(Profile.*\)$/^b^u\1^p/;s/\(n\/a\)/^i\1^p/g")
|
||||||
|
csecho "$WHITE" "$table"
|
||||||
|
echo
|
||||||
|
echo "(* = default VPN)"
|
||||||
|
exit 0
|
||||||
|
elif [[ $cmd == "on" ]]; then
|
||||||
|
[[ $usingdefault -eq 1 ]] && inform "[using default VPN: ^b$DEFAULTPROFILE^p]"
|
||||||
|
get_vpn_status
|
||||||
|
if [[ $vstatus == "Connected" ]]; then
|
||||||
|
error "VPN profile $vprofile is already connected"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z ${PROFILE} ]]; then
|
||||||
|
error "No VPN profile provided and no default VPN profile set."
|
||||||
|
csecho "$RED" "Either specify on commandline, or add this to ^b${CONFFILE}^p:"
|
||||||
|
csecho "$RED" "#default:^ivpn_name^p"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
id=$(get_profile_id "${PROFILE}")
|
||||||
|
if [[ -n $id ]]; then
|
||||||
|
curprofile=${profile[$id]}
|
||||||
|
curuser=${user[$id]}
|
||||||
|
curpw=${pw[$id]}
|
||||||
|
curgroup=${group[$id]}
|
||||||
|
curvpntype=${vpntype[$id]}
|
||||||
|
curserver=${server[$id]}
|
||||||
|
curservercert=${servercert[$id]}
|
||||||
|
curroutes=${routes[$id]}
|
||||||
|
else
|
||||||
|
error "Could not determine VPN ID for profile ^b${PROFILE}^p."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n $curgroup ]]; then
|
||||||
|
grouparg="--authgroup=$curgroup"
|
||||||
|
else
|
||||||
|
grouparg=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $curservercert ]]; then
|
||||||
|
inform "No server certificate is defined for ^b$curprofile^p."
|
||||||
|
notify "Trying to obtain server certificate"
|
||||||
|
foundcert=$(sudo ${OPENCONNECT} --non-inter --protocol=anyconnect -u "$curuser" $grouparg "$curserver" 2>&1 | grep -- --servercert | awk '{ print $NF }')
|
||||||
|
if [[ -n $foundcert ]]; then
|
||||||
|
ok
|
||||||
|
inform "Got server certificate '^b${foundcert}^p'"
|
||||||
|
notify "Updating configuration file ^b$CONFFILE^p"
|
||||||
|
bakfile="${CONFFILE}".backup
|
||||||
|
prevlines=$(cat "$CONFFILE" | awk NF | wc -l | bc)
|
||||||
|
newconfig=$(cat "${CONFFILE}" | awk -v p="$curprofile" -v c="$foundcert" -F, '{ OFS=","; if ($1 == p) { $8 = c; } print }')
|
||||||
|
newlines=$(echo "$newconfig" | awk NF | wc -l | bc)
|
||||||
|
|
||||||
|
err=""
|
||||||
|
if [[ $newlines -ne $prevlines ]]; then
|
||||||
|
err="line count different"
|
||||||
|
elif ! grep -q pin-sha256 <<<"$newconfig"; then
|
||||||
|
err="new config missing server cert"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $err ]]; then
|
||||||
|
ok
|
||||||
|
cp -p "${CONFFILE}" "${bakfile}"
|
||||||
|
echo "$newconfig" > ${CONFFILE}
|
||||||
|
curservercert="$foundcert"
|
||||||
|
else
|
||||||
|
fail
|
||||||
|
error "Regenerated config file seems wrong ($err)"
|
||||||
|
cecho -s "$RED" "Current config:"
|
||||||
|
cecho -s "$RED" "$(cat "$CONFFILE")" | sed 's/^/ /'
|
||||||
|
echo
|
||||||
|
cecho -s "$RED" "Newly generated config:"
|
||||||
|
cecho -s "$RED" "$newconfig" | sed 's/^/ /'
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
fail
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
nstr="Connecting to ^b${PROFILE}^p as user ^b${curuser}^p"
|
||||||
|
[[ -n $curgroup ]] && nstr="${nstr} group ${curgroup}"
|
||||||
|
[[ -n $curserver ]] && nstr="${nstr} server ${curserver}"
|
||||||
|
|
||||||
|
notify "${nstr}"
|
||||||
|
|
||||||
|
rm -f "$VPNPIDFILE"
|
||||||
|
if [[ -n $curroutes ]]; then
|
||||||
|
printf '%s' "$curpw" | sudo ${OPENCONNECT} --background --non-inter --protocol=$vpntype -u "$curuser" --passwd-on-stdin $grouparg -s "$VPNSLICE $curroutes" --servercert "$curservercert" "$curserver" >"${LOGFILE}" 2>&1
|
||||||
|
else
|
||||||
|
printf '%s' "$curpw" | sudo ${OPENCONNECT} --background --non-inter --protocol=$vpntype -u "$curuser" --passwd-on-stdin $grouparg --servercert "$curservercert" "$curserver" >"${LOGFILE}" 2>&1
|
||||||
|
fi
|
||||||
|
rv=$?
|
||||||
|
res=$(cat "$LOGFILE")
|
||||||
|
if [[ $rv -eq 0 ]]; then
|
||||||
|
cpid=$(pgrep openconnect)
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
echo "$cpid" > "$VPNPIDFILE"
|
||||||
|
else
|
||||||
|
rv=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ $rv -eq 0 ]]; then
|
||||||
|
ok "connected"
|
||||||
|
else
|
||||||
|
fail
|
||||||
|
error "Connection failed, logs are below:"
|
||||||
|
cecho -s "$RED" "$res" | sed 's/^/ /'
|
||||||
|
fi
|
||||||
|
elif [[ $cmd == "status" ]]; then
|
||||||
|
BASECOL="$ORANGE"
|
||||||
|
notify "Checking VPN status"
|
||||||
|
get_vpn_status
|
||||||
|
[[ $? -eq 0 ]] && ok || fail
|
||||||
|
if [[ $vstatus == "Connected" ]]; then
|
||||||
|
col="$GREEN"
|
||||||
|
else
|
||||||
|
col="$RED"
|
||||||
|
fi
|
||||||
|
csecho -n "$BASECOL" "VPN status: ${col}${BOLD}${vstatus}^p"
|
||||||
|
if [[ ${vstatus,,} =~ "connected" ]]; then
|
||||||
|
[[ -n $vserver ]] && csecho "$BASECOL" " to ^b${vprofile}^p (${vvpntype}:${vuser}@${vserver})" || echo
|
||||||
|
fi
|
||||||
|
elif [[ $cmd == "off" ]]; then
|
||||||
|
rv=1
|
||||||
|
get_vpn_status
|
||||||
|
if [[ $vstatus == "Connected" ]]; then
|
||||||
|
notify "Disconnecting from ${vvpntype} VPN ^b${vprofile}^p"
|
||||||
|
errstring=""
|
||||||
|
errdata=""
|
||||||
|
|
||||||
|
thepid=$(cat $VPNPIDFILE)
|
||||||
|
if [[ -n $thepid ]]; then
|
||||||
|
sudo kill $thepid
|
||||||
|
sleep 2 # give it some time
|
||||||
|
res=$(ps -p $thepid 2>&1)
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
rm -f "${VPNPIDFILE}"
|
||||||
|
rv=0
|
||||||
|
else
|
||||||
|
errstring="could not kill pid $thepid:"
|
||||||
|
errdata="$res"
|
||||||
|
rv=1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
errstring="Cannot determine current VPN PID to kill."
|
||||||
|
rv=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $rv -eq 0 ]]; then
|
||||||
|
ok
|
||||||
|
else
|
||||||
|
fail
|
||||||
|
error "$errstring"
|
||||||
|
[[ -n $errdata ]] && cecho -s "$RED" "$errdata" | sed 's/^/ /'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
fail
|
||||||
|
error "All VPNs are already disconnected"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
20
README.md
20
README.md
|
@ -2,21 +2,19 @@
|
||||||
|
|
||||||
![speeddiff](cvpn.png "speed difference")
|
![speeddiff](cvpn.png "speed difference")
|
||||||
|
|
||||||
Simple CLI wrapper for Cisco's Anyconnect client and F5's BIG-IP VPN client.
|
Simple CLI wrapper for Openconnect to support multiple VPN profiles.
|
||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
- [bash](https://www.gnu.org/software/bash/) version >= 4.x
|
- [bash](https://www.gnu.org/software/bash/) version >= 4.x
|
||||||
- [gof5](https://github.com/kayrus/gof5) (for F5 VPNs)
|
- [openconnect](https://github.com/openconnect)
|
||||||
- [openconnect](https://github.com/openconnect) (for Cisco VPNs)
|
- [vpn-slice](https://github.com/dlenski/vpn-slice)
|
||||||
- [vpn-slice](https://github.com/dlenski/vpn-slice) (for Cisco VPNs)
|
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
```text
|
```text
|
||||||
rob@crom:cvpn$ cvpn -h
|
./cvpn [OPTIONS] on|off|status|list [vpnname]
|
||||||
${PATH}/cvpn [OPTIONS] on|off [vpnname]
|
|
||||||
|
|
||||||
Wrapper for cisco anyconnect 'vpn' script.
|
Wrapper for openconnect to support multiple VPN profiles.
|
||||||
|
|
||||||
-h show this help
|
-h show this help
|
||||||
-p profile Use selected connection profile
|
-p profile Use selected connection profile
|
||||||
|
@ -25,11 +23,11 @@ Wrapper for cisco anyconnect 'vpn' script.
|
||||||
Config file format:
|
Config file format:
|
||||||
#Specify default profile like this:
|
#Specify default profile like this:
|
||||||
#default:myvpn2
|
#default:myvpn2
|
||||||
#Profile,Username,Password,VPNGroup,Vendor,ServerIP,VPNRoutes,ServerCert(for Cisco, script will obtain this and auto-update config file )
|
#Profile,Username,Password,VPNGroup,Vendor,ServerIP,VPNRoutes,ServerCert(script will obtain this and auto-update config file)
|
||||||
# Cisco VPNs, group is optional
|
# Cisco VPNs, group is optional
|
||||||
myvpn1,username_1,password_1,vpngroup_1,cisco,3.3.3.3,10.0.0.0/24 192.168.0.0/24,
|
myvpn1,username_1,password_1,vpngroup_1,anyconnect,3.3.3.3,10.0.0.0/24 192.168.0.0/24,
|
||||||
myvpn2,username_2,password_2,vpngroup_2,cisco,1.1.1.1,172.16.0.0/12,
|
myvpn2,username_2,password_2,vpngroup_2,anyconnect,1.1.1.1,172.16.0.0/12,
|
||||||
# F5 VPNs
|
# F5 VPNs
|
||||||
myvpn3,username_3,password_3,,f5,1.2.3.4
|
myvpn3,username_3,password_3,,f5,1.1.1.1,172.16.0.0/12,
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
129
cvpn
129
cvpn
|
@ -7,23 +7,27 @@ if [[ -z $HAVE_BASHTOOLS ]]; then
|
||||||
fi
|
fi
|
||||||
CONFDIR=${HOME}/.vpn
|
CONFDIR=${HOME}/.vpn
|
||||||
LOGFILE=${CONFDIR}/log
|
LOGFILE=${CONFDIR}/log
|
||||||
VPNPIDFILE=${CONFDIR}/f5pid
|
VPNPIDFILE=${CONFDIR}/vpnpid
|
||||||
DEFAULTCONF=${CONFDIR}/config
|
DEFAULTCONF=${CONFDIR}/config
|
||||||
CONFFILE=${DEFAULTCONF}
|
CONFFILE=${DEFAULTCONF}
|
||||||
VALID_VENDORS="cisco|f5"
|
|
||||||
|
|
||||||
cp -p "$LOGFILE" "${LOGFILE}.0"
|
cp -p "$LOGFILE" "${LOGFILE}.0"
|
||||||
cp /dev/null "$LOGFILE"
|
cp /dev/null "$LOGFILE"
|
||||||
|
|
||||||
|
err=0
|
||||||
OPENCONNECT=$(which openconnect 2>/dev/null)
|
OPENCONNECT=$(which openconnect 2>/dev/null)
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
warn "Can't find openconnect binary - Cisco VPNs won't work."
|
error "Can't find openconnect binary"
|
||||||
|
err=$((err + 1))
|
||||||
fi
|
fi
|
||||||
VPNSLICE=$(which vpn-slice 2>/dev/null)
|
VPNSLICE=$(which vpn-slice 2>/dev/null)
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
warn "Can't find vpn-slice binary - Cisco VPNs won't work."
|
error "Can't find vpn-slice binary"
|
||||||
|
err=$((err + 1))
|
||||||
|
fi
|
||||||
|
if [[ $ree -ne 0 ]]; then
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
mkdir -p "${CONFDIR}"
|
mkdir -p "${CONFDIR}"
|
||||||
|
|
||||||
|
@ -61,14 +65,18 @@ function load_config() {
|
||||||
thisuser=$(cut -d, -f2 <<< "${line}")
|
thisuser=$(cut -d, -f2 <<< "${line}")
|
||||||
thispw=$(cut -d, -f3 <<< "${line}")
|
thispw=$(cut -d, -f3 <<< "${line}")
|
||||||
thisgroup=$(cut -d, -f4 <<< "${line}")
|
thisgroup=$(cut -d, -f4 <<< "${line}")
|
||||||
thisvendor=$(cut -d, -f5 <<< "${line}")
|
thisvpntype=$(cut -d, -f5 <<< "${line}")
|
||||||
thisserver=$(cut -d, -f6 <<< "${line}")
|
thisserver=$(cut -d, -f6 <<< "${line}")
|
||||||
thisroutes=$(cut -d, -f7 <<< "${line}")
|
thisroutes=$(cut -d, -f7 <<< "${line}")
|
||||||
thisservercert=$(cut -d, -f8 <<< "${line}")
|
thisservercert=$(cut -d, -f8 <<< "${line}")
|
||||||
[[ -z $thisvendor ]] && thisvendor="cisco"
|
case $thisvpntype in
|
||||||
[[ -z $thisserver ]] && thisvendor="n/a"
|
"") thisvpntype="anyconnect";;
|
||||||
if [[ ! $thisvendor =~ $VALID_VENDORS ]]; then
|
"cisco") thisvpntype="anyconnect";;
|
||||||
error "invalid VPN vendor '$thisvendor', must be $VALID_VENDORS"
|
"bigip") thisvpntype="anyconnect";;
|
||||||
|
"big-ip") thisvpntype="anyconnect";;
|
||||||
|
esac
|
||||||
|
if [[ -z $thisserver ]]; then
|
||||||
|
error "Missing server IP for profile '$thisprofile'"
|
||||||
cecho -s "$RED" "^bBad line:^p $line"
|
cecho -s "$RED" "^bBad line:^p $line"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
@ -76,7 +84,7 @@ function load_config() {
|
||||||
user[$nvpns]="${thisuser}"
|
user[$nvpns]="${thisuser}"
|
||||||
pw[$nvpns]="${thispw}"
|
pw[$nvpns]="${thispw}"
|
||||||
group[$nvpns]="${thisgroup}"
|
group[$nvpns]="${thisgroup}"
|
||||||
vendor[$nvpns]="${thisvendor}"
|
vpntype[$nvpns]="${thisvpntype}"
|
||||||
server[$nvpns]="${thisserver}"
|
server[$nvpns]="${thisserver}"
|
||||||
routes[$nvpns]="${thisroutes}"
|
routes[$nvpns]="${thisroutes}"
|
||||||
servercert[$nvpns]="${thisservercert}"
|
servercert[$nvpns]="${thisservercert}"
|
||||||
|
@ -90,9 +98,9 @@ function load_config() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function usage() {
|
function usage() {
|
||||||
echo "$0 [OPTIONS] on|off [vpnname]"
|
echo "$0 [OPTIONS] on|off|status|list [vpnname]"
|
||||||
echo
|
echo
|
||||||
echo "Wrapper for cisco anyconnect 'vpn' script."
|
echo "Wrapper for openconnect to support multiple VPN profiles."
|
||||||
echo
|
echo
|
||||||
echo " -h show this help"
|
echo " -h show this help"
|
||||||
echo " -p profile Use selected connection profile"
|
echo " -p profile Use selected connection profile"
|
||||||
|
@ -101,19 +109,17 @@ function usage() {
|
||||||
echo "Config file format:"
|
echo "Config file format:"
|
||||||
echo " #Specify default profile like this:"
|
echo " #Specify default profile like this:"
|
||||||
echo " #default:myvpn2"
|
echo " #default:myvpn2"
|
||||||
echo " #Profile,Username,Password,VPNGroup,VPNType,ServerIP"
|
echo " #Profile,Username,Password,VPNGroup,VPNType,ServerIP,VPNRoutes,ServerCert(script will obtain this and auto-update config file)"
|
||||||
echo " # Cisco VPNs have just user 'server' for status, and group is optional"
|
echo " myvpn1,username_1,password_1,vpngroup_1,anyconnect,3.3.3.3,10.0.0.0/24 192.168.0.0/24,"
|
||||||
echo " myvpn1,username_1,password_1,vpngroup_1,cisco,3.3.3.3"
|
echo " myvpn2,username_2,password_2,vpngroup_2,anyconnect,1.1.1.1,172.16.0.0/12,"
|
||||||
echo " myvpn2,username_2,password_2,vpngroup_2,cisco,1.1.1.1"
|
echo " myvpn3,username_3,password_3,,f5,1.1.1.1,172.16.0.0/12,"
|
||||||
echo " # F5 VPNs must have a 'server'"
|
|
||||||
echo " myvpn3,username_3,password_3,,f5,1.2.3.4"
|
|
||||||
echo
|
echo
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_profile_id() { #1=profile_to_check
|
function get_profile_id() { #1=profile_to_check
|
||||||
local x lookfor="$1"
|
local x lookfor="$1"
|
||||||
for x in ${!profile[@]}; do
|
for x in ${!profile[@]}; do
|
||||||
if [[ ${profile[$x]} == $lookfor ]]; then
|
if [[ ${profile[$x],,} == ${lookfor,,} ]]; then
|
||||||
echo "${x}"
|
echo "${x}"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
@ -124,28 +130,21 @@ function get_profile_id() { #1=profile_to_check
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_vpn_status() { # populates vprofile vuser vstatus vserver vvendor, return 0 if vpn up
|
function get_vpn_status() { # populates vprofile vuser vstatus vserver vvpntype, return 0 if vpn up
|
||||||
local rv=0 fpid pname
|
local rv=0 vpnpid pname
|
||||||
vprofile=""
|
vprofile=""
|
||||||
vuser=""
|
vuser=""
|
||||||
vstatus="Disconnected"
|
vstatus="Disconnected"
|
||||||
vserver=""
|
vserver=""
|
||||||
vvendor=""
|
vvpntype=""
|
||||||
|
|
||||||
if [[ -e $VPNPIDFILE ]]; then
|
if [[ -e $VPNPIDFILE ]]; then
|
||||||
fpid=$(cat $VPNPIDFILE 2>/dev/null)
|
vpnpid=$(cat $VPNPIDFILE 2>/dev/null)
|
||||||
pname=$(ps -p $fpid -o command="" 2>/dev/null)
|
pname=$(ps -p $vpnpid -o command="" 2>/dev/null)
|
||||||
if [[ $pname =~ gof5 ]]; then
|
|
||||||
vstatus="Connected"
|
|
||||||
vserver=$(echo "$pname" | sed 's/^.*--server //;s/ .*//g')
|
|
||||||
vuser=$(echo "$pname" | sed 's/^.*--username //;s/ .*//g')
|
|
||||||
vvendor=F5
|
|
||||||
elif [[ $pname =~ openconnect ]]; then
|
|
||||||
vstatus="Connected"
|
vstatus="Connected"
|
||||||
vserver=$(echo "$pname" | awk '{ print $NF }')
|
vserver=$(echo "$pname" | awk '{ print $NF }')
|
||||||
vuser=$(echo "$pname" | sed 's/^.*-u //;s/ .*//g')
|
vuser=$(echo "$pname" | sed 's/^.*-u //;s/ .*//g')
|
||||||
vvendor=Cisco
|
vvpntype=$(echo "$pname" | sed 's/^.*--protocol=//;s/ .*//g')
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
rv=1
|
rv=1
|
||||||
fi
|
fi
|
||||||
|
@ -156,7 +155,7 @@ function get_vpn_status() { # populates vprofile vuser vstatus vserver vvendor,
|
||||||
if [[ $vserver == ${server[$x]} ]]; then
|
if [[ $vserver == ${server[$x]} ]]; then
|
||||||
vprofile="${profile[$x]}"
|
vprofile="${profile[$x]}"
|
||||||
[[ -z $vuser ]] && vuser=${user[$x]}
|
[[ -z $vuser ]] && vuser=${user[$x]}
|
||||||
[[ -z $vvendor ]] && vvendor=${vvendor[$x]}
|
[[ -z $vvpntype ]] && vvpntype=${vvpntype[$x]}
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
@ -202,9 +201,6 @@ if [[ -z $PROFILE ]]; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
pgrep -q gof5 && f5up=1 || f5up=0
|
|
||||||
|
|
||||||
if [[ $cmd == "list" ]]; then
|
if [[ $cmd == "list" ]]; then
|
||||||
F="%s,%s,%s,%s,%s,%s\n"
|
F="%s,%s,%s,%s,%s,%s\n"
|
||||||
table=$(
|
table=$(
|
||||||
|
@ -214,7 +210,7 @@ if [[ $cmd == "list" ]]; then
|
||||||
p="${pw[$x]:0:2}....${pw[$x]: (-2)}"
|
p="${pw[$x]:0:2}....${pw[$x]: (-2)}"
|
||||||
prof="${profile[$x]}"
|
prof="${profile[$x]}"
|
||||||
[[ $prof == $DEFAULTPROFILE ]] && prof="*${prof}"
|
[[ $prof == $DEFAULTPROFILE ]] && prof="*${prof}"
|
||||||
printf "${F}" "${prof}" "${user[$x]}" "${p}" "${group[$x]:-(n/a)}" "${server[$x]:-(n/a)}" "${vendor[$x]}"
|
printf "${F}" "${prof}" "${user[$x]}" "${p}" "${group[$x]:-(n/a)}" "${server[$x]:-(n/a)}" "${vpntype[$x]}"
|
||||||
done
|
done
|
||||||
) | column -s, -t
|
) | column -s, -t
|
||||||
)
|
)
|
||||||
|
@ -243,7 +239,7 @@ elif [[ $cmd == "on" ]]; then
|
||||||
curuser=${user[$id]}
|
curuser=${user[$id]}
|
||||||
curpw=${pw[$id]}
|
curpw=${pw[$id]}
|
||||||
curgroup=${group[$id]}
|
curgroup=${group[$id]}
|
||||||
curvendor=${vendor[$id]}
|
curvpntype=${vpntype[$id]}
|
||||||
curserver=${server[$id]}
|
curserver=${server[$id]}
|
||||||
curservercert=${servercert[$id]}
|
curservercert=${servercert[$id]}
|
||||||
curroutes=${routes[$id]}
|
curroutes=${routes[$id]}
|
||||||
|
@ -252,10 +248,16 @@ elif [[ $cmd == "on" ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z $curservercert && ${curvendor,,} == "cisco" ]]; then
|
if [[ -n $curgroup ]]; then
|
||||||
|
grouparg="--authgroup=$curgroup"
|
||||||
|
else
|
||||||
|
grouparg=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $curservercert ]]; then
|
||||||
inform "No server certificate is defined for ^b$curprofile^p."
|
inform "No server certificate is defined for ^b$curprofile^p."
|
||||||
notify "Trying to obtain server certificate"
|
notify "Trying to obtain server certificate"
|
||||||
foundcert=$(sudo ${OPENCONNECT} --non-inter --protocol=anyconnect -u "$curuser" --authgroup="$curgroup" "$curserver" 2>&1 | grep -- --servercert | awk '{ print $NF }')
|
foundcert=$(sudo ${OPENCONNECT} --non-inter --protocol=$curvpntype -u "$curuser" $grouparg "$curserver" 2>&1 | grep -- --servercert | awk '{ print $NF }')
|
||||||
if [[ -n $foundcert ]]; then
|
if [[ -n $foundcert ]]; then
|
||||||
ok
|
ok
|
||||||
inform "Got server certificate '^b${foundcert}^p'"
|
inform "Got server certificate '^b${foundcert}^p'"
|
||||||
|
@ -301,46 +303,10 @@ elif [[ $cmd == "on" ]]; then
|
||||||
notify "${nstr}"
|
notify "${nstr}"
|
||||||
|
|
||||||
rm -f "$VPNPIDFILE"
|
rm -f "$VPNPIDFILE"
|
||||||
if [[ $curvendor == "f5" ]]; then
|
|
||||||
nohup sudo gof5 --server "${curserver}" --username "${curuser}" --password "${curpw}" >>${LOGFILE} 2>&1 &
|
|
||||||
f5pid=$!
|
|
||||||
nlines=0
|
|
||||||
res=""
|
|
||||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
||||||
nlines=$((nlines + 1))
|
|
||||||
if [[ ${line,,} =~ stablished ]]; then
|
|
||||||
rv=0
|
|
||||||
res="$line"
|
|
||||||
break
|
|
||||||
elif [[ ${line,,} =~ failed ]]; then
|
|
||||||
rv=1;
|
|
||||||
res="$line"
|
|
||||||
break;
|
|
||||||
elif [[ ${nlines} -ge 30 ]]; then
|
|
||||||
rv=4;
|
|
||||||
res="$line"
|
|
||||||
break;
|
|
||||||
fi
|
|
||||||
ps -p $f5pid >/dev/null 2>&1
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
rv=2;
|
|
||||||
res="$line"
|
|
||||||
break;
|
|
||||||
fi
|
|
||||||
done < <(timeout 300 tail -f ${LOGFILE} )
|
|
||||||
|
|
||||||
if [[ -z $res ]]; then
|
|
||||||
rv=3;
|
|
||||||
res="$(tail -n 10 ${LOGFILE})"
|
|
||||||
fi
|
|
||||||
if [[ $rv -eq 0 ]]; then
|
|
||||||
echo "$f5pid" > "$VPNPIDFILE"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [[ -n $curroutes ]]; then
|
if [[ -n $curroutes ]]; then
|
||||||
printf '%s' "$curpw" | sudo ${OPENCONNECT} --background --non-inter --protocol=anyconnect -u "$curuser" --passwd-on-stdin --authgroup="$curgroup" -s "$VPNSLICE $curroutes" --servercert "$curservercert" "$curserver" >"${LOGFILE}" 2>&1
|
printf '%s' "$curpw" | sudo ${OPENCONNECT} --background --non-inter --protocol=$curvpntype -u "$curuser" --passwd-on-stdin $grouparg -s "$VPNSLICE $curroutes" --servercert "$curservercert" "$curserver" >"${LOGFILE}" 2>&1
|
||||||
else
|
else
|
||||||
printf '%s' "$curpw" | sudo ${OPENCONNECT} --background --non-inter --protocol=anyconnect -u "$curuser" --passwd-on-stdin --authgroup="$curgroup" --servercert "$curservercert" "$curserver" >"${LOGFILE}" 2>&1
|
printf '%s' "$curpw" | sudo ${OPENCONNECT} --background --non-inter --protocol=$curvpntype -u "$curuser" --passwd-on-stdin $grouparg --servercert "$curservercert" "$curserver" >"${LOGFILE}" 2>&1
|
||||||
fi
|
fi
|
||||||
rv=$?
|
rv=$?
|
||||||
res=$(cat "$LOGFILE")
|
res=$(cat "$LOGFILE")
|
||||||
|
@ -352,7 +318,6 @@ elif [[ $cmd == "on" ]]; then
|
||||||
rv=1
|
rv=1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
if [[ $rv -eq 0 ]]; then
|
if [[ $rv -eq 0 ]]; then
|
||||||
ok "connected"
|
ok "connected"
|
||||||
else
|
else
|
||||||
|
@ -372,13 +337,13 @@ elif [[ $cmd == "status" ]]; then
|
||||||
fi
|
fi
|
||||||
csecho -n "$BASECOL" "VPN status: ${col}${BOLD}${vstatus}^p"
|
csecho -n "$BASECOL" "VPN status: ${col}${BOLD}${vstatus}^p"
|
||||||
if [[ ${vstatus,,} =~ "connected" ]]; then
|
if [[ ${vstatus,,} =~ "connected" ]]; then
|
||||||
[[ -n $vserver ]] && csecho "$BASECOL" " to ^b${vprofile}^p (${vvendor}:${vuser}@${vserver})" || echo
|
[[ -n $vserver ]] && csecho "$BASECOL" " to ^b${vprofile}^p (${vvpntype}:${vuser}@${vserver})" || echo
|
||||||
fi
|
fi
|
||||||
elif [[ $cmd == "off" ]]; then
|
elif [[ $cmd == "off" ]]; then
|
||||||
rv=1
|
rv=1
|
||||||
get_vpn_status
|
get_vpn_status
|
||||||
if [[ $vstatus == "Connected" ]]; then
|
if [[ $vstatus == "Connected" ]]; then
|
||||||
notify "Disconnecting from ${vvendor} VPN ^b${vprofile}^p"
|
notify "Disconnecting from ${vvpntype} VPN ^b${vprofile}^p"
|
||||||
errstring=""
|
errstring=""
|
||||||
errdata=""
|
errdata=""
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue