VPN in a Box

vpn in box

Why run the VPN client in a VM?

The Cisco AnyConnect VPN client will not allow you to ssh into your VM and set up your VPN in case the server side profile is configured with:


There are ways to hack this, but I have come to settle on running VPN in an VM with X:

VM with a lightweight distro and desktop environment

I run a VM with Debian. It runs X and has a light DM, like Fluxbox, so that it doesn't consume too many resources.


In the VM, I've installed Cisco AnyConnect VPN.

HTTP proxy

In the VM, I've installed tinyproxy. It's started by default, so you just need to note down the port number and use that when launching your browsers:

$ grep ^Port /etc/tinyproxy/tinyproxy.conf
Port 8000

Giving the VM a name

Naming is hard, I've called it proxy. Since I run it in KVM managed by virsh, I query it for its IP like so:

$ virsh net-dhcp-leases default | grep proxy | awk '{print $5}'

And add it to my /etc/hosts:

# tee proxy /etc/hosts

Now, whenever I say proxy, my machine routes the request to the VM.

SSH through the VPN

When I need to ssh into a machine that requires me to be on the VPN, I use:

$ ssh -J proxy bugs.internal

Web browser through the VPN

When I need to browse a web site that requires me to be on the VPN, I start it with an extra option specifying the HTTP proxy:

$ google-chrome-stable --proxy-server=proxy:8000 https://accounting.internal &

When I need to use curl over the VPN, I pass the -x parameter:

$ curl -x proxy:8000 https://accounting.internal

Maven through the VPN

In my .zshrc (.bashrc work just the same), I have the following that adds proxy settings to the MAVEN_OPTS variable depending on an internal website is available:

curl --max-time 1 --fail -s -x proxy:8899 -I https://bugs.internal/ && {

Anything through the VPN

Most command line programs support the environment variables:


I have the following in my .zshrc to set these variables dynamically:

curl --max-time 1 --fail -s -x proxy:8899 -I https://bugs.internal/ && {
  export no_proxy=localhost
  export NO_PROXY=${no_proxy}
  export http_proxy='http://proxy:8000
  export https_proxy=${http_proxy}
  export HTTP_PROXY=${http_proxy}
  export HTTPS_PROXY=${http_proxy}


That's it. All other requests, I use regular browser sessions that don't route through the VPN. Which is most of what I need: Teams, Slack, Outlook, Git++

Happy networking!

Licensed under CC BY Creative Commons License ~ ✉ torstein.k.johansen @ gmail ~ 🐘 @skybert@emacs.ch ~ 🐦 @torsteinkrause