阅读视图

发现新文章,点击刷新页面。
🔲 ☆

mDNS:Homelab 网络的良药

在 Homelab 中折腾了一段时间后,我发现自己陷入了一个困境:随着设备数量的增加,管理 IP 地址变得越来越痛苦。

典型的场景是这样的:
– SSH 到某台服务器:ssh user@192.168.1.101,等等,101 是哪台机器来着?
– 访问某个服务:`http://192.168.2.88:8080`,这个 88 又是什么?
– 更糟糕的是,DHCP 租约过期后 IP 变了,所有的配置都要改一遍

我尝试过给每台设备绑定静态 IP,但这种方案有几个问题:

  1. IP 地址难以记住:20+ 台设备,每个都要记住对应的 IP
  2. 静态绑定不优雅:在路由器上一个个配置 DHCP 静态绑定很繁琐
  3. 缺乏灵活性:设备迁移到其他网络时需要重新配置

后来我发现了 mDNS(多播域名系统),它完美地解决了这些问题。配置完成后,我可以直接使用 server3.localpfsense.local 这样的域名来访问设备,再也不用记 IP 地址了。

这篇文章记录了我在 OpenWrt + pfSense 双层路由环境下配置 mDNS 的完整过程,包括踩过的坑和解决方案。

我的网络环境

我的网络是两层路由结构:
一级路由:OpenWrt,家庭主路由器,网段 192.168.1.0/24
二级路由:pfSense,虚拟机网络路由器,网段 192.168.2.0/24

这样设置的目的是将虚拟机网络与主网络解耦,让 VM 可以独立运行并组成一个独立的集群。但这也带来了跨网段访问的问题,mDNS 的 reflector 功能正好可以解决这个问题。

路由配置篇

我的一级路由用的是 OpenWrt,二级路由用的是 pfSense。虽然系统不同,但配置思路是类似的。

核心组件是 Avahi,一个开源的 mDNS/DNS-SD 实现。OpenWrt 和 pfSense 都可以直接安装。

OpenWrt 安装配置

安装 Avahi

opkg update
opkg install avahi-daemon-service-ssh avahi-daemon-service-http

修改配置文件

编辑 /etc/avahi/avahi-daemon.conf

[server]
use-ipv4=yes
use-ipv6=yes
check-response-ttl=no
use-iff-running=no
allow-interfaces=br-lan   # 指定监听的网络接口

[publish]
publish-addresses=yes
publish-hinfo=yes
publish-workstation=no
publish-domain=yes

[reflector]
enable-reflector=yes      # 关键:启用 reflector 功能,用于跨网段转发
reflect-ipv=no

[rlimits]
rlimit-core=0
rlimit-data=4194304
rlimit-fsize=0
rlimit-nofile=30
rlimit-stack=4194304
rlimit-nproc=3

关键配置说明
allow-interfaces=br-lan:指定 Avahi 监听的网络接口
enable-reflector=yes:启用 reflector 功能,这是实现跨网段 mDNS 的核心

参考:

  • https://openwrt.org/docs/guide-developer/mdns
  • https://openwrt.org/docs/guide-user/network/zeroconfig/zeroconf

pfSense 安装配置

安装插件

在 pfSense 的 Package Manager 中搜索并安装 avahi 插件。

关键问题:WAN 接口配置

这里我踩了个坑。pfSense 默认不允许在 WAN 接口启用 mDNS,这是出于安全考虑(如果 WAN 是公网,确实不应该暴露 mDNS)。

但在我的两层路由场景下,二级路由的 WAN 接口连接的是一级路由的 LAN,需要在 WAN 接口启用 mDNS 才能实现跨网段通信。

解决方法:修改插件源码

编辑 /usr/local/www/avahi_settings.php,找到并注释掉 WAN 过滤代码:

// vi /usr/local/www/avahi_settings.php
// 找到两处 wan 的过滤代码,注释掉:
// unset($available_interfaces['wan']);

修改后,在 Web 控制台就可以看到 WAN 选项了,同时选中 WAN 和 LAN 启用。

生成的配置文件

修改后 pfSense 会自动生成配置文件(位于 /usr/local/etc/avahi/avahi-daemon.conf):

这里需要注意:不推荐直接手动修改这个配置文件,因为它会被 GUI 覆盖。建议通过修改 PHP 源码让 GUI 支持 WAN 配置。

参考配置内容

# /usr/local/etc/avahi/avahi-daemon.conf
[server]
allow-interfaces=em0,em1    # WAN 和 LAN 接口
use-ipv4=yes
use-ipv6=no

[publish]
publish-addresses=yes
publish-domain=yes

[reflector]
enable-reflector=yes        # 启用跨网段转发

可选:启用 D-Bus

某些情况下可能需要启用 D-Bus:

mkdir -p /var/run/dbus/
dbus-daemon --system

至此 pfSense 的配置就完成了。

防火墙配置

重要:mDNS 使用 UDP 5353 端口,需要在防火墙中开放此端口。

