問題
學校有兩個網絡,我電腦網線插在同一個交換機的同一個接口上,有時候獲取的是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