连接到Cisco VPN时如何允许本地LAN访问?


82

连接到Cisco VPN时如何维护本地LAN访问?

使用Cisco VPN连接时,服务器必须能够指示客户端阻止本地LAN访问。

假设无法关闭此服务器端选项,与Cisco VPN客户端连接时如何允许本地LAN访问?


我曾经认为这仅仅是添加路由以捕获更高度量标准的LAN流量的问题,例如:

  Network 
Destination      Netmask        Gateway       Interface  Metric
   10.0.0.0  255.255.0.0       10.0.0.3        10.0.0.3      20  <--Local LAN
   10.0.0.0  255.255.0.0  192.168.199.1  192.168.199.12       1  <--VPN Link

尝试删除10.0.x.x -> 192.168.199.12路线没有任何效果:

>route delete 10.0.0.0
>route delete 10.0.0.0 mask 255.255.0.0
>route delete 10.0.0.0 mask 255.255.0.0 192.168.199.1
>route delete 10.0.0.0 mask 255.255.0.0 192.168.199.1 if 192.168.199.12
>route delete 10.0.0.0 mask 255.255.0.0 192.168.199.1 if 0x3

尽管它仍然可能只是路由问题,但尝试添加或删除路由失败。

Cisco VPN客户端驱动程序在什么级别上执行网络堆栈中需要做什么才能覆盖本地管理员管理其计算机的能力?

Cisco VPN客户端不能使用魔术。它仍然是我计算机上运行的软件。它使用什么机制来干扰机器的网络?当IP / ICMP数据包到达网络时会发生什么?数据包在网络堆栈中的哪个位置被吞噬?

也可以看看


编辑:我尚未尝试的事情:

>route delete 10.0.*

更新:由于Cisco放弃了其旧客户端,转而使用AnyConnect(基于HTTP SSL的VPN),因此这个未解决的问题可以作为历史遗物。

展望未来,我们可以尝试与他们的新客户解决相同的问题


1
VPN链接的指标较低,因此请先尝试使用您的本地路由。增加本地LAN的度量标准很可能会禁用本地LAN。如果未将VPN配置为通过隧道传输所有流量,则您的家庭子网可能是解决方案。您需要通过此VPN访问哪些IP?这是VPN端上的整个10.0.0.0吗?
pberlijn 2011年

听起来很可能是问题所在。我认为更高的指标=更好
伊恩·博伊德


2
的思科Anyconnect可以在描述OpenConnect替代大多兼容的客户端来代替serverfault.com/a/664097/104573
Vadzim

Answers:


53

Anyconnect的问题在于,它首先修改了路由表,然后对其进行了修改并进行了修复(如果您手动对其进行了修改)。我找到了解决方法。适用于版本3.1.00495、3.1.05152、3.1.05170以及3.1系列中的其他任何版本。可能与其他版本一起使用,但前提是类似的想法应该在代码未重写的情况下起作用。对我们来说幸运的是,思科已将保姆“婴儿醒了”的呼叫放入了一个共享库中。因此,我们的想法是我们通过LD_PRELOAD阻止vpnagentd采取措施。

  1. 首先我们创建一个文件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;
    }
    
  2. 然后像这样编译它:

    gcc -o libhack.so -shared -fPIC hack.c
    
  3. 安装libhack.so到思科库路径:

    sudo cp libhack.so  /opt/cisco/anyconnect/lib/
    
  4. 调低代理商:

    /etc/init.d/vpnagentd stop
    
  5. 确保它真的坏了

    ps auxw | grep vpnagentd
    

    如果没有,请kill -9确保。

  6. 然后通过添加LD_PRELOAD=/opt/cisco/anyconnect/lib/libhack.so 在何处调用vpnagentd来修复/etc/init.d/vpnagentd,因此它看起来像这样:

    LD_PRELOAD=/opt/cisco/anyconnect/lib/libhack.so /opt/cisco/anyconnect/bin/vpnagentd
    
  7. 现在启动代理:

    /etc/init.d/vpnagentd start
    
  8. 修复iptables,因为AnyConnect将它们弄乱了:

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

    您可能需要在此处做一些更高级的操作,以仅允许访问某些LAN主机。

  9. 现在,请根据需要修复路线,例如:

    route add -net 192.168.1.0 netmask 255.255.255.0 dev wlan0
    
  10. 检查它们是否真的存在:

    route -n
    

