通过 VPN 打印并不需要 Bonjour 发现
AirPrint 描述文件用地址、路径和端口指定打印机,因此发现机制无需穿越隧道。路由、该端口和 TLS 仍必须正常工作。
你大概听说过,从 iPhone 通过 VPN 打印需要 Bonjour 发现穿越隧道。这个说法把人推向 TAP 网桥和多播中继,而它们什么也修不好。AirPrint 接受显式目标:配置描述文件可以把打印机的地址、资源路径和端口交给手机。要让该条目出现在打印面板里,发现过程根本不必发生。描述文件不做的事情是创建路由、让非 AirPrint 打印机说 IPP,或者授权任务。
这个迷思始于一个真实的观察
Bonjour 按设计就是链路本地多播。被路由的点对点隧道不承载这些组,因此 VPN 上的手机无法浏览远端局域网里的打印机,同一隧道上的笔记本电脑也一样。正确的结论不是打印需要网桥,而是浏览需要另一种投递机制,而显式列表就是那种机制。
多播中继确实存在,有些网络也运营得很好,但它们解决的是你可能并不需要的发现需求。如果部署只需要打印到一台已批准的设备,那么发布这台设备比把广播域延伸到隧道另一侧更小、更易测试,也更容易撤销。
描述文件实际携带什么
描述文件 com.apple.airprint 包含一个打印机字典数组。每个字典接受一个 IPAddress(可以是字面地址或主机名)、一个 ResourcePath、一个可选的 Port 和一个可选的 ForceTLS。Apple 从 iOS 11 起记录了 Port 和 ForceTLS,因此混合设备群需要在部署前明确这一点。
路径是人们最容易猜错的那个字段。ResourcePath 对应打印机 _ipps._tcp 或 _ipp._tcp Bonjour 记录中的 rp 值。在现代无驱动打印机上它常常是 ipp/print,在较旧机型上常常是厂商专有值。从别的型号复制路径,会得到一个先出现、随后拒绝每个任务的队列。
数组中的一项如下所示,其中的占位值并不是经过测试的端点:
<dict>
<key>ResourcePath</key>
<string>ipp/print</string>
<key>IPAddress</key>
<string>printer-07.office.example</string>
<key>Port</key>
<integer>8631</integer>
<key>ForceTLS</key>
<true/>
</dict>
那个片段不是描述文件。它只是描述文件内部 AirPrint 数组的一个元素,而描述文件仍需要自己的元数据以及签名或 MDM 分发。AirPrint 打印机字典是各字段含义的参考。
从打印机本身收集这些值,而不是从搜索结果里找
在已经能打印到该设备的 Mac 上,ippfind 或 dns-sd -B _ipp._tcp 会显示广播的实例,打印机自己的网页界面通常会列出 IPP 路径和端口。把四个值都写进部署记录,下一个人就不必再从截图里重新推导。
然后有意识地决定 TLS。当 ForceTLS 为真时,手机必须信任打印机出示的证书,而自签名证书会失败,除非你也部署信任锚。为了让队列能用而关掉 TLS,是关于网络路径的决定,不是绕开麻烦证书的权宜之计。
投递,然后是两个相反的故障
在存在设备管理通道的地方通过它投递描述文件,把工作手机上手动安装的描述文件当作它本该是的例外。安装之后,打印机应当完全没有任何发现流量就出现在打印面板里。那次出现,才是描述文件唯一需要保证的东西。
一台能出现但每个任务都失败的打印机,问题在路由、端口、路径或 TLS,而这些都不是描述文件能解决的。
一台从不出现的打印机,问题反而在投递或描述文件本身:描述文件没有安装、数组格式错误,或者某个值与设备不匹配。在碰 VPN 之前,先重读这些值和目标设备。为修列表问题而加一个发现中继是昂贵的错误,因为列表从一开始就不依赖发现。
让条目保持可维护
在你控制区域的地方优先使用主机名而不是字面地址,这样地址变更不会让每个已安装的描述文件失效。该主机名必须在隧道开启时能从手机解析,这又把它带回拆分 DNS 的话题,而不是打印的话题。
把打印机所有者和描述文件所有者写进部署记录。当队列迁移时,要有意更新已发布的目标,因为旧条目不会自行过期,会继续把用户引向已退役的设备。
这些都不会让打印机具备 AirPrint 能力。描述文件发布的是一个目标,设备仍然必须会说 IPP。