确保允许以下流量:
– 源:LAN 主机
– 目标:路由器本机(224.0.0.251,mDNS 组播地址)
– 端口:UDP 5353

具体配置方法因路由器而异,在 OpenWrt 或 pfSense 的防火墙规则中添加即可。

主机配置

路由器配置完成后,还需要配置各个主机才能使用 mDNS。我这里以 Ubuntu Server 为例。

设置 Hostname

首先给主机设置一个有意义的 hostname:

sudo hostnamectl set-hostname server3

之后就可以通过 server3.local 访问这台主机了。

配置网络为 DHCP

mDNS 的一大优势是不需要静态 IP,所以把网络配置改为 DHCP:

# 编辑 netplan 配置
vim /etc/netplan/00-installer-config.yaml
network:
  ethernets:
    ens34:
      dhcp4: true
  version: 2
# 应用配置
netplan apply

启用 systemd-resolved 的 mDNS 功能

Ubuntu 新版本使用 systemd-resolved 管理 DNS,需要在这里启用 mDNS:

# 编辑配置文件
vim /etc/systemd/resolved.conf
[Resolve]
MulticastDNS=yes
LLMNR=yes

或者用命令一键修改:

sed -i "s|#MulticastDNS=no|MulticastDNS=yes|g" /etc/systemd/resolved.conf
sed -i "s|#LLMNR=no|LLMNR=yes|g" /etc/systemd/resolved.conf
systemctl restart systemd-resolved

踩坑:Netplan 不支持 mDNS 配置

这里有个大坑。即使修改了 resolved.conf,mDNS 在网络接口上仍然是关闭的:

# 检查接口的 mDNS 状态
resolvectl mdns ens34
# 输出:Link 2 (ens34): no

# 手动启用
resolvectl mdns ens34 yes

但这个设置重启后会失效,因为 Netplan 不支持 mDNS 配置(相关 Bug,2019 年提出至今未修复)。

Netplan 会在 /run 目录下生成配置文件,优先级高于 /etc,导致手动修改无效。

解决方案:创建 systemd 服务

既然是开机自启动的问题,那就用 systemd 来解决:

创建 systemd 服务文件:

cat << EOF > /etc/systemd/system/user-set-mdns@.service
[Unit]
Description=Enable MulticastDNS on network interface
After=systemd-resolved.service

[Service]
ExecStart=resolvectl mdns %i yes

[Install]
WantedBy=multi-user.target
EOF

启用服务(替换 ens34 为你的网卡名称):

sudo systemctl enable user-set-mdns@ens34
sudo systemctl start user-set-mdns@ens34
sudo systemctl status user-set-mdns@ens34

至此,主机的 mDNS 配置就完成了,重启后也会自动生效。

方案二:使用 Avahi(适用于老系统)

如果你的系统没有使用 systemd-resolved(比如老版本的 Ubuntu 或 Debian),可以直接安装 Avahi:

sudo apt-get install avahi-daemon libnss-mdns libnss-mymachines

安装后 Avahi 会自动启动,无需额外配置。

验收测试

配置完成后,让我们测试一下效果。

基本测试

现在可以抛弃 IP 地址,直接使用 .local 域名访问设备:

ping server3.local
ping code-env.local
ping vm-proxy.local
ping pfsense.local
ping openwrt.local

实际使用场景

SSH 连接

# 以前
ssh user@192.168.2.101

# 现在
ssh user@server3.local

访问 Web 服务

# 以前
http://192.168.2.88:8080

# 现在
http://vm-proxy.local:8080

容器配置

# docker-compose.yml
services:
  app:
    environment:
      - DATABASE_URL=postgresql://postgres@db-server.local:5432/mydb

跨网段测试

最重要的是测试跨网段访问,确认 reflector 功能正常工作:

# 从一级网络(192.168.1.x)访问二级网络设备
ping vm-server.local  # 这台设备在 192.168.2.x 网段

# 从二级网络访问一级网络设备
ping openwrt.local    # 这台设备在 192.168.1.x 网段

如果能 ping 通,说明 mDNS reflector 配置成功!

补充说明

二级路由的 IP 配置注意事项

后续重新部署时发现一个问题:如果 pfSense 二级路由使用静态 IP,会导致一级路由无法获取二级的 mDNS 记录。

解决方法
– 在一级路由(OpenWrt)上通过 DHCP 静态绑定给二级路由分配 IP
– 不要在二级路由上直接配置静态 IP
– 配置好后重启二级路由

OpenWrt 防火墙规则(命令行方式)

如果你习惯用命令行配置 OpenWrt 防火墙,可以使用以下命令:

uci -q delete firewall.mdns
uci set firewall.mdns="rule"
uci set firewall.mdns.name="Allow-mDNS"
uci set firewall.mdns.src="*"
uci set firewall.mdns.src_port="5353"
uci set firewall.mdns.dest_ip="224.0.0.251"
uci set firewall.mdns.dest_port="5353"
uci set firewall.mdns.proto="udp"
uci set firewall.mdns.target="ACCEPT"
uci commit firewall
/etc/init.d/firewall restart

