Avahi
- 零配置网络 (zeroconf) 的免费实现,包括一个用于多播 DNS/DNS-SD 服务发现的系统。它允许程序在本地网络上发布和发现运行的服务和主机,而无需进行特定配置。例如,您可以插入网络并立即找到要打印的打印机、要查看的文件以及要交谈的人。它根据 GNU 较宽松通用公共许可证 (LGPL) 获得许可。
安装
安装 avahi 包并启用 avahi-daemon.service 或使用套接字激活。
systemd-resolved.service,然后再使用 Avahi。使用 Avahi
主机名解析
Avahi 使用“hostname.local”命名方案提供本地主机名解析。要启用它,请安装 nss-mdns 包并启动/启用 avahi-daemon.service。
然后,编辑 /etc/nsswitch.conf 文件,并将 hosts 行修改为在 resolve 和 dns 之前包含 mdns_minimal [NOTFOUND=return]
hosts: mymachines mdns_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] files myhostname dns
- 如果您在解析
.local主机时遇到速度变慢(或者您不想使用 IPv6),请尝试使用mdns4_minimal和mdns4来代替mdns_minimal和mdns。 - 上述行使
nss-mdns成为.local域的权威解析器,除非您的单播 DNS 服务器响应local顶级域的SOA查询,或者请求包含两个以上的标签。请参阅nss-mdns激活说明。- systemd-resolved 会响应这些查询,即使其 mDNS 支持被禁用。请参阅 #systemd-resolved 阻止 nss-mdns 工作。
- 有关 nss 配置的更多信息,请参阅 nss-mymachines(8) 和 Avahi 文档。
为自定义 TLD 配置 mDNS
mdns_minimal 模块仅处理 .local TLD 的查询。请注意 [NOTFOUND=return],它指定如果 mdns_minimal 找不到 *.local,它将不会继续在 dns、myhostname 等中搜索它。
如果您希望 Avahi 支持其他 TLD,您应该
- 将
mdns_minimal [NOTFOUND=return]替换为完整的mdns模块。也有仅 IPv4 和仅 IPv6 的模块mdns[46](_minimal) - 使用您选择的
domain-name自定义/etc/avahi/avahi-daemon.conf - 在
/etc/mdns.allow中允许 Avahi 自定义 TLD
工具
Avahi 包含多个实用工具,可帮助您发现网络上运行的服务。例如,运行此命令可发现网络中的服务
$ avahi-browse --all --ignore-local --resolve --terminate
如果此命令没有任何输出,则很可能是由于 防火墙阻止了 mDNS 流量。
如果您只想执行 mDNS 查询以将 .local 主机名解析为 IP 地址(类似于 dig 或 nslookup),请使用
$ avahi-resolve-host-name some-host-name.local
请注意,getent hosts 命令可以同时进行 DNS 和 mDNS 查询。
Avahi Zeroconf Browser avahi-discover 显示您网络上的各种服务。请注意,它需要 Avahi 的可选依赖项 gtk3、python-dbus 和 python-gobject。您还可以使用 bssh 和 bvnc 分别浏览 SSH 和 VNC 服务器。
防火墙
如果您正在使用 防火墙,请确保打开 UDP 端口 5353。
链路本地 (Bonjour/Zeroconf) 聊天
Avahi 可用于 Linux 下的 Bonjour 协议支持。请查看 Wikipedia:Comparison of instant messaging clients 或 List of applications/Internet#Instant messaging clients 以获取支持 Bonjour 协议的客户端列表。
获取 IPv4LL IP 地址
如果 dhcpcd 客户端未能通过 DHCP 获取 IPv4LL 地址,它可以尝试获取。默认情况下,此选项已禁用。要启用它,请注释掉 noipv4ll 字符串
/etc/dhcpcd.conf
... #noipv4ll ...
或者,运行 avahi-autoipd
# avahi-autoipd -D
添加服务
Avahi 会广告在 /etc/avahi/services 中找到的 *.service 文件的服务。此目录中的文件必须可由 avahi 用户/组读取。
如果您想广告一个没有 *.service 文件的服务,创建自己的文件非常容易。例如,假设您想根据 RFC:865 在 TCP 端口 17 上广告一个每日引语 (QOTD) 服务,并且您正在您的机器上运行它
第一步是确定 <type>。 avahi.service(5) 指出类型应该是“此服务的 DNS-SD 服务类型。例如,'_http._tcp'”。由于 DNS-SD 注册表已于 2010 年合并到 IANA 注册表中,我们可以在 IANA 注册表 或 /etc/services 文件中查找服务名称。那里显示的服务名称是 qotd。由于我们在 TCP 上运行 QOTD,所以我们现在知道服务是 _qotd._tcp,端口(根据 IANA 和 RFC 865)是 17。
因此,我们的服务文件是
qotd.service
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h</name>
<service>
<type>_qotd._tcp</type>
<port>17</port>
</service>
</service-group>
有关更复杂的场景,例如广告在另一台服务器上运行的服务、DNS 子类型等,请参阅 avahi.service(5)。
请记住,Avahi 不支持 <type> 字段中的任意字符串,您只能设置 Avahi 的服务数据库中已知的值。如果您想注册自定义内容,很可能需要编辑数据库定义,构建一个更新的版本并将其分发给您的主机。
SSH
Avahi 提供了一个示例服务文件来广告 SSH 服务器。要启用它
# cp /usr/share/doc/avahi/ssh.service /etc/avahi/services/
文件共享
NFS
如果您设置了 NFS 共享,您可以使用 Avahi 在支持 Zeroconf 的浏览器(例如 KDE 上的 Konqueror 和 macOS 上的 Finder)或文件管理器(如 GNOME/Files)中自动挂载它们。
在 /etc/avahi/services 中创建一个 .service 文件,其中包含以下内容
/etc/avahi/services/nfs_Zephyrus_Music.service
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">NFS Music Share on %h</name>
<service>
<type>_nfs._tcp</type>
<port>2049</port>
<txt-record>path=/data/shared/Music</txt-record>
</service>
</service-group>
如果您的 /etc/exports 中有 insecure 选项,则端口是正确的;否则,需要进行更改(请注意,macOS 客户端需要 insecure)。路径是您的导出路径,或其子目录。出于某种原因,自动挂载功能已从 Leopard 中移除,但提供了一个脚本。这是基于此帖子。
Samba
在服务器和客户端都运行 Avahi 守护进程后,客户端上的文件管理器应该会自动找到服务器。
Vsftpd
您还可以自动发现常规 FTP 服务器,例如 vsftpd。安装 vsftpd 包并根据您的个人偏好更改 vsftpd 的设置(参见 ubuntuforums.org 上的此主题或 vsftpd.conf(5))。
在 /etc/avahi/services 中创建一个 .service 文件,其中包含以下内容
/etc/avahi/services/ftp.service
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name>FTP file sharing</name>
<service>
<type>_ftp._tcp</type>
<port>21</port>
</service>
</service-group>
FTP 服务器现在应该由 Avahi 广告。您现在应该能够从网络上另一台计算机的文件管理器中找到 FTP 服务器。您可能需要在客户端上启用#主机名解析。
故障排除
主机名更改时附加递增数字
这是一个已知错误,由主机名竞态条件引起。一个可能的解决方法是禁用 IPv6 来尝试防止竞态条件。如果存在多个接口,请使用 allow-interfaces 将 Avahi 限制为单个接口。另一个可能的解决方法是禁用缓存以阻止 Avahi 检查主机名冲突,但这会阻止 Avahi 执行查找。
systemd-resolved 阻止 nss-mdns 工作
nss-mdns 仅在 /etc/resolv.conf 中列出的 DNS 服务器对“local”域的 SOA 查询返回 NXDOMAIN 时才起作用。[1]
首先检查您配置的 DNS 服务器是否用 NXDOMAIN 回复“local”域的 SOA 查询。例如
$ host -t SOA local
如果 DNS 服务器返回 NXDOMAIN,则无需执行以下步骤。Avahi 应该能够正常找到网络中的资源,即使在使用 systemd-resolved 时也是如此。
在旧版本的 systemd-resolved 中,resolved.conf 中的全局设置 MulticastDNS=no(请参阅 resolved.conf(5))导致了 Avahi 不兼容的“local”域响应代码。这导致 Avahi 无法正确找到资源(打印机)。有关详细信息,请参阅 systemd issue 21659。
但是,如果上述 DNS 查询未能为“local”域返回 NXDOMAIN,您可以使用完整的 mdns NSS 模块而不是 mdns_minimal,并创建 /etc/mdns.allow 以仅允许“local”域。例如
/etc/nsswitch.conf
hosts: mymachines mdns [NOTFOUND=return] resolve [!UNAVAIL=return] files myhostname dns
/etc/mdns.allow
.local. .local
mdns_minimal 而不是 mdns。Avahi 套接字出现 ECONNREFUSED (连接被拒绝)
如果您的 Avahi 实例启动并正常运行,但 nss 似乎没有将请求转发到 mdns,这可能是由卡住的套接字 /run/avahi-daemon/socket 引起的。这可以通过 strace 等工具进行验证。在这种情况下,您可能需要重新启动 avahi-daemon.service 和 avahi-daemon.socket 才能使其正常工作。
KDE Connect 内置 mDNS 冲突
如果您使用 kdeconnect,则存在与 avahi 的 mDNS 冲突,因为 kdeconnect 也运行其 mdns 服务器。这可能导致主机名冲突,例如在网络重启后将您的主机重命名为 myhostname-2。
要解决此问题,请删除 kdeconnect,或构建一个不带 mDNS 支持的版本,例如 kdeconnect-no-mdnsAUR。
请参阅 kde bug 487719。
参见
- Avahi - 官方项目网站
- Wikipedia:Avahi (software)
- iTunes (包含 Bonjour) - 在 Windows 上启用 Zeroconf
- http://www.zeroconf.org/