Linux : Cisco SSL VPN
Background
Your network administrator provides you with some Cisco AnyConnect SSL VPN configuration that works great with WIndows and Mac OS but of course, nobody cares about Linux and you are a proud Linux Fedora 27 user - yeah! But how to access to company resources while on the go ? Read below
Configuring AnyConnect VPN on Fedora 27
It's been a while since I'm struggling with this. I can install Cisco AnyConnect but somehow it always failed at the CSD step (Cisco Secure Desktop). There are some required steps before allowing you to access the corporate network : is your antivirus up to date, do you have the latest OS patches installed, ...
As always, each problem got a solution. First, you need to install openconnect package
$ sudo dnf install NetworkManager-openconnect NetworkManager-openconnect-gnome
Once done, you need to create the CSD script that runs when connecting to the VPN peer. It will validate your host during the compliance test. Simply create a csd.sh file in your home directory with the below content. Do not forget to replace my_vpn_peer.my_domain.com by your real VPN server.
#!/bin/bash
# Cisco Anyconnect CSD wrapper for OpenConnect
# Enter your vpn host here
CSD_HOSTNAME=my_vpn_peer.my_domain.com
if [[ -z ${CSD_HOSTNAME} ]]
then
echo "Define CSD_HOSTNAME with vpn-host in script text. Exiting."
exit 1
fi
HOSTSCAN_DIR="$HOME/.cisco/hostscan"
LIB_DIR="$HOSTSCAN_DIR/lib"
BIN_DIR="$HOSTSCAN_DIR/bin"
BINS=("cscan" "cstub" "cnotify")
# parsing command line
shift
URL=
TICKET=
STUB=
GROUP=
CERTHASH=
LANGSELEN=
while [ "$1" ]; do
if [ "$1" == "-ticket" ]; then shift; TICKET=$1; fi
if [ "$1" == "-stub" ]; then shift; STUB=$1; fi
if [ "$1" == "-group" ]; then shift; GROUP=$1; fi
if [ "$1" == "-certhash" ]; then shift; CERTHASH=$1; fi
if [ "$1" == "-url" ]; then shift; URL=$1; fi
if [ "$1" == "-langselen" ];then shift; LANGSELEN=$1; fi
shift
done
ARCH=$(uname -m)
if [[ "$ARCH" == "x86_64" ]]
then
ARCH="linux_x64"
else
ARCH="linux_i386"
fi
# creating dirs
for dir in $HOSTSCAN_DIR $LIB_DIR $BIN_DIR ; do
if [[ ! -f $dir ]]
then
mkdir -p $dir
fi
done
# getting manifest, and checking binaries
wget --no-check-certificate -c "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/$ARCH/manifest" -O "$HOSTSCAN_DIR/manifest"
# generating md5.sum with full paths from manifest
export HOSTSCAN_DIR=$HOSTSCAN_DIR
cat $HOSTSCAN_DIR/manifest | sed -r 's/\(|\)//g' | awk '{ cmd = "find $HOSTSCAN_DIR -iname " $2; while (cmd | getline line) { print $4, line; } }' > $HOSTSCAN_DIR/md5.sum
# check number of files either
MD5_LINES=`wc --lines $HOSTSCAN_DIR/md5.sum | awk '{ print $1; }'`
MANIFEST_LINES=`wc --lines $HOSTSCAN_DIR/manifest | awk '{ print $1; }'`
echo "Got $MANIFEST_LINES files in manifes, locally found $MD5_LINES"
# check md5
md5sum -c $HOSTSCAN_DIR/md5.sum
if [[ "$?" -ne "0" || "$MD5_LINES" -ne "$MANIFEST_LINES" ]]
then
echo "Corrupted files, or whatever wrong with md5 sums, or missing some file"
# just download every file mentioned in manifest (not ideal, but hopefully should be enough)
FILES=( $(cat $HOSTSCAN_DIR/manifest | sed -r 's/\(|\)//g' | awk '{ print $2; }') )
WORK_DIR=`pwd`
TMP_DIR=`mktemp -d` && cd $TMP_DIR
for i in ${FILES[@]} ; do
FILE="$(basename "$i")"
echo "Downloading: $FILE to $TMP_DIR"
wget --no-check-certificate -c "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/$ARCH/$FILE" -O $FILE
# some files are in gz (don't understand logic here)
if [[ ! -f $FILE || ! -s $FILE ]]
then
# remove 0 size files
if [[ ! -s $FILE ]]; then
rm $FILE
fi
echo "Failure on $FILE, trying gz"
FILE_GZ=$FILE.gz
wget --no-check-certificate -c "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/$ARCH/$FILE_GZ" -O $FILE_GZ
gunzip --verbose --decompress $FILE_GZ
fi
# don't know why, but my version of hostscan requires tables to be stored in libs
echo $FILE | grep --extended-regexp --quiet --invert-match ".so|tables.dat"
IS_LIB=$?
if [[ "$IS_LIB" -eq "1" ]]
then
cp --verbose $FILE $LIB_DIR
else
cp --verbose $FILE $BIN_DIR
fi
done
for i in ${BINS[@]} ; do
echo "Setting excecution bit on: $BIN_DIR/$i"
chmod u+x $BIN_DIR/$i
done
cd $WORK_DIR
rm -rf $TMP_DIR
fi
# cstub doesn't care about logging options, sic!
#ARGS="-log debug -ticket $TICKET -stub $STUB -group $GROUP -host $URL -certhash $CERTHASH"
ARGS="-log error -ticket $TICKET -stub $STUB -group $GROUP -host $URL -certhash $CERTHASH"
echo "Launching: $BIN_DIR/cstub $ARGS"
$BIN_DIR/cstub $ARGS
# Cisco Anyconnect CSD wrapper for OpenConnect
# Enter your vpn host here
CSD_HOSTNAME=my_vpn_peer.my_domain.com
if [[ -z ${CSD_HOSTNAME} ]]
then
echo "Define CSD_HOSTNAME with vpn-host in script text. Exiting."
exit 1
fi
HOSTSCAN_DIR="$HOME/.cisco/hostscan"
LIB_DIR="$HOSTSCAN_DIR/lib"
BIN_DIR="$HOSTSCAN_DIR/bin"
BINS=("cscan" "cstub" "cnotify")
# parsing command line
shift
URL=
TICKET=
STUB=
GROUP=
CERTHASH=
LANGSELEN=
while [ "$1" ]; do
if [ "$1" == "-ticket" ]; then shift; TICKET=$1; fi
if [ "$1" == "-stub" ]; then shift; STUB=$1; fi
if [ "$1" == "-group" ]; then shift; GROUP=$1; fi
if [ "$1" == "-certhash" ]; then shift; CERTHASH=$1; fi
if [ "$1" == "-url" ]; then shift; URL=$1; fi
if [ "$1" == "-langselen" ];then shift; LANGSELEN=$1; fi
shift
done
ARCH=$(uname -m)
if [[ "$ARCH" == "x86_64" ]]
then
ARCH="linux_x64"
else
ARCH="linux_i386"
fi
# creating dirs
for dir in $HOSTSCAN_DIR $LIB_DIR $BIN_DIR ; do
if [[ ! -f $dir ]]
then
mkdir -p $dir
fi
done
# getting manifest, and checking binaries
wget --no-check-certificate -c "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/$ARCH/manifest" -O "$HOSTSCAN_DIR/manifest"
# generating md5.sum with full paths from manifest
export HOSTSCAN_DIR=$HOSTSCAN_DIR
cat $HOSTSCAN_DIR/manifest | sed -r 's/\(|\)//g' | awk '{ cmd = "find $HOSTSCAN_DIR -iname " $2; while (cmd | getline line) { print $4, line; } }' > $HOSTSCAN_DIR/md5.sum
# check number of files either
MD5_LINES=`wc --lines $HOSTSCAN_DIR/md5.sum | awk '{ print $1; }'`
MANIFEST_LINES=`wc --lines $HOSTSCAN_DIR/manifest | awk '{ print $1; }'`
echo "Got $MANIFEST_LINES files in manifes, locally found $MD5_LINES"
# check md5
md5sum -c $HOSTSCAN_DIR/md5.sum
if [[ "$?" -ne "0" || "$MD5_LINES" -ne "$MANIFEST_LINES" ]]
then
echo "Corrupted files, or whatever wrong with md5 sums, or missing some file"
# just download every file mentioned in manifest (not ideal, but hopefully should be enough)
FILES=( $(cat $HOSTSCAN_DIR/manifest | sed -r 's/\(|\)//g' | awk '{ print $2; }') )
WORK_DIR=`pwd`
TMP_DIR=`mktemp -d` && cd $TMP_DIR
for i in ${FILES[@]} ; do
FILE="$(basename "$i")"
echo "Downloading: $FILE to $TMP_DIR"
wget --no-check-certificate -c "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/$ARCH/$FILE" -O $FILE
# some files are in gz (don't understand logic here)
if [[ ! -f $FILE || ! -s $FILE ]]
then
# remove 0 size files
if [[ ! -s $FILE ]]; then
rm $FILE
fi
echo "Failure on $FILE, trying gz"
FILE_GZ=$FILE.gz
wget --no-check-certificate -c "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/$ARCH/$FILE_GZ" -O $FILE_GZ
gunzip --verbose --decompress $FILE_GZ
fi
# don't know why, but my version of hostscan requires tables to be stored in libs
echo $FILE | grep --extended-regexp --quiet --invert-match ".so|tables.dat"
IS_LIB=$?
if [[ "$IS_LIB" -eq "1" ]]
then
cp --verbose $FILE $LIB_DIR
else
cp --verbose $FILE $BIN_DIR
fi
done
for i in ${BINS[@]} ; do
echo "Setting excecution bit on: $BIN_DIR/$i"
chmod u+x $BIN_DIR/$i
done
cd $WORK_DIR
rm -rf $TMP_DIR
fi
# cstub doesn't care about logging options, sic!
#ARGS="-log debug -ticket $TICKET -stub $STUB -group $GROUP -host $URL -certhash $CERTHASH"
ARGS="-log error -ticket $TICKET -stub $STUB -group $GROUP -host $URL -certhash $CERTHASH"
echo "Launching: $BIN_DIR/cstub $ARGS"
$BIN_DIR/cstub $ARGS
Make the file excecutable
$ chmod +x csd.sh
$ sudo openconnect --csd-wrapper=csd.sh --user= --authgroup=""
You will be prompted to enter your password, then you are connected. Do not close this terminal session otherwise you will be disconnected.
It is creating a new tun0 interface with your VPN client IP assigned to it.
$ ifconfig tun0
tun0: flags=4305 mtu 1406
tun0: flags=4305
inet 192.168.3.8 netmask 255.255.255.255 destination 192.168.3.8
inet6 fe80::f19e:dd67:3854:edc7 prefixlen 64 scopeid 0x20
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC)
RX packets 8905 bytes 11943194 (11.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6716 bytes 435375 (425.1 KiB)
TX errors 0 dropped 195 overruns 0 carrier 0 collisions 0
To disconnect from the VPN session, just hit Ctrl+C in the terminal where you have started openconnect.
Note : root (sudo) privileges are required to modify the system network configuration.
Now, there is a UI equivalent in the system, but I did not managed to make it working. If you have any clue ;)
It really took me nights to figure out why my Cisco AnyConnect doesn't want to work on my environment until I decided to search for alternatives!
Hi,
ReplyDeleteCan you please share a important technic about server security(linux hardening).
Thanks & your blog is very useful for linux free vpn lovers.Keep it up :)
Well research and informative too. I, used FastestVPN for secure and easy to configure. But FastestVPN offers Best VPN for Linux with an easy setup that lets you experience the internet with freedom, anonymity, security and privacy!
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeletethanks for sharing informative information.
ReplyDelete