此hack的以前的更简单版本提供了仅执行“ return 0”的功能。-该海报指出:“到目前为止,我观察到的唯一副作用是,vpnagentd使用的是top所报告的100%的CPU,但是总体CPU仅为3%的用户和20%的系统,并且该系统具有完美的响应能力我对它进行了拉直处理,当从两者快速返​​回时,似乎都在循环中执行两个选择,但它从未读取或写入-我以为我用LD_PRELOAD剪切出的调用应该被读取。这样做,但是到目前为止对我来说已经足够了。如果有人有更好的解决方案,请分享。”

小问题的问题在于,它会导致单个cpu核心一直保持100%的状态,从而有效地将您的硬件cpu线程数减少了一个,无论您的vpn连接是否处于活动状态。我注意到代码正在执行的选择位于netlink套接字上,该套接字在路由表更改时发送vpnagentd数据。vpnagentd不断注意到netlink套接字上有一条新消息,并调用routeCallBackHandler来处理它,但是由于琐碎的黑客无法清除新消息,因此它只会不断地被反复调用。上面提供的新代码将刷新netlink数据,因此不会发生导致100%cpu的无限循环。

如果某些方法不起作用,请gdb -p $(pidof vpnagentd)在附加后执行:

b socket
c
bt

并查看您所在的呼叫。然后只需猜测要剪切的那个呼叫,然后将其添加到hack.c并重新编译即可。


4
这是天才。我正在尝试使其在OSX上运行,并有一个问题:您怎么知道要覆盖的方法是命名的_ZN27CInterfaceRouteMonitorLinux20routeCallbackHandlerEv
donturner 2014年

2
@donturner尝试nm /opt/cisco/anyconnect/lib/libvpnagentutilities.dylib | grep routeCallbackHandlerEv,然后您会发现__ZN25CInterfaceRouteMonitorMac20routeCallbackHandlerEv
麦凯文2015年

我通过使用gdb附加到vpnagentd并设置各种断点来解决了这一问题。
Sasha Pachev

@McKelvin 在Ubuntu下在我的AnyConnect上nm /opt/cisco/anyconnect/lib/libvpnagentutilities.so返回 nm: /opt/cisco/anyconnect/lib/libvpnagentutilities.so: no symbols,因此生成时没有符号表信息。你怎么能得到那个?
nephewtom

@SashaPachev如何调试没有符号信息的vpnagentd?
nephewtom

11

这非常麻烦,但是如果您使用VMWare Player或类似软件创建最小的VM,并在其中运行Cisco AnyConnect VPN客户端,则可以使用VMWare虚拟网络适配器根据需要设置路由,或者直接使用虚拟机,用于通过Cisco SSL VPN访问所需的任何资源,并将文件“拖放”到实际计算机中或从您的实际计算机中“拖放”。


7

正如伊恩·博伊德Ian Boyd)所建议的那样,Shrew Soft VPN软件也帮了我大忙

它可以导入Cisco VPN客户端配置文件。我使用了Cisco VPN Client版本5.0.05.0290,并且在安装Shrew VPN(版本2.1.7)并导入Cisco配置文件后,能够在连接到公司VPN的同时访问本地LAN,而无需任何其他Shrew VPN连接配置(或软件)。


如果这适用于android,那将是惊人的。
加百利博览会

1
我来自2019年,它有效!!!!!!!
Sergey Povisenko

5

感谢Sasha Pachev的出色表现

vpnagentd通过覆盖对所做的更改,也使解析器混乱/etc/resolv.conf。我最终赢得了与之对抗的比赛,从而解决了这一问题:

#!/bin/bash

dnsfix() {
    [ -f /etc/resolv.conf.vpnbackup ] || echo "Not connected?" >&2 || return 0 # do nothing in case of failure
    while ! diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup #>/dev/null
    do
         cat /etc/resolv.conf.vpnbackup >/etc/resolv.conf
    done
    chattr +i /etc/resolv.conf
    diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null 
}

while ! dnsfix
do
    echo "Retrying..."
    chattr -i /etc/resolv.conf
done

