mDNS(Multicast DNS,组播 DNS)是一种在本地局域网内、无需专用 DNS 服务器就能做主机名解析与服务发现的协议。
功能
主机名解析:把 my-printer.local 解析成 IP,适用于临时/家庭/小型网络,无需搭建 DNS。
服务发现(配合 DNS-SD):发现“有哪些 AirPlay、打印、HTTP 服务”等,而不仅仅是主机名。例如浏览 _airplay._tcp.local、_http._tcp.local。
关键点一览
端口与地址:UDP/5353;IPv4 组播 224.0.0.251,IPv6 组播 ff02::fb(链路本地,路由器不会转发)。
正确的 mDNS 查询(多播)需要满足
IP Header 中目标IP地址属于多播地址 224.0.0.251 或 ff02::fb
Ethernet Header中目标 MAC 属于多播 MAC(由多播IP编码而成)
IPv4 mDNS(224.0.0.251)→ 01:00:5e:00:00:fb
规则:01:00:5e + IPv4 多播地址的低 23 位(RFC 1112)。对 224.0.0.251(0xE0.00.00.FB)映射即 00:00:fb。
IPv6 mDNS(ff02::fb)→ 33:33:00:00:00:fb
规则:33:33 + IPv6 组播地址的低 32 位(RFC 2464/5342)。
UDP、端口 5353
域名后缀:通常是 .local.(RFC 6762 规定为 mDNS 专用后缀)。
相关标准:RFC 6762(mDNS)、RFC 6763(DNS-SD)。
常见实现/名称:Apple Bonjour(macOS/iOS),Linux 上的 Avahi,Windows 10+ 也支持 mDNS。
使用
主动查询
你要访问 host.local,系统把 DNS 查询改为发组播到 224.0.0.251:5353。
网段里拥有该名字的设备直接单播/组播回复 A/AAAA 记录(还可能带 SRV/TXT 等)。
DNS-SD:要找服务时,先查询 _<service>._<proto>.local(比如 _http._tcp.local)得到服务实例名,再查 SRV/TXT 获取主机名+端口+元数据,最后查主机名的 A/AAAA。
冲突处理:设备上电会探测(probe)名字是否被占用;如冲突会改名(如 X (2).local)并宣布(announce/defend)。
被动缓存
mDNS/ DNS-SD 守护进程(macOS 的 mDNSResponder、Linux 的 avahi-daemon)会旁听所有 5353 流量,把看到的应答(含开机 announce、后续更新、goodbye=TTL 0)放进本地缓存。
主机名解析与服务发现
主机名解析:只用 A/AAAA 查询 host.local
服务发现(DNS-SD):查 _service._tcp.local
目标 | 查询名 | 主要 RR 类型 | 结果里有什么 | 适用场景 |
|---|---|---|---|---|
主机名解析 | host.local. | A/AAAA(可能带附加记录) | 只给你 IP(v4/v6) | 你已经知道主机名,只想拿到 IP |
服务发现(DNS-SD) | _<service>._<proto>.local.(例如 _http._tcp.local.)或先查 _services._dns-sd._udp.local. | PTR → SRV + TXT → A/AAAA | 发现有哪些“服务实例”(名字、端口、元信息),再解析它背后的主机 IP | 你不知道谁提供服务、端口是多少、或需要按类型列出 |
简化流程对比:
主机名解析:
你发 A/AAAA host.local → 返回 A/AAAA(IP)。到此结束。
服务发现:
你发 PTR _http._tcp.local → 得到若干实例名(比如 "Home Assistant._http._tcp.local")
→ 对某个实例发 SRV/TXT → 得到目标主机名 + 端口 + 元数据(如路径、特性)
→ 再对目标主机名发 A/AAAA 拿到 IP。链路更长,但信息更全。
_services._dns-sd._udp.local
DNS-SD 的“服务类型枚举 (Service Type Enumeration)”入口。
对 _services._dns-sd._udp.local 发 PTR 查询,网络里的设备会用 PTR 记录告诉你“我正在发布哪些服务类型”。返回的不是具体设备或 IP,而是一串类型名,比如:
_http._tcp.local. _airplay._tcp.local. _raop._tcp.local. _googlecast._tcp.local. _hap._tcp.local. # HomeKit / HAP _home-assistant._tcp.local. _ipp._tcp.local. # IPP 打印
这一步就像“先看看这个网段都有什么品类的服务”。
说明:设备/栈(Bonjour/Avahi)通常会自动把自己声明的服务类型通过这个入口再“指一遍”。不是强制标准动作,但主流实现都支持,所以 Browser / Scan 类工具常用它来“列清单”。
工具
# 列出全部服务 avahi-browse -at # 列出全部服务及其解析结果 avahi-browse -art # 列出网段里“有哪些服务类型” avahi-browse -rt _services._dns-sd._udp # 浏览某个服务类型(列出实例名) avahi-browse -rt _http._tcp # 针对具体实例查看 SRV/TXT/IP(avahi 会自动跟进解析) avahi-browse -rt _hap._tcp # 或 Apple 工具分步: dns-sd -B _http._tcp # 浏览类型 dns-sd -L "Home Assistant" _http._tcp local # 解析某个实例 → SRV/TXT/A/AAAA