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 的操作。
首先我们创建一个文件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 适配版本。
然后像这样编译它:
gcc -o libhack.so -shared -fPIC hack.c
Run Code Online (Sandbox Code Playgroud)
安装libhack.so
到 Cisco 库路径:
sudo cp libhack.so /opt/cisco/anyconnect/lib/
Run Code Online (Sandbox Code Playgroud)
取消代理:
/etc/init.d/vpnagentd stop
Run Code Online (Sandbox Code Playgroud)
确保它真的关闭了
ps auxw | grep vpnagentd
Run Code Online (Sandbox Code Playgroud)
如果没有,kill -9
只是为了确定。
如果有/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)
现在启动代理:
/etc/init.d/vpnagentd start
Run Code Online (Sandbox Code Playgroud)
修复 iptables,因为 AnyConnect 弄乱了它们:
iptables-save | grep -v DROP | iptables-restore
Run Code Online (Sandbox Code Playgroud)
您可能想要在这里做一些更高级的事情,以只允许访问某些 LAN 主机。
现在根据需要修改路线,例如:
route add -net 192.168.1.0 netmask 255.255.255.0 dev wlan0
Run Code Online (Sandbox Code Playgroud)
检查它们是否真的存在:
路由 -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 并重新编译。
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(以及其他平台)。
小智 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
正在使用inotify
API 来监视解析器文件更改。从那以后就走下坡路了。这是额外的黑客:
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)
有这方面的消息吗?
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 的指标。
归档时间: |
|
查看次数: |
169824 次 |
最近记录: |