解决Linux下连接Cisco VPN后局域网不能访问

在Linux下使用Cisco Anyconnect客户端连接VPN后,局域网无法访问,无论如何设置路由,路由表始终无法改变
网上搜了一下,原因是Anyconnect客户端监听路由表,一旦改变,通过一个回调再改回去

解决办法:Anyconnect监听路由表的回调代码位于一个so共享库,可以通过LD_PRELOAD阻止Anyconnect加载原来的监听回调

创建hack.c

#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);
        }
     }
     fd--;
  }
  return 0;
}
$ gcc -o libhack.so -shared -fPIC hack.c
$ sudo cp libhack.so  /opt/cisco/anyconnect/lib/

修改/etc/init.d/vpnagentd,启动vpnagentd的地方前面添加LD_PRELOAD=/opt/cisco/anyconnect/lib/libhack.so

LD_PRELOAD=/opt/cisco/anyconnect/lib/libhack.so /opt/cisco/anyconnect/bin/vpnagentd

重新启动vpnagentd

$ sudo /etc/init.d/vpnagentd start

最后修改一下iptables

$ sudo iptables-save | grep -v DROP | iptables-restore

再修改路由表就可以生效了

$ sudo route add -net 192.168.1.0 netmask 255.255.255.0 dev eth0
$ sudo route -n

以上方法对于version 3.1.00495, 3.1.05152, 3.1.05170的Anyconnect客户端有效

如果前面说的方法无效,可以试试用gdb调试,找出回调函数的名字

gdb -p $(pidof vpnagentd)
b socket
c
bt

参考:How to allow local LAN access while connected to Cisco VPN?
PDF:How to allow local LAN access while connected to Cisco VPN