@
cs010 不知道楼主现在问题解决了没有,有机会的话可以沟通交流一下。我做了一个跨平台的 VPN 软件,其中很多遇到的坑应该都和你一样踩过。看了很多回复,很多人真的太过于想当然了。从路由层面上来说,修改路由表是跨平台方案绝对不可行的一条路,在 ios/android 平台基本上属于死路。首先 VPN 的话,如果想做到尽可能多的事情,Android 的 VPNService,macos/ios 的 Network Extension 或 Network system Extension(PacketTunnelProvider ),windows 的 Wintun 都是不错的选择。至于在 default route 走 tun 情况下,其他流量怎么出去;首先系统为了防止到 VPN server 不再命中 default ,都提供了一种添加明细的方式(当然,大部分都是开启时指定,不能动态修改),如 Android 里 VPNService 的 protect, macos/ios 里 NE 的 SeverIP/Exculde routes 等可以帮助你做到这点。如果不满足的话,就像你说的必须经过协议栈(lwip,实际上有一种巧妙的方法可以让系统协议栈帮我们做这件事而不用嵌入用户态协议栈)拿到报文,你自己作为一个 TCP/UDP 代理再绑定接口把包发出去。socket.SO_BINDTODEVICE 这个选项如果不行,你可以直接绑定接口的 src ip 尝试一下,我实测两种方式都是 work 的,后者怀疑是 macos 有相关的策略路由 :)