2011-05-17 14:23:58 +0000 2011-05-17 14:23:58 +0000
85
85

如何在连接Cisco VPN时允许本地局域网访问?

在连接到Cisco VPN时,如何保持本地LAN访问?

使用Cisco VPN连接时,服务器有能力指示客户端防止本地局域网访问。

假设不能关闭这个服务器端选项,那么如何在连接Cisco VPN客户端时允许本地局域网访问?


我曾经认为这仅仅是添加了捕获较高度量的局域网流量的路由问题,例如:

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.*

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

往后,我们可以尝试用他们的新客户端来解决【同样的问题】(https://serverfault.com/questions/307602/cisco-anyconnect-ssl-vpn-client-allows-local-lan-access-but-not-on-additional-m)。

答案 (10)

56
56
56
2013-02-05 00:07:44 +0000

Anyconnect的问题是,它先修改路由表,然后保姆,如果你手动修改它,就会把它修复起来。我找到了一个变通的方法。适用于3.1.00495、3.1.05152、3.1.05170版本,也可能适用于3.1系列的任何其他版本。可能适用于其他版本,至少类似的想法应该是工作,假设代码没有被重写。幸运的是,思科已经把保姆 “宝宝醒了 "的调用放到了一个共享库中。所以我们的想法是,我们通过LD/_PRELOAD来防止vpnagentd的动作。

1.首先我们创建一个文件hack.c

注意:这段代码只适用于Linux。将此解决方案应用于macOS机器,请参见macOS适配版.

1.然后像这样编译。

  1. libhack.so安装到Cisco库路径中。

  2. 将代理程序下线:

  3. 确保它真的被关闭

  4. 然后修复/etc/init.d/vpnagentd,在调用vpnagentd的地方添加LD_PRELOAD=/opt/cisco/anyconnect/lib/libhack.so,使其看起来像这样。

  5. 现在启动代理:

  6. 修复iptables,因为AnyConnect会破坏它们。

  7. 现在修复你喜欢的路由,例如:

  8. 检查一下它们是否真的存在。

这个黑客的一个更简单的版本给出了一个只做 "返回0; "的函数 – 那位发帖者指出 "到目前为止,我观察到的唯一副作用是vpnagentd使用了100%的CPU,就像top所报告的那样,但总体CPU只有3%的用户和20%的系统,而系统的反应是完美的. 我测试了一下,它似乎是在一个循环中做了两个选择,当空闲时迅速从两个选择中返回,但它从来没有读或写–我想我用LD_PRELOAD切掉的调用应该是读。也许有更干净的方法,但目前对我来说已经足够好了。如果有人有更好的解决方案,请分享。”

这个微不足道的黑客的问题是,它导致单个cpu核心一直处于100%的状态,有效地减少了你的硬件cpu线程数–无论你的vpn连接是否活跃。我注意到代码所做的选择是在netlink套接字上,当路由表发生变化时,它会发送vpnagentd数据。vpnagentd一直注意到netlink套接字上有新的消息,并调用routeCallBackHandler来处理它,但由于trivial hack没有清除新的消息,它只是不断地被调用。

如果有些东西不工作,就做gdb -p $(pidof vpnagentd),一旦连接。

b socket
c
bt

看看你在哪个电话里. 然后猜测你想剪掉哪一个,加到hack.c中,重新编译即可。

11
11
11
2011-12-24 14:43:04 +0000

这是非常复杂的,但如果你使用VMWare Player或类似的软件创建一个最小的虚拟机,并在虚拟机中运行Cisco AnyConnect VPN客户端,就可以使用VMWare虚拟网络适配器设置你想要的路由,或者简单地使用虚拟机通过Cisco SSL VPN访问任何需要的资源,并将文件 “拖/放 "到/从你的实际机器上。

7
7
7
2013-03-05 13:17:21 +0000

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

它可以导入思科VPN客户端的配置文件。我使用的是Cisco VPN Client 5.0.05.0290版本,安装了Shrew VPN(2.1.7版本)并导入了Cisco配置文件后,在连接到公司VPN的同时,我就可以访问本地局域网,而不需要额外配置Shrew VPN连接(或软件)。

5
5
5
2015-01-28 18:51:15 +0000

感谢 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

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

Update1/2:通过strace发现vpnagentd正在使用inotify API监控解析器文件的变化。从那以后就开始走下坡路了。这里是额外的黑客。

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

这有点矫枉过正,因为它禁用了**代理的所有文件监视。但似乎还行。

下面的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+LD_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
``` 脚本中的用户名/密码设置。
4
4
4
2012-06-17 13:37:24 +0000

我的公司还在使用那个vpn。vpnc客户端只需这样修改你的iptables设置:

# iptables-save # Generated by iptables-save v1.4.10 on Sun Jun 17 14:12:20 2012 \*filter :INPUT DROP [0:0] :FORWARD ACCEPT [0:0] :OUTPUT DROP [0:0] -A INPUT -s 123.244.255.254/32 -d 192.168.0.14/32 -j ACCEPT -A INPUT -i tun0 -j ACCEPT -A INPUT -i lo0 -j ACCEPT -A INPUT -j DROP -A OUTPUT -s 192.168.0.14/32 -d 123.244.255.254/32 -j ACCEPT -A OUTPUT -o tun0 -j ACCEPT -A OUTPUT -o lo0 -j ACCEPT -A OUTPUT -j DROP COMMIT

就可以过滤除了vpn流量以外的所有流量。

只需用iptables-save在文件中获取过滤器,添加符合你需求的INPUT和OUTPOUT访问线,然后用iptables-restore重新应用该文件。

例如要访问192.168.0上的本地网络x2& “`

Generated by iptables-save v1.4.10 on Sun Jun 17 14:12:20 2012 *filter :INPUT DROP [0:0] :FORWARD ACCEPT [0:0] :OUTPUT DROP [0:0] -A INPUT -s 123.244.255.254/32 -d 192.168.0.14/32 -j ACCEPT -A INPUT -s 192.168.0.0/24 -d 192.168.0.14/32 -j ACCEPT #local in -A INPUT -i tun0 -j ACCEPT -A INPUT -i lo0 -j ACCEPT -A INPUT -j DROP -A OUTPUT -s 192.168.0.14/32 -d 123.244.255.254/32 -j ACCEPT -A OUTPUT -s 192.168.0.14/32 -d 192.168.0.0/24 -j ACCEPT #local out -A OUTPUT -o tun0 -j ACCEPT -A OUTPUT -o lo0 -j ACCEPT -A OUTPUT -j DROP COMMIT

4
4
4
2019-02-05 01:45:11 +0000

对于那些希望在使用思科AnyConnect SSL VPN时保持对其路由表的控制的用户,请查看 OpenConnect 。它既支持思科AnyConnect SSL VPN,又不试图破坏或 “安全 "路由表条目。@Vadzim上面的评论中暗示了这一点。

在尝试了所有的方法后,除了修补AnyConnect安全移动客户端,我能够在Windows上成功地用OpenConnect GUI替换它。这使我能够保持对本地资源的连接(并更新路由表)。

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

3
3
3
2011-07-23 19:49:44 +0000

有这方面的消息吗?

思科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的指标。

3
3
3
2014-02-28 10:12:50 +0000

由于我不能添加评论,我就在这里发帖。我是在Windows上运行的。

使用虚拟机和在虚拟机内运行AnyConnect,然后使用虚拟机作为你的工作环境和公司网络之间的中介,如果你的 “心爱的 "IT部门通过VPN路由0.0.0.0,从而甚至你的本地网络(包括你的本地PC和虚拟机之间的网络)也通过VPN(原文如此!),那么这个解决方案将无法工作。

我试图应用 @Sasha Pachev 发布的解决方案,但最终我还是给 .dll 打了补丁,使它在函数开始时返回 0。最终,在与动态库进行了一些斗争之后,我能够根据我的需要修改路由表,但显然这还不够!

尽管我的规则似乎是正确的,实现了分路隧道,但我还是得到了General Failure._你有没有遇到过类似的问题,并且能够解决? *

这是我的路由表现在的样子(在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断开时的路由表(未修改)

这是VPN连接时的表(未修改),在这种情况下,当我试图ping 8.8.8.8时,我只是得到超时(因为公司的防火墙不允许流量到内网之外)

3
3
3
2011-11-06 11:44:34 +0000

不知道我的理解是否正确,我先澄清一下我的理解。

你有一个本地局域网(比如10.0.0.0/16)和一个远程的思科VPN服务器(比如64.0.0.0/16)。你想通过Cisco VPN客户端连接到VPN服务器,但你又需要有LAN的访问权限。在这种情况下,你想把整个10.0.x.x/16与VPN连接分开)。) 在Mac客户端中必须添加以下路由:

/sbin/route add -net 10.0 -interface en1

其中en1是你连接到局域网的接口。我知道你也可以在Windows和Linux中添加同样的东西。

1
1
1
2014-05-01 03:42:23 +0000

试着删除那些带有网关10.64.202.13的条目,看看ping 8.8.8.8是否有效,然后再一个一个地把它们加回来,并确定是哪个条目导致了问题。

你是怎么给DLL打补丁的。我甚至无法修改路由表,因为它一直把带VPN网关的0.0.0.0加回来。