在多个DHCP服务器的网络环境中选择指定的DHCP服务
问题
学校有两个网络,我电脑网线插在同一个交换机的同一个接口上,有时候获取的是172.27开头的IP,有时候获取的是192.168开头的IP。
通常第一次开机获取的是172.27的IP,插拔网线或重启网络接口后会变为192.168的IP。
两个网络各有作用但是并不互通,非常影响正常使用网络,因此我使用以下方式使得电脑固定通过DHCP获取172.27开头的ip。
原因解析
这种现象表明电脑连接的是一个同时存在两个网络环境(两个不同的DHCP服务器)的局域网 ,并且这两个网络在同一个物理交换机上共存。
这个交换机可能连接着两个不同的路由器或三层设备 ,分别运行着两个DHCP服务。
- 一个是提供
172.27.x.x
段的DHCP服务器,DHCP服务器和网关都是172.27.1.1
; - 一个是提供
192.168.x.x
段的DHCP服务器,DHCP服务器和网关都是192.168.1.1
;
当电脑发送DHCP请求时,两个DHCP服务器都可能收到请求,并响应DHCP Offer,客户端通常选择第一个收到的DHCP Offer 作为自己的配置来源;
解决方案
原理
如果允许手动设置IP地址,那很简单,直接手动设置IP为所需网段的IP地址即可。
不然在没有权限操作上层交换机的情况下,只能通过技术手段,设法使得设备仅接收特定DHCP服务器的DHCP Offer。
输入以下命令监听eth0
接口的DHCP报文
sudo tcpdump -i eth0 port 67 or port 68
方案
我电脑是Ubuntu 24.04,网络配置使用的是 netplan + systemd-networkd 的方案,但 systemd-networkd 的 DHCP 客户端并不支持对 DHCP Offer 进行筛选,因此我需要使用 dhclient 来替代DHCP的这个功能。
配置dhclient作为DHCP客户端
Ubuntu自带dhclient,默认没有启用。若没有则需要安装。
sudo apt install isc-dhcp-client
修改 dhclient 配置文件,将模板从 /etc/dhcp/dhclient.conf
复制到 /etc/dhcp/dhclient.eth0.conf
,eth0
修改为你的网络接口名称。添加一行reject 192.168.1.1;
,使其拒绝来自192.168.1.1
的内容,这样就可以只响应和接受172.27.1.1
的DHCP服务了。
# /etc/dhcp/dhclient.eth0.conf
reject 192.168.1.1;
禁用原DHCP功能
修改 netplan 配置文件,设置将dhcp4: no
,使 networkd 不处理 dhcp,交由 dhclient 完成。
# /etc/netplan/01-netcfg.yaml
network:version: 2renderer: networkdethernets:enp6s0:dhcp4: nodhcp6: no
设置dhclient开机启动
配置 dhclient 服务以使其开机启动,创建以下文件:
参考:https://github.com/egberts/systemd-dhclient
# /etc/systemd/system/dhclient@.service
[Unit]
Description=dhclient on %I
Documentation=man:dhclient(8)# dhclient wants network.target afterward
# dhclient will stay up regardlessof network.target failure
Wants=network.target#
Before=network.target# Binds to a specific device based on %i
BindsTo=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device[Service]
# Reads /etc/dhcp/dhclient.conf, by default
# Invokes /sbin/dhclient-script, by default, upon receiving a lease IP
# Force dhclient to run in foreground and let systemd handle all Unix FDs (0,1, and 2)
ExecStart=/sbin/dhclient -4 -d -v -cf /etc/dhcp/dhclient.%I.conf -pf /var/run/dhclient.%I.pid -lf /var/lib/dhcp/dhclient.%I.leases %I
Type=simple
PIDFile=/run/dhclient.%I.pid# DHCLIENT should never exit, ever.
# DHCLIENT should not use '-1' option nor handle exit code 2 in a special way
Restart=always
##### TBD ExecStop=/sbin/dhclient -x
##### TBD ExecReload=/sbin/dhclient -r
#StandardInput=null
#StandardOutput=journal
#StandardError=journal# Environment variables used by dhclient
# Could define those envname in /etc/default/dhclient.%I
# PATH_DHCLIENT_CONF The dhclient.conf configuration file.
# PATH_DHCLIENT_DB The dhclient.leases database.
# PATH_DHCLIENT_PID The dhclient PID file.
# PATH_DHCLIENT_SCRIPT The dhclient-script file.
# environment filespec is prefaced with '-' as to ignore if unreadable or nonexisting
EnvironmentFile=-/etc/default/dhclient
EnvironmentFile=-/etc/default/dhclient.%I[Install]
WantedBy=multi-user.target
设置开机启动,其中eth0
修改为你的网络接口名称,下同:
sudo systemctl enable dhclient@eth0.service
这是重启应该就能成功了,如果你不想重启,执行以下代码应用该设置:
sudo netplan apply && sudo systemctl start dhclient@eth0.service
连带问题
系统中还存在一个systemd-networkd-wait-online.service
服务,其目的是在完成计算机启动前等待网络连接,但我使用了 dhclient 替代了一部分 networkd 的功能,使其 无法再感知 IP 是否已配置成功,这会导致开机时卡在该步骤直至超时,影响启动体验。
建议直接禁用 systemd-networkd-wait-online.service
sudo systemctl disable systemd-networkd-wait-online.service
sudo systemctl mask systemd-networkd-wait-online.service