Rewritten to support connecting to multiple vpns simultaneously.
This commit is contained in:
parent
839244cd61
commit
3852304c59
177
cvpn
177
cvpn
|
@ -70,6 +70,7 @@ function load_config() {
|
|||
thisroutes=$(cut -d, -f7 <<< "${line}")
|
||||
thisdomains=$(cut -d, -f8 <<< "${line}")
|
||||
thisservercert=$(cut -d, -f9 <<< "${line}")
|
||||
thispidfile=${CONFDIR}/${thisprofile// /}.pid
|
||||
case $thisvpntype in
|
||||
"") thisvpntype="anyconnect";;
|
||||
"cisco") thisvpntype="anyconnect";;
|
||||
|
@ -90,6 +91,7 @@ function load_config() {
|
|||
routes[$nvpns]="${thisroutes}"
|
||||
domains[$nvpns]="${thisdomains}"
|
||||
servercert[$nvpns]="${thisservercert}"
|
||||
pidfile[$nvpns]="${thispidfile}"
|
||||
nvpns=$((nvpns + 1))
|
||||
done <<< "${CONFLINES}"
|
||||
else
|
||||
|
@ -132,36 +134,51 @@ function get_profile_id() { #1=profile_to_check
|
|||
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
|
||||
function vpnisup() { # 1=profile
|
||||
local idx pf rv pid
|
||||
idx=$(get_profile_id "$1")
|
||||
rv=$?
|
||||
if [[ $rv -ne 0 || -z $idx ]]; then
|
||||
return 1
|
||||
fi
|
||||
pf=${pidfile[$idx]}
|
||||
if [[ -n $pf && -e $pf ]]; then
|
||||
pid=$(cat $pf)
|
||||
ps -p $pid >/dev/null 2>&1
|
||||
if [[ $? -eq 0 ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
function get_vpn_status() { # populates vprofile[] vpid[] vuser[] vstatus[] vserver[] vvpntype[] nup, return true if any vpns are up
|
||||
local rv=0 vpnpid pname x
|
||||
unset vprofile
|
||||
unset vpnpid
|
||||
unset vstatus
|
||||
unset vserver
|
||||
unset vuser
|
||||
unset vvpntype
|
||||
nup=0
|
||||
|
||||
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]}
|
||||
vpnisup "${profile[$x]}"
|
||||
if [[ $? -eq 0 ]]; then
|
||||
vprofile+=(${profile[$x]})
|
||||
vpid+=($(cat ${pidfile[$x]}))
|
||||
vstatus+=("Connected")
|
||||
vserver+=(${server[$x]})
|
||||
vuser+=(${user[$x]})
|
||||
vvpntype+=(${vpntype[$x]})
|
||||
nup=$((nup + 1))
|
||||
fi
|
||||
done
|
||||
fi
|
||||
return $rv
|
||||
[[ $nup -eq 0 ]] && return 1
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
PROFILE=""
|
||||
|
@ -196,7 +213,7 @@ load_config || exit 1
|
|||
|
||||
usingdefault=0
|
||||
PROFILE="$2"
|
||||
if [[ -z $PROFILE ]]; then
|
||||
if [[ -z $PROFILE && $cmd == "up" ]]; then
|
||||
if [[ -n ${DEFAULTPROFILE} ]]; then
|
||||
PROFILE="${DEFAULTPROFILE}"
|
||||
usingdefault=1
|
||||
|
@ -204,28 +221,56 @@ if [[ -z $PROFILE ]]; then
|
|||
fi
|
||||
|
||||
if [[ $cmd == "list" ]]; then
|
||||
F="%s,%s,%s,%s,%s,%s\n"
|
||||
F="%s,%s,%s,%s,%s,%s,%s,%s\n"
|
||||
|
||||
table=$(
|
||||
(
|
||||
printf "${F}" "Profile" "Username" "Password" "Group" "Server" "Type"
|
||||
printf "${F}" "Profile" "Up?" "Username" "Password" "Group" "Server" "Type" "Scope"
|
||||
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]}"
|
||||
[[ $prof == $DEFAULTPROFILE ]] && prof="${prof}*"
|
||||
vpnisup "${prof}"
|
||||
if [[ $? -eq 0 ]]; then
|
||||
yn="Yes"
|
||||
c="${GREEN}"
|
||||
else
|
||||
yn="No"
|
||||
c="${GREY}"
|
||||
fi
|
||||
scope="${domains[$x]} ${routes[$x]}"
|
||||
vt=${vpntype[$x]}
|
||||
[[ ${vt,,} == "anyconnect" ]] && vt=Cisco
|
||||
printf "${F}" "${prof}" "$yn" "${user[$x]}" "${p}" "${group[$x]:-(n/a)}" "${server[$x]:-(n/a)}" "${vt}" "${scope%% *}"
|
||||
|
||||
# show one route/domain per row
|
||||
scope_a=( ${scope} )
|
||||
#echo "${profile[$x]} scope: [${scope}]" >&2
|
||||
#echo "${profile[$x]} scope_a: [${scope_a[@]}]" >&2
|
||||
if [[ ${#scope_a[@]} -ge 2 ]]; then
|
||||
i=1 # skip first one
|
||||
while [[ $i -lt ${#scope_a[@]} ]]; do
|
||||
printf "${F}" " " " " " " " " " " " " " " "${scope_a[$i]}"
|
||||
i=$((i + 1))
|
||||
done
|
||||
fi
|
||||
done
|
||||
) | column -s, -t
|
||||
)
|
||||
table=$(echo "$table" | sed "s/^\(Profile.*\)$/^b^u\1^p/;s/\(n\/a\)/^i\1^p/g")
|
||||
|
||||
# underline heading
|
||||
table=$(echo "$table" | sed "s/^\(Profile.*\)$/^b^u\1^p/;")
|
||||
table=$(awk -v G="$GREEN" -v P="$PLAIN" '($2 == "Yes") { printf(G); } ($2 == "No") { printf(P); } { print }' <<<"$table")
|
||||
|
||||
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"
|
||||
vpnisup "${PROFILE}"
|
||||
if [[ $? -eq 0 ]]; then
|
||||
error "VPN profile $PROFILE is already connected"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -246,6 +291,7 @@ elif [[ $cmd == "on" ]]; then
|
|||
curservercert=${servercert[$id]}
|
||||
curroutes=${routes[$id]}
|
||||
curdomains=${domains[$id]}
|
||||
curpidfile=${pidfile[$id]}
|
||||
#echo "got curprofile=${profile[$id]}"
|
||||
#echo "got curuser=${user[$id]}"
|
||||
#echo "got curpw=${pw[$id]}"
|
||||
|
@ -255,6 +301,7 @@ elif [[ $cmd == "on" ]]; then
|
|||
#echo "got curservercert=${servercert[$id]}"
|
||||
#echo "got curroutes=${routes[$id]}"
|
||||
#echo "got curdomains=${domains[$id]}"
|
||||
#echo "got curpidfile=${pidfile[$id]}"
|
||||
else
|
||||
error "Could not determine VPN ID for profile ^b${PROFILE}^p."
|
||||
exit 1
|
||||
|
@ -314,22 +361,26 @@ elif [[ $cmd == "on" ]]; then
|
|||
|
||||
notify "${nstr}"
|
||||
|
||||
rm -f "$VPNPIDFILE"
|
||||
rm -f "$curpidfile"
|
||||
if [[ -n $curroutes && -n $curdomains ]]; then
|
||||
printf '%s' "$curpw" | sudo ${OPENCONNECT} --background --non-inter --protocol=$curvpntype -u "$curuser" --passwd-on-stdin $grouparg -s "$VPNSLICE --domains-vpn-dns ${curdomains// /,} $curroutes" --servercert "$curservercert" "$curserver" >"${LOGFILE}" 2>&1
|
||||
rv=$?
|
||||
elif [[ -n $curroutes ]]; then
|
||||
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
|
||||
rv=$?
|
||||
elif [[ -n $curdomains ]]; then
|
||||
printf '%s' "$curpw" | sudo ${OPENCONNECT} --background --non-inter --protocol=$curvpntype -u "$curuser" --passwd-on-stdin $grouparg -s "$VPNSLICE --domains-vpn-dns $curdomains" --servercert "$curservercert" "$curserver" >"${LOGFILE}" 2>&1
|
||||
rv=$?
|
||||
else
|
||||
printf '%s' "$curpw" | sudo ${OPENCONNECT} --background --non-inter --protocol=$curvpntype -u "$curuser" --passwd-on-stdin $grouparg --servercert "$curservercert" "$curserver" >"${LOGFILE}" 2>&1
|
||||
fi
|
||||
rv=$?
|
||||
fi
|
||||
res=$(cat "$LOGFILE")
|
||||
if [[ $rv -eq 0 ]]; then
|
||||
cpid=$(pgrep openconnect)
|
||||
cpid=$(pgrep -f "openconnect.* ${curserver}")
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo "$cpid" > "$VPNPIDFILE"
|
||||
echo "$cpid" > "$curpidfile"
|
||||
rv=0
|
||||
else
|
||||
rv=1
|
||||
fi
|
||||
|
@ -345,31 +396,45 @@ elif [[ $cmd == "status" ]]; then
|
|||
BASECOL="$ORANGE"
|
||||
notify "Checking VPN status"
|
||||
get_vpn_status
|
||||
[[ $? -eq 0 ]] && ok || fail
|
||||
if [[ $vstatus == "Connected" ]]; then
|
||||
col="$GREEN"
|
||||
ok
|
||||
if [[ $nup -eq 0 ]]; then
|
||||
csecho "$ORANGE" "Not connected to any VPNs"
|
||||
exit 0
|
||||
elif [[ $nup -eq 1 ]]; then
|
||||
ess=""
|
||||
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
|
||||
ess="s"
|
||||
fi
|
||||
csecho "$ORANGE" "Connected to ^b$nup^p VPN${ess}:"
|
||||
for x in ${!vstatus[@]}; do
|
||||
col="$GREEN"
|
||||
csecho "$BASECOL" " ${col}${BOLD}${vstatus[$x]}^p ${BASECOL}to ^b${vprofile[$x]}^p (${vvpntype[$x]}:${vuser[$x]}@${vserver[$x]})"
|
||||
done
|
||||
elif [[ $cmd == "off" ]]; then
|
||||
if [[ -n $PROFILE ]]; then
|
||||
# bring down just one vpn
|
||||
idxlist=$(get_profile_id "$PROFILE")
|
||||
else
|
||||
# bring down all vpns
|
||||
idxlist="${!profile[@]}"
|
||||
fi
|
||||
ntried=0
|
||||
for x in $idxlist; do
|
||||
vpnisup "${profile[$x]}"
|
||||
if [[ $? -eq 0 ]]; then
|
||||
rv=1
|
||||
get_vpn_status
|
||||
if [[ $vstatus == "Connected" ]]; then
|
||||
notify "Disconnecting from ${vvpntype} VPN ^b${vprofile}^p"
|
||||
ntried=$((ntried + 1))
|
||||
notify "Disconnecting from ^b${profile[$x]}^p VPN"
|
||||
errstring=""
|
||||
errdata=""
|
||||
|
||||
thepid=$(cat $VPNPIDFILE)
|
||||
thepid=$(cat ${pidfile[$x]})
|
||||
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}"
|
||||
rm -f "${pidfile[$x]}"
|
||||
rv=0
|
||||
else
|
||||
errstring="could not kill pid $thepid:"
|
||||
|
@ -388,12 +453,18 @@ elif [[ $cmd == "off" ]]; then
|
|||
error "$errstring"
|
||||
[[ -n $errdata ]] && cecho -s "$RED" "$errdata" | sed 's/^/ /'
|
||||
fi
|
||||
else
|
||||
fail
|
||||
elif [[ -n $PROFILE ]]; then
|
||||
error "The VPN ^b${PROFILE}^p is already disconnected"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
if [[ $ntried -eq 0 && -z $PROFILE ]]; then
|
||||
error "All VPNs are already disconnected"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
|
||||
|
|
Loading…
Reference in New Issue