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 "##################################################################"