Like many of you, many people use Cisco AnyConnect to get on Enterprise Networks.
In my case, I had two separate Cisco AnyConnect networks that I needed to be connected to in order to be connected to a Virtual Desktop/Server through either RDP/SSH on each network.
As a result, I started digging into the IP Stack and seeing about ways to leverage Docker to segment route mapping and allow something like this to work to my advantage.
Here’s a rough sketch of what’s done here:
- Step 1:
- My Local Computer -> Spin Up Docker Container -> Have Docker Container Connect to Remote Cisco AnyConnect Endpoint
- Step 2:
- My Local Computer -> Allocate a local port and forward it to a remote address INSIDE the Docker Container (Destination IP/DNS and Port)
- Step 3:
- My Local Computer -> Open RDP/SSH Session on localhost and allocated local port -> Connection to Remote Desktop/Server Succeeded!
Now, I had a few issues getting this up and going and the major one was making sure that the OpenConnect/AnyConnect Client wasn’t effectively blocking out ssh connections to allow this port forward allocation. However, I DID end up finding a way around this and made sure that the OpenConnect/AnyConnect Client wasn’t hijacking all requests to port 22 and instead was only hijacking/redirecting requests to the VPN. I accomplished this by using a nifty tool called VPN Splice.
You can check out this awesome utility written by Dan Lenski here:
https://github.com/dlenski/vpn-slice
All in all I ended up with this great combo of work and I am extremely proud of it. It has to be the most complex little tool I think I have ever written and it would NOT be possible without the people over at Docker.
All of the below information and files can be found ready to go on my Github repo here:
https://github.com/qwertycody/Docker-VPN-Tool
Here is the Source Code (Future Updates will be on the Above Repo):
Filename: build.sh
docker rmi garrett_tech:vpn_tool --force
docker build --rm=true -t garrett_tech:vpn_tool .
docker system prune --force
Filename: Dockerfile
FROM debian:latest
RUN apt-get update
RUN apt-get install -y openconnect
RUN apt-get install -y openssh-server
RUN apt-get install -y passwd
RUN apt-get install -y python3
RUN apt-get install -y python3-pip
RUN apt-get install -y dnsutils
RUN apt-get install -y iptables
RUN apt-get install -y iproute2
RUN apt-get install -y screen
RUN pip3 install https://github.com/dlenski/vpn-slice/archive/master.zip
RUN apt-get clean all
RUN mkdir /var/run/sshd
RUN echo "PasswordAuthentication yes" >> /etc/ssh/ssh_config
RUN echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
RUN echo 'echo "root:password" | chpasswd' >> /startup.sh
RUN echo "/usr/sbin/sshd -D &" >> /startup.sh
RUN echo "ping localhost" >> /startup.sh
EXPOSE 22
EXPOSE 3389
CMD sh /startup.sh
Filename: run_website.sh
OPENCONNECT_VPN_ENDPOINT="myCiscoVpnEndpoint.website.com"
DESTINATION_ADDRESS="myRemoteDesktopOrServerOrSshServer.website.com"
DESTINATION_PORT="3389"
LOCAL_DOCKER_ADDRESS="192.168.99.100"
LOCAL_DOCKER_SSH_PORT="2022"
LOCAL_LISTEN_PORT="2023"
CONTAINER_NAME="vpn_website"
IMAGE_NAME="garrett_tech:vpn_tool"
sh dockerVpnTool.sh $OPENCONNECT_VPN_ENDPOINT $DESTINATION_ADDRESS $DESTINATION_PORT $LOCAL_DOCKER_ADDRESS $LOCAL_DOCKER_SSH_PORT $LOCAL_LISTEN_PORT $CONTAINER_NAME $IMAGE_NAME
Filename: dockerVpnTool.sh
OPENCONNECT_VPN_ENDPOINT=$1
DESTINATION_ADDRESS=$2
DESTINATION_PORT=$3
LOCAL_DOCKER_ADDRESS=$4
LOCAL_DOCKER_SSH_PORT=$5
LOCAL_LISTEN_PORT=$6
CONTAINER_NAME=$7
IMAGE_NAME=$8
docker stop $CONTAINER_NAME
docker rm $CONTAINER_NAME
PORT_SSH="$LOCAL_DOCKER_SSH_PORT:22"
docker run -d --privileged --rm --name $CONTAINER_NAME -p $PORT_SSH $IMAGE_NAME
clear
echo "##################################################################"
echo "THE NEXT PROMPT WILL ASK YOU TO ENTER A FEW THINGS"
echo "ONCE YOU ARE FULLY CONNECTED TO THE VPN ENDPOINT"
echo "PRESS CTRL+A+D TO DETACH AND CONTINUE THE CONNECTION PROCESS"
echo "IF YOU UNDERSTAND THESE INSTRUCTIONS PRESS ENTER TO CONTINUE"
echo "##################################################################"
read
if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ] || [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
winpty docker exec -it $CONTAINER_NAME bash -c "screen openconnect $OPENCONNECT_VPN_ENDPOINT --script \"vpn-slice $DESTINATION_ADDRESS\""
else
docker exec -it $CONTAINER_NAME bash -c "screen openconnect $OPENCONNECT_VPN_ENDPOINT --script \"vpn-slice $DESTINATION_ADDRESS\""
fi
ssh-keygen -R [$LOCAL_DOCKER_ADDRESS]:$LOCAL_DOCKER_SSH_PORT
ssh -fNL $LOCAL_LISTEN_PORT:$DESTINATION_ADDRESS:$DESTINATION_PORT -l root $LOCAL_DOCKER_ADDRESS -p $LOCAL_DOCKER_SSH_PORT
echo "##################################################################"
echo "If there are no errors up to this point you can now connect"
echo "to the endpoint using localhost:$LOCAL_LISTEN_PORT using ssh/rdp"
echo "##################################################################"