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

Ian*_*oyd 102 cisco-vpn-client

如何在连接到 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
Run Code Online (Sandbox Code Playgroud)

并尝试删除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
Run Code Online (Sandbox Code Playgroud)

虽然它仍然可能只是一个路由问题,但尝试添加或删除路由会失败。

Cisco VPN 客户端驱动程序在网络堆栈中的哪个级别执行覆盖本地管理员管理其机器的能力的操作?

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

也可以看看


编辑:我还没有尝试过的事情:

>route delete 10.0.*
Run Code Online (Sandbox Code Playgroud)

更新:由于思科已经放弃了他们的旧客户端,转而使用 AnyConnect(基于 HTTP SSL 的 VPN),这个未解决的问题可以成为历史的遗物。

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

小智 61

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;
    }
    
    Run Code Online (Sandbox Code Playgroud)

注意:此代码仅适用于 Linux。要将此解决方案应用于 macOS 机器,请参阅macOS 适配版本

  1. 然后像这样编译它:

    gcc -o libhack.so -shared -fPIC hack.c
    
    Run Code Online (Sandbox Code Playgroud)
  2. 安装libhack.so到 Cisco 库路径:

    sudo cp libhack.so  /opt/cisco/anyconnect/lib/
    
    Run Code Online (Sandbox Code Playgroud)
  3. 取消代理:

    /etc/init.d/vpnagentd stop
    
    Run Code Online (Sandbox Code Playgroud)
  4. 确保它真的关闭了

    ps auxw | grep vpnagentd
    
    Run Code Online (Sandbox Code Playgroud)

    如果没有,kill -9只是为了确定。

  5. 如果有/etc/init.d/vpnagentd,则通过添加LD_PRELOAD=/opt/cisco/anyconnect/lib/libhack.so 调用底层可执行文件的位置来修复它,如下所示:

    LD_PRELOAD=/opt/cisco/anyconnect/lib/libhack.so /opt/cisco/anyconnect/bin/vpnagentd
    
    Run Code Online (Sandbox Code Playgroud)

    更现代的 AnyConnect 安装避免/etc/init.d/vpnagentd使用/lib/systemd/system/vpnagentd.service,在这种情况下,您将需要以下内容:

    sudo mv /opt/cisco/anyconnect/bin/vpnagentd /opt/cisco/anyconnect/bin/vpnagentd.orig &&
    { echo '#!/bin/bash' &&
      echo "LD_PRELOAD=$HOME/vpn/libhack.so exec /opt/cisco/anyconnect/bin/vpnagentd.orig"
    } | sudo tee /opt/cisco/anyconnect/bin/vpnagentd &&
    sudo chmod +x /opt/cisco/anyconnect/bin/vpnagentd
    
    Run Code Online (Sandbox Code Playgroud)
  6. 现在启动代理:

    /etc/init.d/vpnagentd start
    
    Run Code Online (Sandbox Code Playgroud)
  7. 修复 iptables,因为 AnyConnect 弄乱了它们:

    iptables-save | grep -v DROP | iptables-restore
    
    Run Code Online (Sandbox Code Playgroud)

    您可能想要在这里做一些更高级的事情,以只允许访问某些 LAN 主机。

  8. 现在根据需要修改路线,例如:

    route add -net 192.168.1.0 netmask 255.255.255.0 dev wlan0
    
    Run Code Online (Sandbox Code Playgroud)
  9. 检查它们是否真的存在:

    路由 -n

这个 hack 之前的一个更简单的版本给出了一个只执行“返回 0;”的函数。- 该海报指出“到目前为止,我观察到的唯一副作用是 vpnagentd 使用了 top 报告的 100% 的 CPU,但总体 CPU 只有 3% 的用户和 20% 的系统,并且系统响应完美. 我跟踪它,当空闲从两个快速返回时,它似乎在循环中进行两次选择,但它从不读取或写入 - 我想我用 LD_PRELOAD 切断的调用应该读取。可能有一种更清洁的方法这样做,但到目前为止对我来说已经足够了。如果有人有更好的解决方案,请分享。”

微不足道的问题在于它导致单个 cpu 内核始终为 100%,有效地将您的硬件 cpu 线程数减少了一个 - 无论您的 vpn 连接是否处于活动状态。我注意到代码所做的选择是在 netlink 套接字上进行的,它在路由表更改时发送 vpnagentd 数据。vpnagentd 不断注意到 netlink 套接字上有一条新消息,并调用 routeCallBackHandler 来处理它,但由于琐碎的 hack 没有清除新消息,它只会一次又一次地被调用。上面提供的新代码刷新了 netlink 数据,因此不会发生导致 100% cpu 的无限循环。

如果某些东西不起作用,请执行gdb -p $(pidof vpnagentd),一旦附加:

b socket
c
bt
Run Code Online (Sandbox Code Playgroud)

看看你在哪个调用中。然后猜猜你想删掉哪个,把它添加到 hack.c 并重新编译。

  • 这是天才。我试图让它在 OSX 上运行,但有一个问题:你怎么知道要覆盖的方法被命名为“_ZN27CInterfaceRouteMonitorLinux20routeCallbackHandlerEv”? (5认同)
  • @donturner 尝试`nm /opt/cisco/anyconnect/lib/libvpnagentutilities.dylib | grep routeCallbackHandlerEv` 然后你会发现`__ZN25CInterfaceRouteMonitorMac20routeCallbackHandlerEv` (2认同)

Law*_*ceC 13

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


小智 9

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

在尝试了除了修补 AnyConnect 安全移动客户端之外的所有内容后,我能够在 Windows 上成功地将其替换为OpenConnect GUI。这使我能够保持与本地资源的连接(并更新路由表)。

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

  • 太感谢了!在我找到一个运行 AnyConnect 的系统之前,我确实浏览了 4 个(!!!)系统,结果发现删除本地访问非常痛苦。Windows 用户请注意:从 https://github.com/openconnect/openconnect-gui/releases 获取它。只需在 URL 前面加上 https:// 即可,对我来说,只需 0 个额外配置即可(Cisco Asa)。以及本地局域网访问。 (2认同)

小智 8

正如Ian Boyd建议的那样,Shrew Soft VPN 软件也为我解决了问题。

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

  • 我来自 2019 年,它有效!!!!!! (3认同)

小智 6

感谢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
Run Code Online (Sandbox Code Playgroud)

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

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

更新 1/2:一个strace透露vpnagentd正在使用inotifyAPI 来监视解析器文件更改。从那以后就走下坡路了。这是额外的黑客:

int _ZN18CFileSystemWatcher11AddNewWatchESsj(void *string, unsigned int integer)
{
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

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

下面的 vpn 客户端包装器脚本集成了所有功能(已更新以包含此额外的 hack)。 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
Run Code Online (Sandbox Code Playgroud)


Mar*_*rki 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
Run Code Online (Sandbox Code Playgroud)

哈哈。这里似乎没有低于 20 的指标。

  • 我找到了 ShrewSoft VPN。它可以连接到 Cisco IPSec VPN 服务器,并且忽略 VPN 服务器管理员要求我与自己的网络断开连接的要求。(有关详细说明,请参阅http://superuser.com/questions/312947/how-to-configure-shrewsoft-vpn-to-connect-to-cisco-vpn-server/312950#312950)尽管它没有回答这个问题,它是一个解决方法。**注意**:ShrewSoft VPN 仅适用于 IPSec;它不适用于 SSL VPN(即较新的 Cisco AnyConnect VPN 客户端) (3认同)

归档时间:

查看次数:

169824 次

最近记录:

4 年,8 月 前