好的,这是我的问题。请原谅我,因为它有点复杂。我几乎 100% 确定它是由 MacOS 10.6 内核错误引起的,但由于我们不能指望修复错误,我需要一个解决方法。
我之前了解到“ipfw ... fwd”规则在 MacOS 10.6 上不能正常工作(它在 10.5 上工作)除非你先这样做
sysctl -w net.inet.ip.scopedroute=0
然而,事实证明这个解决方案也不完美。进行此更改后大约 10 到 15 分钟,我的 Mac 基本上停止与 Internet 通信。即使我绝对有一个有效的默认路由,在我的本地网络之外 ping 任何东西都会开始说“没有到主机的路由”。我已将问题追溯到不正确的 ARP 条目。在运行上述命令之前,我的 arp 表如下所示:
# arp -a
router (192.168.42.1) at 0:1c:10:b0:d4:79 on en1 ifscope [ethernet]
运行上面的 sysctl 然后做 之后ping google.com
,看起来是这样的:
# arp -a
dd-wrt (192.168.42.1) at 0:1c:10:b0:d4:79 on en1 [ethernet]
dd-wrt (192.168.42.1) at 0:1c:10:b0:d4:79 on en1 ifscope [ethernet]
到目前为止,如此无害。但是过了一会儿,原来的 arp 条目超时了,我们只剩下新的了。MacOS 尝试刷新旧条目,但它再也没有回来。tcpdump 显示来自我的 Mac 的重复 ARP 请求,并从路由器返回正确的 ARP 响应,但答案永远不会被放入 ARP 表中。我怀疑答案只是更新同一 IP 的另一个ARP 条目,因为它们在某种哈希表中具有相同的键。
运行“arp -a -d”(或我尝试过的“arp -d”的任何变体)不会成功删除两个 ARP 条目 - 仅删除其中一个。显然,这不是正确的。
以下任何解决方法都会使问题消失,但都是不可取的:
- 不要在运行时更改 sysctl,而是编辑 sysctl.conf 并重新启动。
- 更改 sysctl 后,关闭界面并重新启动。
- 更改 sysctl 后,删除通过该接口的所有路由(使用
route
命令)并重新创建它们。
但是,这些选项中的每一个都会使系统暂时处于数据包不可路由的状态。此外,因为我实际上并不知道这个 sysctl 做了什么(有人可以指出我的文档吗?)我真的希望我的程序能够在退出时将其更改回正常状态。但是如果我这样做,那么下次我的程序启动时它会再次被破坏。
我认为我真正需要做的只是清除 ARP 表,但也许我遗漏了一些明显的东西。有没有一种简单的方法可以解决这个问题,还是我必须求助于一些丑陋的东西?
(顺便说一句,我正在开发的程序是名为sshuttle的开源程序。如果您在 sysctl 设置为默认值 1 的新 Mac 上尝试它,您应该能够轻松地复制该问题。)
感谢您的任何建议。