网络与代理
网络与代理
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」一篇