运维笔记:NetworkManager shared 模式给共享客户端固定 IP
Manjaro Linux 用 WiFi(wlp7s0)上网,把网线口(enp8s0)共享给一台下游设备。共享用的不是独立 dnsmasq,而是 NetworkManager 自带的 shared 模式。下游设备能正常上网,但 IP 是 DHCP 动态分的,今天 .108,下次可能 .109。想把那台设备固定成 10.42.0.2,方便后面做端口转发和固定访问。
现场
笔记本同时连着两张网卡:
1 | 上游 WiFi(出口) |
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):
1 | $ nmcli connection show ETH_SHARE | grep ipv4.method |
下游那台设备(MAC aa:bb:cc:dd:ee:01,示例)当前租约:
1 | $ sudo cat /var/lib/NetworkManager/dnsmasq-enp8s0.leases |
定位:DHCP 实际由谁发出
shared 模式的 DHCP 不是系统级的 dnsmasq.service 发的——它是 inactive 的:
1 | $ systemctl status dnsmasq |
真正发 DHCP 的是 NM 拉起的另一个 dnsmasq 实例,看进程就能定位到它和它的配置入口:
1 | $ ps aux | grep dnsmasq | grep -v grep |
这条启动参数里有三个关键点:
--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。
1 | $ sudo mkdir -p /etc/NetworkManager/dnsmasq-shared.d |
dhcp-host 的格式:<MAC>,<IP>,<hostname>[,infinite]。infinite 是永久租约,IP 永远属于这台设备。
写完先做语法自检,别等重连了才发现 dnsmasq 起不来:
1 | $ sudo dnsmasq --test --conf-file=/dev/null --conf-dir=/etc/NetworkManager/dnsmasq-shared.d |
然后让 NM 重启它的 dnsmasq。最干净的方式是重连那个共享连接(下文记作 ETH_SHARE,换成你自己的连接名),NM 会自动杀掉旧 dnsmasq、起新的并加载 conf-dir:
1 | $ sudo nmcli connection down ETH_SHARE && sudo nmcli connection up ETH_SHARE |
为什么不直接
kill -HUP那个 dnsmasq?也能用,sudo kill -SIGHUP $(cat /run/nm-dnsmasq-enp8s0.pid)会让它重读配置、不中断现有连接。但重连更彻底——尤其当配置改了 DHCP 池范围时,HUP不一定全量重载。这次只加 dhcp-host,两者都行,我选了重连。
验证新 dnsmasq 起来了、且带上了 conf-dir:
1 | $ cat /run/nm-dnsmasq-enp8s0.pid |
到这一步服务端就配完了。
客户端必须重拿一次 DHCP
配完绑定,下游设备的 IP 不会自动从 .108 变成 .2。静态绑定只在客户端下次续约/重连时生效——这是最容易漏的一步。
- Linux 客户端:
sudo dhclient -r && sudo dhclient - 嵌入式/摄像头/手机:拔插网线或重启设备即可
重连后回笔记本看租约:
1 | $ sudo cat /var/lib/NetworkManager/dnsmasq-enp8s0.leases |
小结
NetworkManager 的 shared 模式是个黑盒:表面上是 NM 一个连接配置,背后它替你拉起了一整套 dnsmasq + iptables + ip_forward。好处是开箱即用,代价是 DHCP 的定制入口藏得很深——不是 /etc/dnsmasq.conf,而是 /etc/NetworkManager/dnsmasq-shared.d/。
记住这个映射关系就够了:改 shared 模式的 DHCP 行为,找 NM 内置 dnsmasq 的 conf-dir,别找系统的 dnsmasq.service。