chattr -i /etc/resolv.conf断开连接时不要忘记。

我试图通过拦截回调来解决它,就像上面的routes方法一样,但是还找不到对应的回调或方法。

Update1 / 2:A strace透露vpnagentd正在使用inotifyAPI监视解析程序文件的更改。从那里开始是下坡路。这是其他技巧:

int _ZN18CFileSystemWatcher11AddNewWatchESsj(void *string, unsigned int integer)
{
  return 0;
}

当然,这有点矫kill过正,因为它禁用了代理的所有文件监视功能。但似乎工作正常。

下面的vpn客户端包装脚本集成了所有功能(已更新为包括此额外的技巧)。chattr不再使用/需要。

更新3:修复了脚本中的用户名/密码设置。现在,它使用vpn.conf以下所述格式的文件(和仅root用户权限)。

#!/bin/bash

# Change this as needed
CONF="/etc/vpnc/vpn.conf"
# vpn.conf format
#gateway <IP>
#username <username>
#password <password>
#delete_routes <"route spec"...> eg. "default gw 0.0.0.0 dev cscotun0"
#add_routes <"route spec"...> eg. "-net 192.168.10.0 netmask 255.255.255.0 dev cscotun0" "-host 10.10.10.1 dev cscotun0"

ANYCONNECT="/opt/cisco/anyconnect"

usage() {
    echo "Usage: $0 {connect|disconnect|state|stats|hack}"
    exit 1
}

CMD="$1"
[ -z "$CMD" ] && usage

ID=`id -u`

VPNC="$ANYCONNECT/bin/vpn"

dnsfix() {
    [ -f /etc/resolv.conf.vpnbackup ] || echo "Not connected?" >&2 || return 0 # do nothing in case of failure
    while ! diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null
    do
         cat /etc/resolv.conf.vpnbackup >/etc/resolv.conf
    done
#    chattr +i /etc/resolv.conf
    diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null 
}

case "$CMD" in
    "connect")
        [ $ID -ne 0 ] && echo "Needs root." && exit 1
        HOST=`grep ^gateway $CONF | awk '{print $2}'`
        USER=`grep ^user $CONF | awk '{print $2}'`
        PASS=`grep ^password $CONF | awk '{print $2}'`
        OLDIFS=$IFS
        IFS='"'
        DEL_ROUTES=(`sed -n '/^delete_routes/{s/delete_routes[ \t\"]*//;s/\"[ \t]*\"/\"/g;p}' $CONF`)
        ADD_ROUTES=(`sed -n '/^add_routes/{s/add_routes[ \t\"]*//;s/\"[ \t]*\"/\"/g;p}' $CONF`)
        IFS=$OLDIFS

        /usr/bin/expect <<EOF
set vpn_client "$VPNC";
set ip "$HOST";
set user "$USER";
set pass "$PASS";
set timeout 5
spawn \$vpn_client connect \$ip
match_max 100000
expect { 
    timeout {
        puts "timeout error\n"
        spawn killall \$vpn_client
        exit 1
    }
    ">> The VPN client is not connected." { exit 0};
    ">> state: Disconnecting" { exit 0};
    "Connect Anyway?"
}
sleep .1
send -- "y\r"
expect { 
    timeout {
        puts "timeout error\n"
        spawn killall \$vpn_client
        exit 1
    }
    "Username:"
}
sleep .1
send -- "\$user\r"
expect { 
    timeout {
        puts "timeout error\n"
        spawn killall \$vpn_client
        exit 1
    }
    "Password: "
}
send -- "\$pass\r";
expect eof
EOF
        sleep 2
        # iptables
        iptables-save | grep -v DROP | iptables-restore

        # routes
        for ROUTE in "${DEL_ROUTES[@]}"
        do
#            echo route del $ROUTE
            route del $ROUTE
        done
        for ROUTE in "${ADD_ROUTES[@]}"
        do
#            echo route add $ROUTE
            route add $ROUTE
        done

        # dns
        while ! dnsfix
        do
            echo "Try again..."
#            chattr -i /etc/resolv.conf
        done

        echo "done."
        ;;
    "disconnect")
#        [ $ID -ne 0 ] && echo "Needs root." && exit 1
        # dns
