本地代理同时面对两段网络关系:客户端到手机,以及手机到目标。把两者当成同一条路,会得到错误结论。
客户端 Socket 属于入口网络
笔记本通过 Wi-Fi 访问 CellRoute 时,Android 会在面向 Wi-Fi 的本地接口接受 TCP 连接;热点模式下,这条连接属于热点局域网路径。客户端 Socket 必须继续留在相同入口网络上,才能维持客户端与手机之间的通信。
把已接受的客户端 Socket 绑定到蜂窝网络,并不会把它变成互联网出口,反而可能破坏原本可达的本地连接。
目标 Socket 决定出口
解析并授权代理请求后,CellRoute 为目标创建第二个 Socket。简化 Kotlin 示意如下:
val socket = cellularNetwork.socketFactory.createSocket()
socket.connect(targetAddress, timeout)
正式实现还需要处理 DNS、目标地址 ACL、超时、异常、统计和清理。关键在于作用范围:每个出站目标 Socket 都由蜂窝 Network 创建,应用无需绑定整个进程,也无需修改 Android 路由表。
DNS 也应使用相同 Network
客户端提交域名时,通过 cellularNetwork.getAllByName(host) 解析,可让 DNS 与预期出口保持一致。CellRoute 会先校验返回 IP,再建立目标连接。
蜂窝 Network 消失后,新连接必须等待可用网络;旧 TCP 连接可能关闭,不能假定会迁移到新 Network。