配置完 mDNS 已经几个月了,现在回想起来,这是我在 Homelab 中做的最有价值的优化之一。

带来的改变

管理效率提升
– 不再需要维护一个 IP 地址清单
– 设备迁移或重启后不用担心 IP 变化
– 写配置文件时直接用域名,可读性大大提升

实际案例

最近我重装了一台服务器,以前的流程是:
1. 安装系统
2. 登录路由器配置静态 IP 绑定
3. 更新所有相关配置文件中的 IP
4. 重启依赖这台服务器的其他服务

现在的流程:
1. 安装系统
2. 设置 hostname
3. 完事

其他服务根本不需要改配置,因为它们用的是 server3.local 这样的域名,自动就能找到新的 IP。

一些建议

命名规范很重要

建议给设备起一个有意义的 hostname:
nas.local 而不是 server1.local
pve-node1.local 而不是 vm1.local
k8s-master.local 而不是 ubuntu-001.local

好的命名可以让你半年后还记得这台设备是干什么的。

文档还是要有的

虽然不用记 IP 了,但建议维护一个简单的设备清单:
– 设备名称和 hostname
– 主要用途和运行的服务
– 重要配置文件位置

安全性考虑

mDNS 只适合内网使用,不要在公网暴露:
– 路由器 WAN 口不要启用 mDNS
– 如果有公网 IP,确保防火墙规则正确
– mDNS 流量不应该离开你的局域网

总结

mDNS 确实是 Homelab 的良药。它解决了 IP 地址管理的痛点,让网络配置更加灵活和优雅。虽然配置过程有一些坑(特别是 Netplan 的问题),但一旦配置好,体验提升是显著的。

如果你也在运营 Homelab,强烈建议试试 mDNS。配置时间不会超过一个下午,但带来的便利是长期的。

希望这篇文章能够帮助你顺利配置 mDNS,少走一些弯路。

参考链接

🔲 ☆

感觉的代价?

看到网友的一篇帖子:

在我二十歲以前,我是一個可以穿牛仔褲睡覺的人。我可以在,今日看起來實在不太舒適的環境下睡覺,不會特別覺得怎麼樣;舉例來說,那時我的床板上鋪的是幾張囤起來準備做模型用的紙板,冬天時實在被床板沁上來的寒意冷得受不了,才去買薄床墊。

那時的我是非常荒廢「感覺」的,我不僅和內在的感覺疏離,也很鈍於外在的感覺,我認為那是我可以穿著牛仔褲睡覺的原因。現在的我,即使穿著柔軟的睡褲,有時候還嫌壓到衣褶子不舒服,差不多是個豌豆公主。

就算現在的我想越過時空去對過去的我表達憐惜,那時的我也一定感覺不到吧。

回頭一看,真是跋涉了好長的路,來到這裡。#

这样的视角,我还是第一次见,于是感到很惊讶。以往看到过很多描述,和年轻时可以随意风餐露宿的状态的对比,最终都是自嘲几句如今娇气了。而这一篇,则认为从前的状态,是一种「不重视感觉」?与之相对的,如今的豌豆公主,是一种重视感觉后的进步?or 至少是进步的代价?

我提出这样的疑问。对方也是日常在 follow 的,多数三观比较一致的网友,于是回复的氛围也很融洽。对方的回复:

的確也有想過自己是不是變得嬌貴了,不過畢竟自己的事情自己最清楚;那時發生了一些大大小小的事,年輕時的我很自己為可以用理智壓制自己的一切,卻在重要關頭發現身體與意志不統合,情緒會逃出來控制身體。

至於豌豆公主是好是壞,我倒沒有想評價,而是接受。頂多就是,感謝現在的我有一些外在條件讓我可以是豌豆公主吧。

其它有着共鸣的人也来讨论:

這樣的狀態是一種進步嗎?我覺得我不會用進步形容它。比較像是在爬一座山,一開始在山腳時,我的身心靈狀態,和登上山後,身心靈狀態已經皆然不同了。

以前的我因為一些事情,常常是伴著淚水入睡的,或是餓著肚子入睡的。從現在往回看,那時候我的身心靈是身.心.靈,三者分開,處於一種先各自顧好自己,無暇顧及其他的狀態。

后面更多地在交流,重视感觉的重要性,和渐渐懂得要重视感觉的心路历程……


我当然赞同重视感觉的重要性;但我大概明白,这个思路的 bug 在哪里。把风餐露宿的青春,和不重视感觉的青春,过度地绑定在一起,以致于前者连带着一同被否定。以及,在发言者之后的人生历程中,那些风餐露宿,并不是什么需要被重视、发展的能力,所以也就无妨被顺带抛弃。抛弃时甚至不会想着,要不要捡回来珍念一下。

发言的人,日常的生活方式、和在其它维度的一些倾向,也符合我的预期。所以也只是大家对不同东西的权重不同吧。并没有否定对方的意思;只是这样的思路我第一次见,记录一下。

❌