VPN 下投屏失败:发现、控制还是播放?
接收设备找不到、会话被拒、播放中途卡住,这三类故障出在不同的环节。先弄清是哪一环,再决定要不要改手机的 VPN 策略或网络。
投屏会在三个地方断掉,而它们从沙发上看起来一模一样。手机可能始终看不到接收设备,接收设备可能出现后拒绝会话,也可能会话已经建立、一分钟后才卡住。手机上的隧道对这三条路径的影响各不相同,对其中一条则是毫无影响。先给失败的那一环命名,再判断改策略是不是正确的杠杆。
先给失败的一环命名,再改策略
观察你点下投屏图标之后手机立刻做了什么。列表为空是发现环节的结果,点击后报告失败是控制环节的结果,会话先建立、稍后才卡住是播放环节的结果。这三者的责任方不同,通常只有前两者与手机的隧道设置有关。
| Stage | What the phone shows | Evidence that separates it |
|---|---|---|
| Discovery | No receiver in the list | Another device on the same segment sees the receiver |
| Control | Receiver listed, session refused | Port answer versus permission prompt |
| Playback | Session starts, then stalls | The receiver's own link, not the phone's |
在改动任何东西之前,先把环节写下来。把修复用在错误的环节上,会让下一次测试变得无法解读,而大多数关于投屏的传言正是从这种混淆里来的。
发现是本地流量,而隧道会把它藏起来
接收设备通过本地通告来广播自己,手机则在同一条链路上用查询把它们找出来,所以任何让手机离开那条链路的做法都会让接收设备从列表里消失。把所有流量都导离局域网的隧道会遮住这些交换,而应用层的本地网络权限即使路由存在也能拦住它们。开了客户端隔离的访客 Wi-Fi 完全不涉及 VPN,也能造出同样的空列表。先证明两台设备处于同一网段,再去怪隧道。
avahi-browse -at | grep -i -E 'chromecast|googlecast'
dig +short @224.0.0.251 -p 5353 _googlecast._tcp.local PTR
第一条命令列出辅助机的网段上有什么在自我通告,第二条直接询问组播 DNS 组。两边都看不到的接收设备,也不会出现在手机应用里,无论手机的隧道处于什么状态。如果从关闭隧道的设备上能看到接收设备,从开启隧道的设备上看不到,那你就同时找到了环节和原因。
局域网例外能让隧道保持开启
许多客户端提供本地网络例外,让隧道保持活动,同时放行本地地址。请用这个有文档的设置,而不是关掉断网开关或整块防火墙,因为后者改动的东西远超过投屏所需。如果网络是有意隔离智能设备的,就向管理方申请具体的发现、控制和回传流量,而不是要求平铺式放行。
nc -vz 192.168.1.50 8009
针对接收设备的控制测试能把权限与可达性分开:端口有应答说明路径存在,而拒绝则说明手机被允许发现该设备,却仍然无法与它通信。8008 和 8009 是常见的投屏端口,应用也可能用别的端口,所以单个端口被拒只能算线索,不能算结论。例外与应用权限彼此独立,因为放行本地访问并不会建立路由,而加一条路由也不会赋予权限。断网开关还可能在重连后丢掉本地流量,这就是隧道恢复后必须重新测试发现环节的原因。
播放可能根本不用手机的连接
在应用主导的会话里,手机把媒体地址交给接收设备,由接收设备用自己的连接去取,所以改手机的对外地址对这条流没有任何作用。受账号限制的片源仍可能因为自身原因失败,而 Google 的投屏要求涵盖的是应用与设备的兼容性,而不是网络路径。让电视本身走隧道是另一套配置,有它自己的策略问题。
两条线索可以区分这两种模式。锁上手机屏幕后仍在继续的投屏是应用主导的,因为接收设备在自己取流;发送端屏幕一锁就停的镜像,是来自手机的连续流。当发现和控制都成功、只有播放卡住时,去看接收设备的 Wi-Fi 链路和它的上网路径,因为在手机上测速描述的是手机,不是电视。
撤销例外并重新测试
每一处临时改动都需要回退的路径,而且顺序很重要。移除局域网例外,重新连接隧道让客户端重新应用策略,然后重复发现那一步,并记下接收设备是否又消失了。这个顺序能告诉你,是例外在起作用,还是中间有别的东西变了。
# after removing the LAN exception, reconnect and confirm the tunnel is up
resolvectl status | grep -E 'DNS Servers|Default Route|Protocols'
avahi-browse -at | grep -i -E 'chromecast|googlecast'
之后分别验证这三个环节,因为其中一个通过并不能说明其他两个。接着检查无关的手机应用是否仍走预期路由,因为一个悄悄变成完全绕行的本地例外,比需要多按一次的投屏要糟糕得多。