#        chattr -i /etc/resolv.conf

        $VPNC disconnect
        ;;
    "state"|"stats")
        $VPNC $CMD
        ;;
    "hack")
        [ $ID -ne 0 ] && echo "Needs root." && exit 1
        /etc/init.d/vpnagentd stop
        sleep 1
        killall -9 vpnagentd 2>/dev/null
        cat - >/tmp/hack.c <<EOF
#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;
}

int _ZN18CFileSystemWatcher11AddNewWatchESsj(void *string, unsigned int integer)
{
  return 0;
}
EOF
        gcc -o /tmp/libhack.so -shared -fPIC /tmp/hack.c
        mv /tmp/libhack.so $ANYCONNECT
        sed -i "s+^\([ \t]*\)$ANYCONNECT/bin/vpnagentd+\1LD_PRELOAD=$ANYCONNECT/lib/libhack.so $ANYCONNECT/bin/vpnagentd+" /etc/init.d/vpnagentd
        rm -f /tmp/hack.c
        /etc/init.d/vpnagentd start
        echo "done."
        ;;
    *)
        usage
        ;;
esac

1
您的通知黑客解决了我的AnyConnect 3.1.14018安装问题,从而解决了我新发现的(2017-02-25)问题,因此在我打开新的终端窗口或GNU屏幕时,它将断开连接。由于某种原因,它正在监视/ var / run / utmp。好,不再了,谢谢!
Martin Dorey

真好 有时“过度杀伤”可能是您的朋友。:-)
Mauro Lacy

4

我的公司仍然使用该VPN。vpnc客户端仅通过以下方式更改iptables设置:

#iptables-保存
#由iptables-save v1.4.10于2012年6月17日14:12:20生成
*过滤
:INPUT DROP [0:0]
:正接受[0:0]
:输出下降[0:0]
-A输入-s 123.244.255.254/32 -d 192.168.0.14/32 -j接受 
-A输入-i tun0 -j接受 
-A输入-i lo0 -j接受
-A输入-j下降 
-A输出-s 192.168.0.14/32 -d 123.244.255.254/32 -j接受 
-A输出-o tun0 -j接受 
-A输出-o lo0 -j接受 
-A输出-j DROP 
承诺

它过滤除VPN流量以外的所有流量。

只需使用iptables-save将过滤器放入文件中,添加符合您需求的INPUT和OUTPOUT访问线,然后使用iptables-restore重新应用该文件。

例如访问192.168.0上的本地网络

#由iptables-save v1.4.10于2012年6月17日14:12:20生成
*过滤
:INPUT DROP [0:0]
:正接受[0:0]
:输出下降[0:0]
-A输入-s 123.244.255.254/32 -d 192.168.0.14/32 -j接受 
-A输入-s 192.168.0.0/24 -d 192.168.0.14/32 -j接受#本地输入
-A输入-i tun0 -j接受 
-A输入-i lo0 -j接受 
-A输入-j下降 
-A输出-s 192.168.0.14/32 -d 123.244.255.254/32 -j接受 
-A输出-s 192.168.0.14/32 -d 192.168.0.0/24 -j ACCEPT#本地输出
-A输出-o tun0 -j接受 
-A输出-o lo0 -j接受 
-A输出-j DROP 
承诺

2
它错了,它不是那么容易只需添加你的路线。我试着和它没有工作.. VPN客户端以内核路由表的控制,是不是让你修改
萨蒂什

3

有什么消息吗?

Cisco VPN客户端驱动程序在什么级别上执行网络堆栈中需要做什么才能覆盖本地管理员管理其计算机的能力?

我完全同意,并想知道同一件事。

无论如何,这是一个需要管理员权限才能安装的应用程序,它在运行时可能会很好地过滤您的工作...

我在Windows上的尝试也失败了:

route change 0.0.0.0 mask 0.0.0.0 192.168.1.1 metric 1
 OK!

IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0      192.168.1.1    192.168.1.230     21 <-- LAN
          0.0.0.0          0.0.0.0    192.168.120.1    192.168.120.3      2 <-- VPN

哈哈。似乎没有20以下的指标。


就linux而言,这(petefreitag.com/item/753.cfm)似乎也表明防火墙也参与其中。
Marki

