你的 iPhone 如何随时随地连上 Mac
你的 Mac 在路由器后面,你的 iPhone 在移动网络上,谁也无法拨通对方。下面按发生的先后顺序,讲讲让它们开始通话的整个过程。
在同一网络下:Bonjour 与一个端口
Mac 应用监听 TCP 端口 51515,并通过 Bonjour 以 _remotedesktop._tcp 的名义广播自己,
附带三条简短信息:设备 ID、Mac 的名称和协议版本。iPhone 会浏览这个服务,
所以同一 Wi-Fi 下的 Mac 会出现在“附近”列表中,不需要任何人输入地址。
这条广播只是一个提示,仅此而已。任何与安全有关的判断都不依据它,因为网络上的任何人都可以广播任何内容。 真正重要的是接下来发生的事:手机打开一个 TLS 1.3 连接,双方各出示一份证书, 并各自把对方的公钥与配对时保存的那一份比对。这种配对如何运作 另有专文介绍。
在家庭网络中,手机会打开两个连接:一个用于控制(输入、设置、窗口列表),另一个只传输画面。 把视频挡在控制流之外,意味着一个很大的关键帧永远不会让鼠标点击排在它后面等待。
离开这个网络:只负责介绍的中继
一旦你离开家,手机就无法访问路由器后面的私有地址,路由器也不会接受没人请求过的连接。 所以 Mac 要提前主动迈出第一步。运行期间,它会保持一个通往 Peering 中继的出站 WebSocket 连接, 并每 25 秒发送一次简短的 ping。这个保持打开的套接字就是 Mac 的在线状态:中继靠它知道这台 Mac 存在且处于唤醒状态。
当你在 iPhone 上轻点你的 Mac 时,会发生这些事:
- 手机请中继去连接你 Mac 的设备 ID。
- 中继向两端各返回一个地址和一对随机的 16 字节令牌,一个用于控制,一个用于视频。
- 两台设备各自向中继发起一个出站 TCP 连接,并先写入自己的令牌。
- 中继匹配这两个令牌,把两个套接字接在一起,把字节从一端复制到另一端。
接着,手机开始进行与家庭网络中相同的 TLS 握手,它会直接穿过中继到达 Mac。 中继只是一条管道,并不参与这场对话,也从不持有任何密钥。如果你想了解它能知道什么、不能知道什么, 请阅读中继能看到什么。
画面走捷径
所有内容都经中继转发是可行的,但那是最慢也最昂贵的路径。所以画面不会一直留在 TCP 连接上, 而是改走 UDP,它更适合视频:迟到的帧毫无价值,重传一帧只会让下一帧更晚。
两端还会向中继提一个问题:对方是从哪个地址连过来的?中继给出它观察到的地址, 然后两台设备开始互相发送加密的小型探测包,每 250 毫秒一次。每个探测包都会在发送方自己的路由器上打开一个“洞”, 当两个洞对上时,就有探测包通过并完成验证。从那一刻起,画面直接从 Mac 传到 iPhone,中继退出视频路径。
这种技术通常称为打洞(hole punching)。它适用于大多数家用路由器,但在一些严格的移动网络和企业网络中会失败, 那种情况下,画面只是继续经由中继传输。无论哪种情况,你都不需要配置任何东西,也不需要开放端口。
当 UDP 被阻止时
有些网络会完全丢弃 UDP。如果在控制连接仍有响应的情况下,已有三秒没有收到画面, iPhone 就会请 Mac 改为通过控制流发送视频,并把视频切成小块。它的码率上限更低,所以画面会更模糊, 但模糊的画面好过冻结的画面。Mac 仍会每隔几秒在快速路径上发送一个关键帧, 手机发现该路径恢复后,就会切换回去。
为什么这样设计
- 没有入站端口。所有连接都是出站的,所以无需更改任何路由器设置,也没有任何东西暴露在互联网上。
- 没有账户。设备靠自己生成的密钥来识别,而不是靠登录。参见无需账户的配对。
- 先走便宜的路径。同一网络内免费且不计量。中继只承载直连路径无法承载的部分。
如果想看面向用户的版本,以及在你外出时让 Mac 保持可连接的设置,请参见 随时随地访问你的 Mac和 让 Mac 在远程访问时保持唤醒。
常见问题
在家以外使用 Peering,需要在路由器上开放端口吗?
不需要。所有连接都是出站的。Mac 保持一个通往中继的连接,两台设备都向它发起出站连接,所以不需要转发任何端口。
Peering 的整个会话都经过中继吗?
中继只在开始时让双方接上。之后画面会尝试直接在你的 Mac 和 iPhone 之间传输,当网络不允许直连时才退回到中继。