网络与代理

VM 网络架构、SOCKS5/HTTP 透明代理 sidecar、流量遥测与运行时策略控制

网络与代理

vphone-cli 为虚拟 iPhone 提供两种网络出口:默认的 shared NAT(与宿主机共享网络),以及由独立 Go 进程 vphone-network-sidecar 实现的透明代理模式(SOCKS5 / HTTP CONNECT)。代理对 guest 应用完全透明——guest 内无需任何代理配置。

网络架构

要点:

  • NAT 模式:直接用系统 NAT,不拉起 sidecar,也没有遥测数据。
  • 代理模式:主进程 posix_spawn 拉起 sidecar(独立进程组),guest 的二层以太帧经 socketpair 引到 sidecar,在用户态重建 TCP/UDP 后经上游代理或宿主机直连发出。
  • 固定拓扑:sidecar 内模拟网关 192.168.127.1,guest 固定为 192.168.127.2,内嵌 DHCP 自动下发;guest DNS 指向网关,由数据面重写转发到配置的上游 DNS。
  • guest 数据面仅支持 IPv4;IPv6 与不支持的 EtherType 直接丢弃并计数。
  • fail-closed:代理模式下 sidecar 意外退出,主进程会终止 VM,绝不静默切回 NAT。

启用代理

方式一:boot 命令行参数

make boot BOOT_ARGS="--socks5-endpoint 127.0.0.1:1080 --socks5-dns 1.1.1.1 --socks5-direct-rule 10.0.0.0/8"

常用选项(SOCKS5 与 HTTP 两组互斥):

选项 说明
--socks5-endpoint IP:port 上游 SOCKS5(必填,IP 字面量,不解析域名)
--socks5-dns IPv4 上游 DNS(必填)
--socks5-username / --socks5-password-file RFC 1929 认证(成对出现)
--socks5-direct-rule CIDR[=port,...] 分流直连规则,可重复
--socks5-udp-policy direct|block UDP 策略(默认 direct;block 可强制 QUIC 回退 TCP)
--http-proxy-endpoint / --http-proxy-dns HTTP CONNECT 代理(约束同上)

所有代理参数在 VM 启动前静态校验,非法配置直接拒绝启动,不会静默降级为 NAT。

方式二:每 VM 的 proxy_config.json

每个 VM 目录下可放一份 proxy_config.json(由 GUI 的代理设置窗口 / vphone-manager Network 页 / agent 的 proxy-config 路由编辑),下次启动生效:

{
  "enabled": true,
  "proxyProtocol": "socks5",
  "endpointHost": "127.0.0.1",
  "endpointPort": 1080,
  "dns": "1.1.1.1",
  "directRules": ["10.0.0.0/8"],
  "udpPolicy": "direct"
}

仅当命令行没有给任何代理参数时才读取该文件(命令行永远优先);enabled=false 或校验失败时按 NAT 启动并记录原因。

三种模式能力对比

能力 Shared NAT SOCKS5 HTTP proxy
guest TCP 系统 NAT SOCKS5 CONNECT HTTP CONNECT
guest UDP 系统 NAT UDP ASSOCIATE / 直连 固定宿主机直连
认证 RFC 1929 Basic
TCP/UDP 分流(direct rules) 支持 不支持
guest IPv6 系统决定 不支持 不支持

注意:HTTP CONNECT 没有 UDP 隧道能力,所有 UDP(含 QUIC/HTTP3)固定走宿主机直连——这是协议限制而非故障;要求单一出口时用 SOCKS5 或把 UDP policy 设为 block

流量遥测与运行时控制

代理模式下每次启动会创建一个 telemetry run,你可以用独立的 network-* 命令观察与干预运行中 VM 的网络(默认连最新的 live run):

# 总览:run 状态、TCP/UDP flow 数与速率
.build/release/vphone-cli network-status

# 逐 flow 列表(PATH 列显示 proxy / direct / blocked)
.build/release/vphone-cli network-flows

# 持续订阅事件流(Ctrl-C 退出,支持断点续传)
.build/release/vphone-cli network-events

# 运行时改策略:替换分流规则 / 切换 UDP 策略,即时生效
.build/release/vphone-cli network-control --direct-rule 192.168.0.0/16 --udp-policy block

GUI 侧:vphone-cli 的 Network 菜单提供实时状态摘要与 Network Inspector 遥测窗口;vphone-manager 的 Network 页编辑同一份 proxy_config.json

排障提示:

  • ping 成功只代表 sidecar 本地应答 ICMP,不代表上游代理可达
  • 先看 run 目录(/private/tmp/vphone-network-<uid>/network-runs/<UUID>/)下的 telemetry.jsonl 末尾事件,再看 flow 表。
  • 密码文件必须 0600 且属当前用户;凭据不进入 argv、日志与遥测,但 HTTP Basic 无 TLS,不要在不可信网络上使用长期凭据。

开发:改动 sidecar

sidecar 源码在 sidecar/network-proxy/(Go,含 cmd/vphone-network-sidecar 入口与 l2/dataplane/socks5/httpproxy/telemetry 等 internal 包)。改动后跑:

cd sidecar/network-proxy && go test -race ./...

sidecar 随 make build 一起编译(要求 Go ≥ 1.25)并 ad-hoc 签名;单独的 swift build 不会产出它,代理模式下找不到 sidecar 二进制会拒绝启动。

深入阅读

  • fd 契约、遥测 schema 与全部设计取舍:仓库 docs/networking.md
  • 经集群 agent 远程读写 VM 代理配置:本帮助中心「集群管理与 vphone-agent」一篇