有时网络会出现一种很容易被误解的现象:在家里或办公室里,直接访问 nas.local、选择一台 AirPrint 打印机,或者在资源管理器里输入一台 Windows 主机名,居然都能工作。明明没有给每台设备建 DNS 记录,名字却自己“长出来了”。
这背后常被混着叫成 Bonjour、mDNS 或 LLMNR,但它们并不是同一个东西。
先给结论:Bonjour 是苹果对一组零配置网络能力的产品名称;mDNS 是在本地链路解析名字的协议;DNS-SD 是用 DNS 记录发布和发现服务的约定;LLMNR 则是 Windows 环境中另一套本地名称解析协议。 它们的目标相近,工作方式和安全影响却不一样。
四个名字,四个层次
Bonjour:一个用户能感知到的总称
Bonjour 是 Apple 使用的品牌名,常见体验是“设备插进网络就被发现”。比如 Mac 能发现共享文件夹、iPhone 能找到 AirPlay 设备、电脑能列出网络打印机。
它不是一条单独的线上的协议。实际实现通常把下面两件事组合起来:
- 用 mDNS 把主机名解析成局域网地址
- 用 DNS-SD 把“这里有什么服务”公布给同一链路的其他设备
所以看到安装程序里有 Bonjour,不应简单理解成“装了一个神秘的 Apple 网络协议”;它更接近一套基于开放标准的本地发现实现。Windows 上的一些 iTunes、打印机或开发工具也会带它。
mDNS:不问中心 DNS,向本地网络喊一声
mDNS 是 Multicast DNS,规范在 RFC 6762。它沿用 DNS 的报文格式,却不依赖一台权威 DNS 服务器。
当主机想知道 studio.local 对应哪个地址时,会向本地链路的组播地址发送 DNS 查询:
-
IPv4:
224.0.0.251:5353/UDP -
IPv6:
ff02::fb:5353/UDP
声明了 studio.local 的设备收到查询后,直接用 A 或 AAAA 记录回答。组播的 TTL/hop limit 应为 255,这也是接收端判断报文确实来自本链路的一项保护。路由器默认不会转发这种链路本地组播,因此它天然只在一个二层网络或 VLAN 内有效。
.local 是 mDNS 的特殊顶级域。这里有一个实际陷阱:如果企业把内部 Unicast DNS 域也命名为 .local,客户端就可能在普通 DNS 和 mDNS 之间产生歧义。新建内部域名时,使用受控的子域,例如 corp.example.com,通常更省心。
DNS-SD:名字之外,告诉别人“我提供什么”
只把主机名解析到 IP 还不够。用户真正需要的往往是“有没有一台支持双面打印的打印机”或“局域网里有哪些 SSH 服务”。DNS-Based Service Discovery(DNS-SD,见 RFC 6763)规定了一套 DNS 记录组织方式。
一台设备可以公布这样的服务实例:
Office Printer._ipp._tcp.local.
查询通常由几类记录拼起来:
-
PTR:_ipp._tcp.local下有哪些服务实例 -
SRV:实例实际连接的主机名和端口 -
TXT:型号、能力、队列名等元数据 -
A/AAAA:目标主机名对应的地址
这就是为什么网络打印机、HomeKit 设备或本地开发服务能够出现在系统的“可发现设备”列表里。mDNS 负责在本地交换这些 DNS 记录,DNS-SD 则定义记录应该表达什么含义。
LLMNR:Windows 的兜底名称解析
LLMNR 全名 Link-Local Multicast Name Resolution,定义在 RFC 4795。它同样借用了 DNS 报文格式,也会使用组播,但它不是 mDNS,也不负责 DNS-SD 那种服务枚举。
典型场景是:Windows 想解析一个单标签名称,例如 FILESERV,正常 DNS 没有答案或没有可用的搜索后缀时,系统可能继续发 LLMNR 查询。它使用:
-
IPv4:
224.0.0.252:5355/UDP -
IPv6:
ff02::1:3:5355/UDP
从端口、组播地址到名称空间,LLMNR 和 mDNS 都不同。把它理解成“DNS 失败时在本链路问一圈的 Windows 兜底手段”更准确。旧环境还可能同时有 NetBIOS Name Service(NBNS,UDP 137),于是一次看似普通的主机名访问,抓包里会看到 DNS、LLMNR、NBNS 依次出现。
一次解析大概发生了什么
假设笔记本要连 fileserver,但 DNS 里没有对应记录。具体顺序会受操作系统、网络策略、域加入状态和应用实现影响,不能把下面的流程当成每台机器的绝对行为,但它能解释排障时常见的现象:
flowchart TD
A[应用请求 fileserver] --> B[常规 DNS 查询]
B --> C{DNS 有答案吗?}
C -->|有| D[连接返回的地址]
C -->|没有| E[可能发 LLMNR 或 NBNS 查询]
E --> F[本链路任意主机回应]
F --> D
而访问 printer.local 时,通常是另一条路:客户端用 mDNS 向 224.0.0.251:5353 查询,打印机直接回应。发现所有 _ipp._tcp.local 服务时,则是 DNS-SD 的 PTR 查询。
理解这点很重要:“能解析”不代表答案来自你认为的 DNS 服务器。 很多“偶现的 DNS 问题”,其实是不同名称解析机制抢答,或者某个终端缓存了之前的答案。
为什么安全排查总会提到 LLMNR
LLMNR 和 NBNS 最大的问题不是报文本身复杂,而是它们常常允许网络中任何主机回答一个未被验证的名字。
假设用户误输入了 \\filesrever\share,DNS 没有这个名字。攻击者只要在同一网段监听并抢先回答“我就是 filesrever”,客户端就可能向攻击者建立 SMB 或 HTTP 连接。如果后续发生 NTLM 协商,攻击者有机会捕获挑战响应,进而进行离线口令猜测或在特定条件下中继认证。
这也是内网测试工具经常监听 LLMNR、NBNS 和 mDNS 的原因。风险的核心是:模糊的名字解析失败,被转换成了不受信任的本地广播问答。
处理优先级通常是:
- 在 Windows 域环境通过组策略关闭 LLMNR,优先修复 DNS 和搜索后缀配置
- 评估后关闭不需要的 NetBIOS over TCP/IP,淘汰依赖短主机名的旧脚本
- 对 SMB 启用签名等合适的认证保护,并限制不必要的出站认证
- 用明确的 FQDN 和受管 DNS 记录替代“猜一个机器短名”
- 在访客网、办公网、IoT 网之间做 VLAN 隔离,不让本地组播和广播跨越不该跨的边界
关闭 LLMNR 不能自动修复所有认证风险,但它能去掉一条很常见的错误解析路径。实施前应先观察是否有旧设备或应用依赖它;网络策略的目标应是把名字解析收回到可管理、可审计的 DNS,而不是让业务在某个角落悄悄失效。
mDNS 也不是“天然安全”
mDNS 比 LLMNR 更适合设备发现,但它同样是本地网络里的无认证组播协议。任何在同一链路的设备都可能看到服务名称、主机名、型号和 TXT 元数据;配置不当时,这些信息本身就足以帮助资产枚举。
这不意味着应该一刀切关掉 mDNS。AirPrint、AirPlay、HomeKit、开发机的本地服务发现都可能依赖它。更实际的处理方法是按网络边界设计:
- 家庭网络里,保留需要的发现能力,避免把陌生设备放入可信 LAN
- 公司网络里,将办公终端、访客和 IoT 设备隔离;只在确有需求时通过网关做受控的 mDNS 反射
- 不把敏感信息塞进 DNS-SD TXT 记录,例如账号、内部拓扑或可直接使用的令牌
- 盘点谁在宣告服务,移除长期遗留的共享与开发服务
很多网络设备有“Bonjour Gateway”或“mDNS Reflector”功能。它可以让不同 VLAN 的设备互相发现,但也会扩大可见范围。启用前应明确需要穿透的是哪一种服务类型,而不是把所有 _services._dns-sd._udp 信息都转出去。
怎么看见它们
排障时,先看报文通常比猜操作系统的解析顺序可靠。Wireshark 里过滤 mdns、llmnr 或 nbns,很快就能知道客户端到底问了谁、谁又回答了什么。
在常见系统上,也可以用这些工具观察:
# macOS:浏览局域网 DNS-SD 服务
dns-sd -B _ssh._tcp local.
# Linux(安装 Avahi 工具后):列出所有发现到的服务
avahi-browse --all --resolve
# Linux:直接抓两种协议的 UDP 流量
sudo tcpdump -ni any 'udp port 5353 or udp port 5355'
在 Windows 上,ipconfig /displaydns 可以查看 DNS 客户端缓存;结合事件日志、抓包和组策略结果,通常比只看一条 ping 的成败更有价值。另一个小细节是:ping 不一定复现应用的完整解析和连接路径,SMB、浏览器、系统服务各自可能有不同的解析器行为。
最后:把“方便”放在正确的边界里
Bonjour/mDNS 让局域网设备能做到开箱即用,DNS-SD 让“找到服务”比“记住 IP”自然得多;LLMNR 则是历史上为名称解析空档准备的兜底方案。
它们解决的都是便利性问题,却不该取代一个清楚的网络设计。需要自动发现的本地设备,就让它们在受控的链路内通过 mDNS 工作;需要稳定访问的服务器,就给它们受管 DNS、明确的 FQDN 和合适的访问控制;不再需要的 LLMNR 与 NBNS,则尽早从依赖链里移走。
名字解析看起来是网络里很小的一环,但它决定了连接会被交给谁。这个边界一旦模糊,排障和安全都会开始变得困难。