Control Cisco AnyConnect VPN Routes

By default Cisco AnyConnect VPN routes just about every thinkable IP through the VPN. This is probably not what you want. Preferably, you'd want only the company servers routed through the VPN and the rest of your network traffic should go through the default gateway. What's more, routing all subnets through the VPN makes lots of services fail, for instance did my Docker and LXD containers stop working once I connected to AnyConnect.

This snippet is written by Sasha Pachev and posted on

#include <sys/socket.h>
#include <linux/netlink.h>

int _ZN27CInterfaceRouteMonitorLinux20routeCallbackHandlerEv()
  int fd=50;          // max fd to try
  char buf[8192];
  struct sockaddr_nl sa;
  socklen_t len = sizeof(sa);

  while (fd) {
     if (!getsockname(fd, (struct sockaddr *)&sa, &len)) {
        if (sa.nl_family == AF_NETLINK) {
           ssize_t n = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
  return 0;

With this patched/side loaded vpnagentd function, I can now use AnyConnect and LXD containers, basically, I removed one and one AnyConnect route until my LXD container started working, this snippet may come in handy for others attempting the same:

/sbin/route -n | grep cscotun0 | awk '{print "sudo route del -net "$1 " gw "$2" netmask "$3}'; 

Linux users may use the same approach to tame AnyConnect, see for how to create the shared library. You then need to add LD_PRELOAD to the systemd unit (the article talks about the AC init.d which doesn't exist anymore):

$ cat /lib/systemd/system/vpnagentd.service
Description=Cisco AnyConnect Secure Mobility Client Agent 

ExecStart=/opt/cisco/anyconnect/bin/vpnagentd -execv_instance
ExecReload=/bin/kill -HUP $MAINPID 


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