我正在尝试找到一种解决方案,允许使用适用于 OSX 的 Cisco AnyConnect 客户端进行拆分隧道。我发现它是如何修改防火墙的,这是可以修复的。然而问题是代理服务器守护进程不断劫持路由表。
Sasha Pachev 为 Linux 提出了一个优雅的解决方案(https://superuser.com/a/546668/568559),然而我在将其适配到 OSX 时遇到了挑战。
这黑客为 Linux 编写的参考文献linux/netlink.h,这在 OSX 上是不存在的。我认为这就是AF_NETLINK来自。
#include <sys/socket.h>
#include <linux/netlink.h>
int __ZN25CInterfaceRouteMonitorMac20routeCallbackHandlerEv()
{
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;
}
我不熟悉这种语言,所以我不知道该去哪里找。我可以看到其他人在原始问题中提到了将其适配到 OSX,但我没有看到任何地方发布的结果。
有人成功将这种方法应用于 OSX 吗?非常感谢您的帮助。
一旦我解决了这个问题,我非常乐意分享完整的解决方案。
答案1
刚刚看到这篇文章。想分享一下我的结果。
我刚刚在 OSX 上做了这个 hack。Rubio 给出的解决方案确实有效(但不幸的是,也导致一个核心的 CPU 占用率达到 100%)。
由于 OSX 不使用 LD_PRELOAD,并且出于某种原因 DYLD_INSERT_LIBRARIES 不适用于此二进制文件,因此我无法诱使加载程序使用我的函数。如果其他人遇到此问题,我通过编辑原始 libvpnagentutilities.dylib 程序集解决了它(十六进制编辑器是您最好的朋友)
将函数的前 6 个字节替换为以下指令,即可实现与上面给出的 C 代码相同的“返回 0”效果:
__ZN25CInterfaceRouteMonitorMac20routeCallbackHandlerEv:
0007add0 movl $0x0, %eax
0007add5 retl
但是,在进行更多的函数调用跟踪之后,我找到了一种不增加 CPU 利用率的方法。它实际上比我上面的解决方案更简单。实际上,还有另一个符号被委托修改路由表的任务,名为 _ZN28CInterfaceRouteMonitorCommon20routeCallbackHandlerEv。跟踪该函数的调用堆栈,我发现它调用的函数在偏移量 67c06 处实现更改。
解决方案是什么?忽略我之前列出的更改,只需将 67c06 处的调用指令替换为 nop 即可!
这是之前的内容:
00067c03 movl %eax, (%esp)
00067c06 calll *0x8(%ecx)
00067c09 addl $0x4, %esp
最终版本如下:
00067c03 movl %eax, (%esp)
00067c06 nop
00067c07 nop
00067c08 nop
00067c09 addl $0x4, %esp
这应该是您要更改的全部内容。用此修改后的版本替换原始 vpnagentutilities.dylib,即可享受无需看管的路由表。它仍会在初始连接期间修改该表,但之后您可以随意更改它。
去你的 AnyCONNECT!
答案2
(我编写了这个函数的扩展版本,用于提取 NETLINK 数据,跟随 Sasha Pachev 的出色侦探工作,找到要拦截的函数。我很高兴看到大家发现该代码很有用。)
我从另一个帖子中看到有人使用“nm”发现 OSX 有一个类似的回调处理程序,而你正在尝试创建一个合适的函数来替换它。据我所知,OSX 根本不提供 NETLINK 接口,因此 OSX 版本的 AnyConnect 不太可能像 Linux 客户端那样控制路由表。我不知道 OSX 提供了什么机制来向 AnyConnect 发出路由更改已发生的信号,但由于它不是基于 NETLINK 的,因此此处用于清除 netlink 消息的代码不适用。
讽刺的是,Sasha 提供的原始存根函数样式很可能就是您所需要的,以阻止它用自己的路线替换您的路线。该函数如下所示:
int __ZN25CInterfaceRouteMonitorMac20routeCallbackHandlerEv()
{
return 0;
}
在 Linux 上,原始函数导致 CPU 使用率过高,因为触发对回调处理程序的调用的 NETLINK 事件永远不会被此无所作为的代码清除。OSX 客户端也可能发生同样的效果,无论触发调用此函数的任何事件都不会被清除。但如果此函数是要拦截的正确处理程序函数,并且您能够创建自己的库来覆盖该函数,并加载该库而不是实际库,那么至少您可以阻止它在您每次尝试自己更改路由表时重置路由表。如果您能做到这一点,牺牲一些 CPU 可能是值得的。
祝你好运!