运维笔记:NetworkManager shared 模式给共享客户端固定 IP

Manjaro Linux 用 WiFi(wlp7s0)上网,把网线口(enp8s0)共享给一台下游设备。共享用的不是独立 dnsmasq,而是 NetworkManager 自带的 shared 模式。下游设备能正常上网,但 IP 是 DHCP 动态分的,今天 .108,下次可能 .109。想把那台设备固定成 10.42.0.2,方便后面做端口转发和固定访问。

现场

笔记本同时连着两张网卡:

NM 用 shared 模式把 enp8s0 当 LAN 口,自动开了:

  • 本机 enp8s0 = 10.42.0.1/24(shared 模式固定用 .1,改不了)
  • 一个内置 dnsmasq 提供 DHCP,动态池 10.42.0.10 – 10.42.0.254
  • net.ipv4.ip_forward=1 + 自动加 iptables NAT,把流量从 enp8s0 转到 wlp7s0 上网

确认连接是 shared 模式(下面命令里的 <共享连接名> 换成你自己的,比如我的叫 ETH_SHARE):

下游那台设备(MAC aa:bb:cc:dd:ee:01,示例)当前租约:

定位:DHCP 实际由谁发出

shared 模式的 DHCP 不是系统级的 dnsmasq.service 发的——它是 inactive 的:

真正发 DHCP 的是 NM 拉起的另一个 dnsmasq 实例,看进程就能定位到它和它的配置入口:

这条启动参数里有三个关键点:

  • --conf-file=/dev/null —— 这个实例显式忽略 /etc/dnsmasq.conf,所以 DHCP 的定制入口不在那里。
  • --conf-dir=/etc/NetworkManager/dnsmasq-shared.d —— 真正的配置目录,NM 给 shared 模式专用,默认是空目录。这就是塞 dhcp-host 的地方。
  • 它的生命周期挂在那个共享连接上——NM 激活连接时拉起、停用时杀掉,不归 dnsmasq.service 管。所以重载配置要靠重连,而不是 systemctl restart dnsmasq。
保持 NM 全托管即可,不要去启用 dnsmasq.service。它和这个内置实例会抢 53/67 端口,造成 DHCP 双重应答、DNS 冲突。

修复:往 conf-dir 放 dhcp-host 静态绑定

目标:把下游设备(MAC aa:bb:cc:dd:ee:01,示例)固定成 10.42.0.2。

dhcp-host 的格式:,,[,infinite]。infinite 是永久租约,IP 永远属于这台设备。

写完先做语法自检,别等重连了才发现 dnsmasq 起不来:

然后让 NM 重启它的 dnsmasq。最干净的方式是重连那个共享连接(下文记作 ETH_SHARE,换成你自己的连接名),NM 会自动杀掉旧 dnsmasq、起新的并加载 conf-dir:

为什么不直接 kill -HUP 那个 dnsmasq?也能用,sudo kill -SIGHUP $(cat /run/nm-dnsmasq-enp8s0.pid) 会让它重读配置、不中断现有连接。但重连更彻底——尤其当配置改了 DHCP 池范围时,HUP 不一定全量重载。这次只加 dhcp-host,两者都行,我选了重连。

验证新 dnsmasq 起来了、且带上了 conf-dir:

到这一步服务端就配完了。

客户端必须重拿一次 DHCP

配完绑定,下游设备的 IP 不会自动从 .108 变成 .2。静态绑定只在客户端下次续约/重连时生效——这是最容易漏的一步。

  • Linux 客户端:sudo dhclient -r && sudo dhclient
  • 嵌入式/摄像头/手机:拔插网线或重启设备即可

重连后回笔记本看租约:

小结

NetworkManager 的 shared 模式是个黑盒:表面上是 NM 一个连接配置,背后它替你拉起了一整套 dnsmasq + iptables + ip_forward。好处是开箱即用,代价是 DHCP 的定制入口藏得很深——不是 /etc/dnsmasq.conf,而是 /etc/NetworkManager/dnsmasq-shared.d/。

记住这个映射关系就够了:改 shared 模式的 DHCP 行为,找 NM 内置 dnsmasq 的 conf-dir,别找系统的 dnsmasq.service。

添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论