跳过正文
  1. 博客/

NetworkManager 的 DHCP 选择

·186 字·1 分钟·
DHCP NetworkManager Systemd

NetworkManager (接下来下面将简称 nm) 的 [main] 配置块中,可以选择不同的几种 DHCP Client 实现:

  • dhclient
  • dhcpcd
  • internal

来自 man NetworkManager.conf,发行版AlmaLinux 9,版本: nmcli tool,version 1.44.0-3.el9

配置未指定的情况下默认使用 internal,而前面 2 种都需要额外安装二进制:

Client Distro / OS family Package
dhclient C9S (CentOS Stream 9) dhcp-client
dhclient Debian isc-dhcp-client
dhcpcd C9S (CentOS Stream 9) dhcpcd
dhcpcd Debian 12 dhcpcd
dhcpcd Ubuntu 22 dhcpcd5

internal 不依赖任何外部二进制,因为它是 nm 自己内部代码实现的。也就意味着在系统中不会存在由 nm fork 出的其他 DHCP Client 进程。

但是这个实现的具体情况有一个隐藏的秘密。如果你有幸使用 debug 输出对 nm 进行过调试,就可以在 DHCP 环节通过日志输出发现这个秘密:internal 有两个别名,systemd,或者 libsystemd。

是的,实际上,这些代码是来自于 systemd,对应 nm 的源代码目录中的 README 也指明了这点。

libnm-systemd-core

以 nm 的 DHCPv6 功能来说,对应 systemd 的代码可以追溯至 sd-dhcp6-client.c

通过 src/libnm-systemd-shared/README.md 的说明,可以看见 systemd 的对应代码是通过一种比较奇怪的工程实践导入进 nm 的 git 仓库的:从源仓库 clone 后再由脚本复制指定文件。由于我并没有 C++ 工程的实际经验,我也不好评价,但是对此最直观的感受就是:这让对应代码溯源变得较为困难,只能找到对应的 commit内容 才能知道上游 systemd 的代码具体对应关系。

注意COMMIT变量

正如文章最开始所展示的 man page 图中说的那样,internal 的实现不如其他外部实现的 featureful。甚至可以说 systemd 的这些实现还存在很多的改进空间,与现实世界那些林林总总的 DHCP Server 实现稍微有点不兼容,有时会发生一些意想不到的问题。

比如这个 Issue: DHCPv6 client ignores packets with invalid bytes at the end,描述了在 Oracle 云上的基础设施中,其 VPC 网关实现的 DHCPv6 Reply 消息中尾部含有非法字节,被 systemd 认为是 bad msg,导致 IPv6 的 DHCP 失败。

比较有意思的是,在 systemd PR 修正后,评论中有人反馈说 Oracle 在最初建议绕过这个问题(让客户不要使用 DHCP)后,在无法知晓的具体时间段悄悄完成了修复。

我为什么会挖掘并知道这些没用的知识?

因为我在华为云也碰见了类似的问题。一样是 IPv6 环境下的 DHCP 无法正常获取 IP,在对 nm 开启 debug 后同样看见了对 reply msg 判断为 bad msg 的信息。

就在我对 nm 的 DHCP 进行了上述情况的粗略挖掘,正准备进行下一步行动时,与同事闲聊了这个意外情况,然后就被其告知了华为云官网的文档链接,其中存在指出在 nm 的 DHCP 配置使用 dhclient 的明确指引段落。尝试了使用 dhclient 后一切正常。

所以,我个人的建议是,如果你也碰到了 nm 在 DHCP 场景下的问题,可以尝试配置使用 dhclient

或者尽量一开始就不用 internal 这个可能存在问题的代码实现,直到 Red Hat 某日在其未来的 C10SC11S 中将默认的网络管理器设置为 systemd-networkd 的那天。