2
我找到了ShrewSoft VPN。它可以连接到Cisco IPSec VPN服务器,并且忽略了VPN服务器管理员要求我与自己的网络断开连接的要求。(有关详细说明,请参见superuser.com/questions/312947/…)即使它不能回答这个问题,也可以解决。注意:ShrewSoft VPN仅适用于IPSec。它不适用于SSL VPN(即较新的Cisco AnyConnect VPN客户端)
Ian Boyd

3

我不知道我是否理解正确,但首先请澄清一下我的理解:

您有一个本地LAN(例如10.0.0.0/16)和一个远程Cisco VPN Server(例如64.0.0.0/16),您想通过Cisco VPN客户端连接到VPN服务器,但是您需要才能进行局域网访问。在这种情况下,您要将整个10.0.xx / 16与VPN连接分开)。在Mac客户端中必须添加以下路由:

/sbin/route add -net 10.0 -interface en1

其中en1是用于连接到LAN的接口。我知道您也可以在Windows和Linux中添加相同的内容。


3
Mac客户端+1;这不适用于我。尽管此命令可能有效,但Cisco客户端可能在创建后不久将其删除(Cisco客户端似乎阻止任何人更改路由)
Ian Boyd 2013年

2

由于我无法添加评论,因此我将在此处发布。我在Windows上运行。

如果您“挚爱”的IT部门通过VPN路由0.0.0.0,从而连本地网络(包括该网络)也无法使用虚拟机并在VM内运行AnyConnect,然后将VM用作工作环境与公司网络之间的中介的解决方案不起作用在本地PC和VM之间)是通过VPN路由的。

我尝试应用@Sasha Pachev发布的解决方案,但最终我修补了.dll,以使该函数的开头返回0。最终,在与动态库进行斗争之后,我能够根据自己的需求修改路由表,但是显然这还不够!

即使我的规则似乎对实现分割隧道是正确的,但我仍然会遇到常规故障。 您是否遇到了能够解决的类似问题?

  • 我的互联网网关是192.168.163.2
  • 我公司的网络网关为10.64.202.1(因此整个10 *子网我当作“北美经销商的”)

这是我的路由表现在的样子(在启用VPN的情况下进行手动修改之后)

在此处输入图片说明

但是ping的结果如下

C:\Users\Mike>ping -n 1 10.64.10.11
Reply from 10.64.10.11: bytes=32 time=162ms TTL=127

C:\Users\Mike>ping -n 1 8.8.8.8
PING: transmit failed. General failure.

C:\Users\Mike>ping -n 1 192.168.163.2
General failure.

仅供参考,以下是VPN断开连接(未更改)时路由表的外观

在此处输入图片说明

这就是当我尝试ping时连接(未更改)VPN时的表格的样子,8.8.8.8我只是超时(因为公司的防火墙不允许流量传到Intranet之外)

在此处输入图片说明


我在修补DLL时遇到困难,有人可以提供其副本还是概述更多我需要更改的偏移量的细节?
肖恩·

1

对于那些希望在使用Cisco AnyConnect SSL VPN时保持对其路由表的控制的用户,请查看OpenConnect。它既支持Cisco AnyConnect SSL VPN,也不会尝试中断或“保护”路由表条目。@Vadzim上面评论中暗示了这一点。

在尝试对AnyConnect Secure Mobility Client进行补丁之后,我能够在Windows上使用OpenConnect GUI成功替换它。这使我能够保持与本地资源的连接(并更新路由表)。

我在Windows上使用OpenConnect,但根据项目页面,它还支持Linux,BSD和macOS(以及其他平台)。


1
这对我有用。但是我的组织使用令牌,因此每次密码都不相同。因此,我不得不打开“批处理模式”,否则它将保存第一个密码并重复使用。
加布里埃尔·卢西

0

尝试使用网关删除那些条目,10.64.202.13看看ping是否8.8.8.8有效,然后将它们一一添加回去,并找出引起问题的原因。

您是如何修补DLL的。我什至无法修改路由表,因为它会不断添加0.0.0.0VPN网关。


1
如果您需要对问题的澄清或其他信息,请发表评论,而不是将其包含在答案中。谢谢。
马修·威廉姆斯

不允许我对现有问题添加评论。
托尼
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.