麒麟服务器DHCP服务配置排障:从dhcpd.conf到跨网段中继 1. 第二篇要解决的核心问题从“装完包”到“真正发地址”在麒麟服务器操作系统上安装 DHCP 服务第一篇里我们已经把软件包装好、样例配置文件复制到位服务也尝试启动过。很多人到这儿就以为收工了结果把客户端一接屏幕上跳出 169.254 开头的地址或者干脆一直转圈 – 这说明 DHCP 服务在麒麟服务器操作系统上虽然“活着”但并没有真正“干活”。第二篇要干的就是把这条链路从服务进程、配置文件、网卡监听、安全策略、租约池一直打通到客户端拿到 IP 的最后一米。这篇内容适合三类人一是刚接手内网运维、第一次在麒麟服务器操作系统上部署 DHCP 服务的新手二是已经装完但被No subnet declaration之类报错卡住的人三是准备把 DHCP 从单网段小机房扩展到多网段、需要处理中继和地址池规划的老手。单网段的读者可以只看前四章跨网段的直接跳到第五章。所有命令都在麒麟服务器操作系统的 V10 系列上验证过配置思路对同类 RHEL 系发行版同样通用。我先把最容易踩的坑摆前面DHCP 服务在麒麟服务器操作系统上的失败九成不是软件本身的问题而是配置文件里写的网段和服务器网卡实际网段对不上或者防火墙把 67 端口的 UDP 包拦了。这两件事占了我处理过的故障里的大半。2. dhcpd.conf 配置文件逐行拆解2.1 全局段与 subnet 段的继承关系先搞懂再动手改/etc/dhcp/dhcpd.conf这个文件采用“作用域继承”的写法写在文件最顶层、不属于任何subnet块的参数是全局默认值下面每个subnet块没重新定义时就自动继承全局的设定。这个机制决定了你改参数该改哪里 – 想让所有网段都生效的写全局只想对某个网段生效的写进对应subnet块。举个实际例子全局写了default-lease-time 21600;某个访客网段的subnet块里写了default-lease-time 3600;那么访客网段租约一小时其他网段还是六小时。很多人把参数堆在全局里结果某个特殊网段没法单独调只能把整份配置拆成两份服务实例白白增加维护成本。还有一点必须强调subnet块里的网段声明必须和服务器上某块网卡实际配置的网段一致或者至少是服务器能路由到达、并且你明确要提供服务的网段。麒麟服务器操作系统上 dhcpd 启动时会扫描本机所有网卡的地址如果收到的请求来自一个没有任何subnet声明的网段它不会去猜而是直接打一条No subnet declaration for xxx的日志然后拒绝服务。这条报错我在新手环境里见得太多了。提示改配置前先执行cp /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.bakDHCP 配错会导致整个网段的终端上不了网回滚速度比排错速度重要。2.2 六个必须手工确认的参数一个都不能含糊样例文件里参数一大堆实际必须你亲手确认的就六个其余保持默认基本无害。下面这张表是我自己部署时的检查清单每次改完配置照着过一遍。参数作用常见取值写错的后果subnet/netmask声明服务网段与网卡一致服务拒绝对该网段分配range可分配地址区间避开静态段把服务器地址发出去造成冲突option routers下发的网关网关真实地址客户端能通内网不能出外网option domain-name-servers下发的 DNS1~2 个内网 DNS能上网但域名解析全挂default-lease-time默认租期秒21600~86400过短导致续租风暴max-lease-time最大租期秒不小于默认值客户端请求长租期被拒range这一段我建议永远手动分段而不是一整段拉到底。比如地址段 192.168.10.100 到 192.168.10.200我一般写成两段中间留口子把 .150 到 .159 空出来给打印机、监控设备这些需要固定但又不方便走静态绑定的设备。这样一来即使后来有人手动设了固定 IP 撞进池子也有缓冲带。default-lease-time的取值要看场景办公网终端流动性小设 4320012 小时甚至 8640024 小时都行能显著减少续租报文无线访客网、会议室网这种终端数量波动大的设 3600 到 7200 更合适地址回收快。我试过在会议室网设 24 小时租期三天后地址池被几百台只来过一次的笔记本占满只能手动清租约文件那滋味不好受。2.3 一份可直接抄改的多网段配置样例下面这份配置是两网段场景网卡分别是 192.168.10.1/24办公和 192.168.20.1/24访客改动量最小直接换地址就能用。# 全局默认值所有 subnet 未覆盖时生效 option domain-name lab.internal; option domain-name-servers 192.168.10.2, 192.168.10.3; default-lease-time 43200; max-lease-time 86400; authoritative; log-facility local7; # 办公网租期长池子避开服务器段 subnet 192.168.10.0 netmask 255.255.255.0 { range 192.168.10.100 192.168.10.199; option routers 192.168.10.1; } # 访客网租期短DNS 用同一个 subnet 192.168.20.0 netmask 255.255.255.0 { range 192.168.20.50 192.168.20.240; option routers 192.168.20.1; default-lease-time 3600; max-lease-time 7200; } # 静态绑定示例网络打印机 host printer-01 { hardware ethernet 00:1b:21:aa:bb:cc; fixed-address 192.168.10.20; }authoritative;这行值得单独说。加上它dhcpd 对来自已知网段但请求地址不可用的客户端会直接回 NAK让客户端立刻重来不加的话它会沉默客户端要等到超时才重试用户体感就是“开机要等半分钟才有网”。单服务器环境基本都该加只有主备双机或者有多台 DHCP 服务器抢答的复杂场景才需要斟酌。改完不要急着重启先跑配置语法检查dhcpd -t -cf /etc/dhcp/dhcpd.conf这条命令只解析配置不启动服务报错会精确到行号。我踩过的坑是中文注释里的全角标点混进参数行dhcpd -t一跑就现形比看日志快得多。3. 服务启动、开机自启与外设环境处理3.1 systemd 下的正确启动姿势麒麟服务器操作系统用 systemd 管服务单元名是dhcpd。标准的启动和自启操作如下systemctl start dhcpd systemctl enable dhcpd systemctl status dhcpdstatus的输出必须盯紧两点一是Active那行是不是active (running)而不是failed二是最下面几行日志有没有No subnet declaration或Not searching LDAP这类被视为正常的提示。很多人只看第一行绿色的 running 就认为没问题其实服务可能在监听但配置里没有可用网段等同于不工作。如果启动失败第一手资料不是猜而是这两条命令journalctl -u dhcpd -n 50 --no-pager dhcpd -t -cf /etc/dhcp/dhcpd.conf麒麟服务器操作系统默认启用了 systemd-journaldjournalctl -u dhcpd能把本次启动的完整日志拉出来。配置语法问题、端口占用问题、权限问题在日志里都会有明确指向。我遇到过一次启动失败原因很隐蔽同事把dhcpd.leases文件用chmod 644改成了所有人可读SELinux 上下文被一并改掉dhcpd 写不进去直接退出日志里只有一行Cant open lease database。另外要留意dhcpd首次启动时需要一个可写的租约文件。RHEL 系路径是/var/lib/dhcpd/dhcpd.leases麒麟服务器操作系统沿用了这个约定。如果这个文件不存在部分版本的 dhcpd 不会自动创建而是直接报错手动touch一个空文件再启动最保险touch /var/lib/dhcpd/dhcpd.leases chown dhcpd:dhcpd /var/lib/dhcpd/dhcpd.leases chmod 644 /var/lib/dhcpd/dhcpd.leases3.2 防火墙与安全模块的放行别让包死在半路麒麟服务器操作系统默认启用 firewalld。DHCP 服务端只监听 UDP 67客户端是 UDP 68服务的防火墙规则必须放行 67。firewall-cmd --permanent --add-servicedhcp firewall-cmd --reload firewall-cmd --list-services用--add-servicedhcp而不是直接开端口好处是规则带语义日后审计一眼能看懂。如果所在环境把服务名精简掉了等价写法是firewall-cmd --permanent --add-port67/udp这里有个反直觉的点如果你和客户端在同一台机器上测服务端自己发请求流量走的是本地回环防火墙根本不参与会出现“本机测正常、别的机器拿不到”的假象。所以功能验证一定要用另一台机器做客户端别用本机自测下结论。SELinux 方面麒麟服务器操作系统默认是 enforcing。绝大多数情况下 dhcpd 的默认策略是够用的不需要额外开关。真遇到服务起不来又怀疑 SELinux用这条命令查最近的拒绝记录ausearch -m avc -ts recent如果确实有和 dhcpd 相关的 AVC 拒绝先想清楚是不是自己把配置文件或租约文件放到了非标准路径 – 是的话规范回去比改策略更省事。我个人的原则是能用标准路径解决的绝不去动 SELinux 布尔值那玩意儿改多了后患无穷。3.3 多网卡监听收敛避免服务到处应答服务器往往不止一块网卡一块业务网、一块管理网、一块存储网。dhcpd 默认会在所有配置了地址的网卡上监听这意味着管理网里的机器也可能收到它发的地址这在严格分域的机房里是不允许的。最简单的收敛办法是改/etc/sysconfig/dhcpdDHCPDARGSens192多个接口用空格分隔。改完重启服务dhcpd 就只在指定网卡上应答。这个文件在麒麟服务器操作系统上同样存在属于 systemd 单元的环境变量来源。另一种方式是在配置文件里用subnet声明来间接控制 – 只有声明了subnet的网段才会被服务。但这种方式在“网卡有地址但我不想服务”的场景下无效因为 dhcpd 仍会尝试匹配。所以我的做法是两手都上subnet只写要服务的网段DHCPDARGS再收一层双保险。顺带说一句网卡命名。麒麟服务器操作系统默认走一致性网络设备命名接口名可能是ens192、eno1这种。查当前接口名用ip -br addr比ifconfig清楚得多而且不用额外装包。ip -br addr输出里能看到每个接口的状态、地址和网段配subnet前先照这个核对一遍能省掉大量“明明配了却不生效”的困惑。4. 租约、静态绑定与地址池运维4.1 读懂 dhcpd.leases排障的第一现场租约文件/var/lib/dhcpd/dhcpd.leases记录了每一个发出去的地址是判断“到底有没有发出去”的唯一权威依据。它的格式长这样lease 192.168.10.105 { starts 1 2025/03/10 09:12:33; ends 1 2025/03/10 21:12:33; cltt 1 2025/03/10 09:12:33; binding state active; next binding state free; hardware ethernet 00:0c:29:1a:2b:3c; uid \001\000\014\051\032\053\074; client-hostname test-pc; }看这个文件有几个要点。starts后面的第一个数字是星期几0 代表周日1 代表周一不是月份也不是序号第一次看很容易蒙。binding state有active、free、backup几种free表示租约已释放或过期可以重用。client-hostname是客户端自己报上来的名字不一定可信但排查时非常有用 – 一眼就能看出这条租约是给谁的。实操中最常用的动作是查某个 MAC 有没有拿到地址grep -i 00:0c:29:1a:2b:3c /var/lib/dhcpd/dhcpd.leases能查到说明服务端确实发了问题在客户端或链路上查不到问题在服务端这一侧。这一个判断就能把排查范围砍掉一半。注意绝对不要手工编辑租约文件。dhcpd 启动时会读取它格式错一个字符就可能起不来。要清理租约标准做法是停服务、备份后删除、重启服务让它重建或者用dhcpd自带的omshell接口操作。4.2 静态绑定的两种写法各有各的适用场景DHCP 里给设备固定地址有两条路一种是在subnet块外面用host声明绑 MAC另一种是把地址从动态池里排除掉、客户端自己配静态 IP。两者不是竞争关系混着用才合理。host绑定的写法前面样例已经给了要注意三个细节。第一fixed-address必须落在某个已声明的subnet范围内否则服务启动就报错。第二host块可以写在文件任意位置但习惯上放在对应subnet块后面方便日后阅读。第三被绑定的地址一定要从range里排除虽然 dhcpd 内部会做冲突检测但排除掉能省掉一次无谓的 ping 探测也让配置意图更清晰。哪些设备适合host绑定打印机、网络摄像头、门禁控制器、AP 管理地址这类需要固定地址、但设备本身不一定方便进后台改配置的。哪些适合手工静态服务器、交换机、路由器这类本来就要人工管理、配置文档里必须写死的。一个实操心得host名字不要用中文、不要带空格用纯小写英文加短横线比如printer-3f-01。我在一个环境里见过用中文主机名绑定的配置后来换版本升级时字符编码处理不一致整个文件解析报错排查了半天才发现是名字的问题。4.3 地址池容量怎么估别等池子满了才想起来地址池大小的估算核心不是看网段里有多少个地址而是看“同时在线的终端峰值”和“租约时长”这两个变量。粗略算法所需池子大小 ≈ 峰值在线终端数 × 1.2 ~ 1.5乘的这个系数用来兜住“刚下线的设备租约还没到期、新设备又来了”的重叠期。具体到一栋办公楼常驻办公终端 150 台每天外来笔记本和手机约 80 台峰值在线 230 台左右那池子留 300 个地址比较稳。再往下算要看租约时长。假设default-lease-time是 12 小时一个终端一天大约占一个地址外来设备当天走、当天释放重叠有限假设租期是 7 天那外来设备走了地址还占着实际需要的池子要大得多。我的经验值是租期不超过 12 小时的系数取 1.2租期 24 小时以上的系数取 1.5 甚至更高。一个 /24 网段可用地址 254 个去掉网关、服务器、网络设备、保留段实际能用于动态分配的往往只有 200 上下。如果你的峰值终端数逼近这个数别硬撑尽早规划拆网段或者扩掩码。扩掩码这件事牵一发动全身网关、静态路由、ACL 都要跟着改等池子满了再动手就是事故了。查看当前池子使用率的土办法是数租约文件grep -c binding state active /var/lib/dhcpd/dhcpd.leases这个数字对上池子总量使用率超过 80% 就该预警了。想更精细的话可以配合日志统计每天的发号量journalctl -u dhcpd --since 1 day ago | grep -c DHCPACK能看出实际的发号频率。5. 跨网段DHCP 中继的落地细节5.1 中继为什么必须存在广播到不了的地方就得靠人搬DHCP 客户端发现地址的方式是广播源地址 0.0.0.0、目的地址 255.255.255.255。广播包天然过不了路由器这是设计使然不是配置问题。所以当你的 DHCP 服务器在 192.168.10.0/24而终端在 192.168.20.0/24 时服务器的广播根本传不过去客户端只能一直等。解决办法就是中继由网关设备把客户端的广播请求“单播”转发给 DHCP 服务器服务器处理完再把应答单播回给中继中继再广播给客户端。整个过程中继扮演了“传话人”的角色。这也是为什么中继设备的那个接口地址会出现在服务器收到的请求里作为giaddr字段 – 服务器就是靠这个字段判断该从哪个subnet块里分配地址。理解了giaddr很多疑惑就通了。比如你明明在 20 网段配了中继服务器却报没有可用地址多半是服务器上没有 192.168.20.0/24 的subnet声明或者声明了但range写错了。再比如一台服务器同时服务多个网段靠的就是每个网段都有独立的中继指向它而不是服务器去扫网段。5.2 中继的两种实现路径与配置要点中继有两种做法一种在交换机或路由器上开 DHCP Relay 功能一种是在麒麟服务器操作系统上用dhcrelay软件包做软中继。前者性能好、不占服务器资源是首选后者适合交换机不支持中继、或者临时验证的场景。软中继的安装和启动yum install -y dhcp # dhcrelay 包含在 dhcp 包里 dhcrelay -i ens224 192.168.10.1-i指定朝向客户端那一侧的接口后面的地址是 DHCP 服务器地址。多服务器可以用多个地址做冗余。实际生产环境要用 systemd 单元管理配置文件在/etc/sysconfig/dhcrelay把参数写进去再systemctl enable --now dhcrelay避免重启丢失。服务器侧要做两件事配合。一是配置文件里补上中继所在网段的subnet声明range、routers、DNS 都要写全这一段的网关填中继设备的接口地址也就是客户端真正的网关。二是确认服务器能路由到中继网段 – 用ping或ip route get确认不通的话中继发来的单播包一样进不来。ip route get 192.168.20.1交换机侧的中继配置因厂商而异思路都一样指定 DHCP 服务器地址指定要中继的接口或 VLAN。这里有个容易忽略的点 – 如果中继口配的是ip helper-address之类注意别把服务器的地址写错了也别把多个 VLAN 的中继都指向同一个服务器却没在服务器上补对应subnet那结果就是部分网段能拿到、部分拿不到排查时容易怀疑人生。还有一个实操细节中继场景下客户端的续租请求RENEW是单播到原服务器地址的不经过中继。如果客户端后来换了网段续租会失败并重新走 DISCOVER这个行为是正常的不用当成故障。日志里看到DHCPREQUEST后跟DHCPNAK再跟DHCPDISCOVER多数就是这类情况。6. 故障排查实录与高频问题速查6.1 客户端拿不到地址按这四步往下切排障最忌讳一上来就改配置。我自己的顺序是固定的四步能把问题范围快速压实。第一步看服务端有没有收到请求。在服务器上抓包tcpdump -i ens192 -n port 67 or port 68如果抓不到任何包问题在链路、中继、防火墙或者客户端网卡本身跟配置无关。抓到了 DISCOVER 但没有 OFFER说明是服务端配置或地址池的问题。第二步看服务端日志。journalctl -u dhcpd -f一条正常的分配过程在日志里是四行DHCPDISCOVER from mac、DHCPOFFER on ip to mac、DHCPREQUEST for ip from mac、DHCPACK on ip to mac。断在哪一步问题就在哪一步。收到 DISCOVER 但没 OFFER基本就是没有匹配的subnet或者池子耗尽。第三步看租约文件确认结果。grep -i 客户端mac /var/lib/dhcpd/dhcpd.leases有active记录但客户端没拿到问题在返回路径 – 防火墙、中继回程路由、客户端侧防火墙都有可能。第四步客户端侧验证。Linux 客户端用dhclient -v看交互过程Windows 客户端用ipconfig /release再ipconfig /renewWindows 的ipconfig /all能看到是不是拿到了 169.254 的自分配地址 – 只要看到 169.254 开头就是完全没拿到服务端的响应。这四步下来九成问题能定位到具体环节剩下的再深挖配置细节。6.2 地址冲突与重复分配最让人头疼的一类地址冲突有两种成因要分开处理。第一种是池子里有设备手工配了静态 IP。这种情况表现为日志里出现DHCPDISCOVER from mac ... ICMP echo reply之类的探测告警或者是客户端拿到地址后报“IP 冲突”。dhcpd 默认在分配前会 ping 一下目标地址有人应答就跳过这个地址。这个机制能兜底但会拖慢分配速度也让状态变得不可预测。根治办法只有两个要么把手工静态设备的地址从range里彻底排除要么把手工静态设备统一改成host绑定。第二种是同一个 MAC 拿到多个地址或者两台设备拿到同一个地址。前者常见于虚拟化环境虚拟机克隆后 MAC 没改两台虚机用同一个 MAC 请求服务端按 MAC 记录租约就会串。后者在多台 DHCP 服务器共存、但没做租约同步的环境里会出现表现是客户端反复跳地址。多服务器场景要上failover机制或做严格的分池隔离这件事不适合临时上要提前规划。还有一种隐蔽的冲突老设备关机前没释放租约新设备被分配到同一地址结果老设备一开机就撞。这种情况下default-lease-time设得太长会加剧问题适当缩短租期、或者在维护窗口重建设备租约能缓解。6.3 高频问题速查表照着查比翻日志快现象最可能原因快速验证处理办法服务启动失败配置语法错dhcpd -t -cf /etc/dhcp/dhcpd.conf按行号改语法日志报No subnet declaration无对应网段声明ip -br addr对比配置补subnet块客户端一直 169.25467 端口被拦服务端tcpdump抓包firewall-cmd放行能拿到 IP 但上不了网网关或 DNS 没下发客户端ip route、查 DNS补option routers/ DNS池子耗尽range太小或租期太长数租约文件 active 数扩池或缩短租期跨网段不生效缺中继或subnet未声明抓包看有无giaddr配中继并补声明租约文件写不进去权限或 SELinux 上下文ls -lZ /var/lib/dhcpd/改回dhcpd属主 644某些设备拿不到、某些正常host绑定地址在池内比对fixed-address与range从池中排除该地址最后分享一个我在实际环境里养成的习惯每次改完dhcpd.conf先跑语法检查再把关键改动点用diff -u对照备份打印一遍最后才重启。DHCP 这个服务的性质决定了它一旦出问题就是整个网段受影响多花两分钟做校验比事后在几百台机器面前解释要轻松得多。另外租约文件别当垃圾定期删它是你回溯问题的黑匣子容量很小留着比清掉有用。很多在麒麟服务器操作系统上装 DHCP 卡住的人最终发现问题都不在“装”这一步而在网段声明、防火墙、池子规划这些细枝末节上。把这些细节按顺序捋一遍服务就能稳稳当当跑起来。