Move to openconnet + vpnslice

This commit is contained in:
Rob Pearce 2023-10-11 11:43:11 +11:00
parent 119d9c0d38
commit bb03283347
1 changed files with 104 additions and 38 deletions

142
cvpn
View File

@ -15,7 +15,15 @@ VALID_VENDORS="cisco|f5"
cp -p "$LOGFILE" "${LOGFILE}.0"
cp /dev/null "$LOGFILE"
VPN=/opt/cisco/anyconnect/bin/vpn
OPENCONNECT=$(which openconnect 2>/dev/null)
if [[ $? -ne 0 ]]; then
warn "Can't find openconnect binary - Cisco VPNs won't work."
fi
VPNSLICE=$(which vpn-slice 2>/dev/null)
if [[ $? -ne 0 ]]; then
warn "Can't find vpn-slice binary - Cisco VPNs won't work."
fi
mkdir -p "${CONFDIR}"
@ -41,7 +49,7 @@ function alias_to_cmd() {
}
function load_config() {
local CONFLINES line thisprofile thisuser thispw thisgroup
local CONFLINES line thisprofile thisuser thispw thisgroup thisroutes thisservercert
DEFAULTPROFILE=""
if [[ -e ${CONFFILE} ]]; then
DEFAULTPROFILE=$(grep '^#default:' "${CONFFILE}" | sed 's/^#default://')
@ -55,6 +63,8 @@ function load_config() {
thisgroup=$(cut -d, -f4 <<< "${line}")
thisvendor=$(cut -d, -f5 <<< "${line}")
thisserver=$(cut -d, -f6 <<< "${line}")
thisroutes=$(cut -d, -f7 <<< "${line}")
thisservercert=$(cut -d, -f8 <<< "${line}")
[[ -z $thisvendor ]] && thisvendor="cisco"
[[ -z $thisserver ]] && thisvendor="n/a"
if [[ ! $thisvendor =~ $VALID_VENDORS ]]; then
@ -68,6 +78,8 @@ function load_config() {
group[$nvpns]="${thisgroup}"
vendor[$nvpns]="${thisvendor}"
server[$nvpns]="${thisserver}"
routes[$nvpns]="${thisroutes}"
servercert[$nvpns]="${thisservercert}"
nvpns=$((nvpns + 1))
done <<< "${CONFLINES}"
else
@ -128,19 +140,14 @@ function get_vpn_status() { # populates vprofile vuser vstatus vserver vvendor,
vserver=$(echo "$pname" | sed 's/^.*--server //;s/ .*//g')
vuser=$(echo "$pname" | sed 's/^.*--username //;s/ .*//g')
vvendor=F5
elif [[ $pname =~ openconnect ]]; then
vstatus="Connected"
vserver=$(echo "$pname" | awk '{ print $NF }')
vuser=$(echo "$pname" | sed 's/^.*-u //;s/ .*//g')
vvendor=Cisco
fi
else
# no f5 vpn, check anyconnect
res=$(${VPN} stats 2>&1)
if [[ $? -eq 0 ]]; then
vstatus=$(grep 'Connection State:' <<< "$res" | grep -v Manage | awk '{ print $3 }' )
if [[ $vstatus == "Connected" ]]; then
vvendor="Cisco"
vserver=$(grep 'Server Address:' <<< "$res" | awk '{ print $3 }' )
fi
else
rv=1
fi
rv=1
fi
if [[ $vstatus == "Connected" ]]; then
@ -232,25 +239,69 @@ elif [[ $cmd == "on" ]]; then
fi
id=$(get_profile_id "${PROFILE}")
if [[ -n $id ]]; then
curprofile=${profile[$id]}
curuser=${user[$id]}
curpw=${pw[$id]}
curgroup=${group[$id]}
curvendor=${vendor[$id]}
if [[ $curvendor == "f5" ]]; then
curserver=${server[$id]}
else
curserver=""
fi
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 [[ -z $curservercert && ${curvendor,,} == "cisco" ]]; 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" --authgroup="$curgroup" "$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 [[ $curvendor == "f5" ]]; then
rm -f "$VPNPIDFILE"
nohup sudo gof5 --server "${curserver}" --username "${curuser}" --password "${curpw}" >>${LOGFILE} 2>&1 &
f5pid=$!
nlines=0
@ -286,25 +337,28 @@ elif [[ $cmd == "on" ]]; then
echo "$f5pid" > "$VPNPIDFILE"
fi
else
if [[ -n $curgroup ]]; then
answers="y\n${curgroup}\n${curuser}\n${curpw}\n"
if [[ -n $curroutes ]]; then
printf '%s' "$curpw" | sudo ${OPENCONNECT} --background --non-inter --protocol=anyconnect -u "$curuser" --passwd-on-stdin --authgroup="$curgroup" -s "$VPNSLICE $routesarg" --servercert "$curservercert" "$curserver" >"${LOGFILE}" 2>&1
else
answers="y\n${curuser}\n${curpw}\n"
printf '%s' "$curpw" | sudo ${OPENCONNECT} --background --non-inter --protocol=anyconnect -u "$curuser" --passwd-on-stdin --authgroup="$curgroup" --servercert "$curservercert" "$curserver" >"${LOGFILE}" 2>&1
fi
res=$(echo -e "$answers" | ${VPN} -s connect "$PROFILE" 2>&1 | tee ${LOGFILE})
grep -q 'state: Connected' <<< "$res$"
rv=$?
res=$(cat "$LOGFILE")
if [[ $rv -eq 0 ]]; then
cpid=$(pgrep openconnect)
if [[ $? -eq 0 ]]; then
echo "$cpid" > "$VPNPIDFILE"
else
rv=1
fi
fi
fi
if [[ $rv -eq 0 ]]; then
ok "connected"
else
fail
if [[ $curvendor == "cisco" ]]; then
error "Connection failed, logs are in ^b${LOGFILE}^p."
else
error "Connection failed, logs are below:"
cecho -s "$RED" "$res" | sed 's/^/ /'
fi
error "Connection failed, logs are below:"
cecho -s "$RED" "$res" | sed 's/^/ /'
fi
elif [[ $cmd == "status" ]]; then
BASECOL="$ORANGE"
@ -325,21 +379,33 @@ elif [[ $cmd == "off" ]]; then
get_vpn_status
if [[ $vstatus == "Connected" ]]; then
notify "Disconnecting from ${vvendor} VPN ^b${vprofile}^p"
errstring=""
errdata=""
if [[ ${vvendor,,} == "f5" ]]; then
#sudo gof5 --server ${s} --close-session
sudo kill $(cat $VPNPIDFILE)
rm -f "${VPNPIDFILE}"
rv=0
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
${VPN} disconnect > ${LOGFILE} 2>&1
rv=$?
errstring="Cannot determine current VPN PID to kill."
rv=1
fi
if [[ $rv -eq 0 ]]; then
ok
else
fail
error "Connection failed, logs are in ^b${LOGFILE}^p."
error "$errstring"
[[ -n $errdata ]] && cecho -s "$RED" "$errdata" | sed 's/^/ /'
fi
else
fail