用 LLMNR协议实现 Windows 和 Linux 的统一访问

LLMNR 全称是 Link-local Multicast Name Resolution,微软 MSDN 上2010年的一篇文章有比较详细的解释。对于一个纯粹的 Windows 机器网络而言,IPv4 可以完全通过 NetBIOS over TCP/IP(NetBT) 实现,换言之, NetBT 是不支持 IPv6 的。

LLMNR有一个典型的应用是,在一个 802.11 无线临时网络里,在没有 DHCP 服务的情况下,相互之间能通过主机名访问。

LLMNR 采用和 RFC1035 规定的类似的DNS 消息通过 UDP 5355 端口通信。
RFC4795 规定了通过 TCP 5355 端口发送消息,但是 Windows(Vista) 不支持。

对于 IPv6 , LLMNR 通过 FF02::1:3 的多播地址,IPv4 是 224.0.0.252的多播地址。DNS解析启动时,主机会向网络广播自己的地址,如果没有冲突,就宣告自己为合法的主机名,如果有冲突,就会等15分钟继续广播查询。

非常幸运的是, Linux 的 systemd-resolved 也支持 LLMNR,但是不幸的是 CentOS7 还使用比较旧版本的 systemd (219),只有229版本以后才支持全功能。

具体而言就是配置文件 /etc/systemd/resolved.conf 只支持
DNS 和 LLMNR 以及 FallbackDNS 三个选项
这个可以通过运行 man resolved.conf 看到。而同样的,在 Ubuntu 1904 上,我们可以看到更多的配置选项, man 去看手册也有更多配置选项的介绍。

在 Ubuntu 上的配置是这样的:

我们内部有两台做加密 DNS 查询的安装有 dnsmasq + DNScrypt-Proxy 的虚拟机,Domains 是解析搜索的顺序,LLMNR 就是这里的主角,打开这个开关, systemd-resolved 服务就会启用 TCP/UDP 5355 端口。MulticastDNS 是多播,会和 avahi-daemon 冲突,由于我们计划使用 LLMNR,所以,多播包括 avahi-daemon 其实都是可以关闭的。

这样子,无论在 CentOS 7 上还是 Ubuntu 上,我们只要用 yum/apt install systemd-resolved 软件包后,根据自己需要修改好配置文件: /etc/systemd/resolved.conf ,然后 systemctl –now enable systemd-resolved 就可以实现 Linux 和 Windows 的无缝访问了。只要知道主机名就可以,无须理会 IP 地址,无须设置 DNS 服务器, avahi-daemon 的多播 DNS 也可以关闭(部分网关设备会开启 avahi-daemon 实现通过名字访问,苹果的机器也需要,所以可以根据情况决定是否关闭 Linux 上的 avahi-daemon)。

当然,事情绝对不会那么顺利,在 Ubuntu 上都能正常解析的主机名,在 CentOS 上都不能相互访问,原来是 /etc/nsswitch.conf 文件作怪。 Ubuntu 上的 这个文件, hosts 那一行非常简单:
hosts: files dns

但是在 CentOS 7 上,在安装有 avahi-daemon 后,这一行是:
hosts: files mdns4_minimal [NOTFOUND=return] dns myhostname
在我们删除软件包 avahi-daemon 后,依然无解。正确的写法是:
hosts: files resolve [!UNAVAIL=return] dns

也就是说,CentOS 这里最大的坑就是 resolve 这个关键字! 没有这个关键字,系统是不会去走 LLMNR 解析的!!!

还有一个待解的问题,当操作系统是通过 dnsmasq DHCP 的 Linux ,通过 Windows 机器 ping 这些名字,都可以正常返回 IPv4 的地址,但是对于静态分配地址的机器,都只是返回 IPv6 的地址。

作者: 甬洁网络

--移动互联网&物联网技术提供商