
手工配 IP 的网段迟早会撞地址。DHCP 把地址与网络参数集中到一台服务器上发客户端开机即用。这篇先把 DORA 四步握手里每个报文的源地址、目的地址与广播方式讲清再说租约到期前后客户端做了什么然后给出完整的服务端与客户端配置最后处理固定 IP、多服务器冲突、跨网段中继三个常见场景。文中命令名与选项均注明英文原意完整清单见文末《附命令英文全称速查表》。本文概要项目内容文章主题DHCPv4 地址自动分配DORA 握手 → 租约与续约 → 服务端 / 客户端配置 → 固定 IP、权威性、中继所属类别Linux 系统管理 → 网络服务 → DHCP知识关键字DHCPv4·dhcpd·dhcpd.conf·dhclient·nmcli·DORA·lease·range·authoritative·relay概念图给出「客户端没地址 → 服务器集中分配 → 拿到 IP 与全套参数」的主链路。概要表里的关键字分别落在服务定位与两种协议在第一章。通信过程与租约在第二章服务器部署在第三章客户端配置在第四章三个进阶场景在第五、六、七章。本文的机器与地址约定服务端zhb-s110.1.8.100客户端zhb-m110.1.8.10网关10.1.8.2域名zhb.cloud。文中的课堂抓包截图拍摄时服务器地址为10.1.8.10与本篇统一后的10.1.8.100是同一台机器流程一致。一、DHCP 解决什么问题1.1 静态分配的三个麻烦在大型网络里手工分配 IP会同时撞上三个问题地址冲突防不住。没人能保证同一个地址没被别的机器用掉全靠人工登记表每台新机器都要手工配。装一台改一次装一百台改一百次改一处要改一圈。网关、DNS 换了得逐台登录去改。1.2 DHCP 能自动下发什么动态主机配置协议DynamicHostConfigurationProtocolDHCP提供了一种自动配置网络参数的方法。它下发的参数包括 IP 地址、子网掩码、默认网关、DNS 服务器、域名、NTP 服务器。参数集中一处管改动即时生效。1.3 DHCPv4 与 DHCPv6DHCP 有两个互不兼容的协议族协议服务对象说明DHCPv4IPv4 网络本篇只讲这一种DHCPv6IPv6 网络地址空间、报文格式、服务器实现都不同服务端与客户端的角色是分开的一台服务器需要固定的、静态的 IP 地址它得先有身份才能发地址客户端则不需要。二、DHCP 的通信过程2.1 四步握手DORA客户端拿到地址要来回四趟取四个报文的字头就是DORA步骤报文方向这一步在干什么①DHCPDISCOVER客户端 → 服务器广播喊话谁是 DHCP 服务器给我个地址②DHCPOFFER服务器 → 客户端服务器应答这个地址给你租期这么长网关 DNS 是这些③REQUEST客户端 → 服务器客户端选定其中一台广播声明「我要用这台给的地址」④ACK服务器 → 客户端确认独占租期从这一刻开始计时客户端用 DHCPv4 配置网卡时DHCPDISCOVER 报文会发往广播地址255.255.255.255。路由器通常不转发这个广播地址所以DHCP 服务器必须和客户端在同一个物理网络要跨网段就得把路由器配成 DHCP 中继代理见第七章。2.2 每一步的源地址、目的地址与端口DHCP 走 UDP客户端发给服务器的报文目的端口是67服务器回给客户端的报文目的端口是68。地址一栏的规律是客户端在拿到地址之前源地址只能填 0.0.0.0。步骤源地址 → 目的地址端口方式DHCPDISCOVER0.0.0.0→255.255.255.25568 → 67广播DHCPOFFER服务器 IP → 广播或客户端地址67 → 68广播或单播DHCPREQUEST0.0.0.0→255.255.255.25568 → 67广播DHCPACK服务器 IP → 客户端地址67 → 68广播或单播抓包验证tcpdump或 Wireshark过滤bootp或dhcp四个报文的Transaction ID 完全相同这是串起一次会话的线索——网段里如果有多台服务器就靠它区分哪些报文属于同一次会话。2.3 第三步为什么还要广播客户端已经知道该找哪台服务器了DHCPREQUEST 却依然广播看着很浪费。原因是网段里可能有多台DHCP 服务器。客户端只接受其中一家的配置但其余服务器已经把地址预留出来了。必须让它们听到这次广播才能把预留给该客户端的地址释放回去。所以 DHCPREQUEST 的报文里同时带了「选中的服务器标识」和「请求的地址」。前者告诉被选中的那台「就是你」后者告诉其它服务器「别留着我的地址了」。2.4 租约与续约分到手的地址不是永久的而是一份租约lease。客户端在租期内独占该地址到期前必须续约否则地址会被收回。客户端手里有两个定时器T1 到期进入 RENEWING 状态只向当初分配地址的那台服务器单播续约T2 到期进入 REBINDING 状态改用广播网段里任何一台 DHCP 服务器都可以接管。两个状态名出自 RFC 2131 的客户端状态机。图上节点的位置是示意实际时刻由客户端的定时器决定也可以由服务端用 option 58 / 59 指定。续约成功的抓包⚠️注意租约到期前客户端会定期向服务器发 DHCPREQUEST确保服务器不会把地址收回去。如果一直续不上走到租约终点客户端就必须释放地址下次联网得从头再走一遍 DORA。2.5 在服务器上查日志DHCP 服务器的所有分配动作都会写进系统日志出问题先看这里# 跟踪 dhcpd 服务的日志[rootzhb-s1 ~]# journalctl --unitdhcpd.service# 或者看通用日志CentOS 7 系[rootzhb-s1 ~]# tail -f /var/log/messages一次完整分配在日志里长这样DHCPDISCOVER from 00:0c:29:26:13:b5 via ens160 DHCPOFFER on 10.1.8.101 to 00:0c:29:26:13:b5 (zhb-m1) via ens160 DHCPREQUEST for 10.1.8.101 (10.1.8.100) from 00:0c:29:26:13:b5 (zhb-m1) via ens160 DHCPACK on 10.1.8.101 to 00:0c:29:26:13:b5 (zhb-m1) via ens160四行对应 DORA 四步。DHCPREQUEST 那行括号里的10.1.8.100是客户端这次请求指向的服务器地址——多台服务器共存时这一栏是判断「客户端最终选了谁」的关键。三、部署 DHCP 服务器3.1 装前检查两件事必须先确认。网卡要有 BROADCAST 标志、并且配了广播地址[rootzhb-s1 ~]# ip addr2: ens160:BROADCAST,MULTICAST,UP,LOWER_UPmtu1500qdisc pfifo_fast state UP group default qlen1000link/ether 00:0c:29:e5:be:0f brd ff:ff:ff:ff:ff:ff inet10.1.8.100/24 brd10.1.8.255 scope global ens160...BROADCAST...和brd 10.1.8.255都要有否则服务器发不出广播响应。服务器必须是静态 IPDHCP 服务器自己要是靠 DHCP 拿地址就会陷入「先有鸡还是先有蛋」的死循环。3.2 安装软件包与放行防火墙# 安装 dhcp 服务端软件包[rootzhb-s1 ~]# yum install -y dhcp# 放行 dhcp 服务运行态 永久态各写一条[rootzhb-s1 ~]# firewall-cmd --add-servicedhcp[rootzhb-s1 ~]# firewall-cmd --add-servicedhcp --permanent⚠️注意--permanent只写配置文件不加它的那条才立即生效。两条都要敲否则重启后要么丢配置、要么当前不生效。3.3 配置文件与常用参数服务端的配置文件是/etc/dhcp/dhcpd.conf。dhcp软件包自带一份示例复制过来改比从零写好[rootzhb-s1 ~]# /bin/cp /usr/share/doc/dhcp-*/dhcpd.conf.example /etc/dhcp/dhcpd.conf[rootzhb-s1 ~]# vim /etc/dhcp/dhcpd.conf一份能用的最小配置subnet 10.1.8.0 netmask 255.255.255.0 { range 10.1.8.101 10.1.8.130; option domain-name-servers 223.5.5.5; option domain-name zhb.cloud; option routers 10.1.8.2; option broadcast-address 10.1.8.255; default-lease-time 600; max-lease-time 7200; }dhcpd.conf 参数说明参数含义英文原意authoritative声明本机对该子网具有权威性遇到不认识的地址请求直接回 DHCPNAKauthoritative权威的subnet … netmask …声明要服务的子网必须以网络地址与掩码成对出现subnet子网netmask子网掩码range 起始 结束可分配的地址池范围range范围option routers下发的默认网关routers路由器即网关option domain-name-servers下发的 DNS 服务器domain name servers域名服务器option domain-name下发的域名后缀domain name域名option domain-search下发的域名搜索列表可写多个域domain search域搜索option broadcast-address下发的广播地址broadcast address广播地址default-lease-time默认租期客户端没特别要求时按它算单位秒default lease time默认租用时长max-lease-time能接受的最长租期客户端要得更久也不给单位秒maximum lease time最长租用时长客户端系统上的 NetworkManager 会拿domain-name-servers和domain-search去更新resolv.conf的nameserver与search两行。3.4 校验配置语法改完先验证再重启否则语法错误会让服务直接起不来[rootzhb-s1 ~]# dhcpd -tInternet Systems Consortium DHCP Server4.2.5 Copyright2004-2013 Internet Systems Consortium. All rights reserved.... Not searching LDAP since ldap-server, ldap-port and ldap-base-dn were not specifiedinthe configfiledhcpd 参数说明参数含义英文原意-t只做配置文件语法检查不做任何网络操作test-T检查租约文件语法Test lease-4作为 DHCPv4 服务器运行默认即此与-6互斥IPv4-6作为 DHCPv6 服务器运行IPv6-p 端口修改监听 UDP 端口默认 67多用于调试port-f前台运行不转入后台foreground-d把日志打到标准错误调试与 syslog 不可靠时用debug-cf 文件指定备用配置文件configfile-lf 文件指定备用租约文件leasefile-pf 文件指定备用 PID 文件pidfile3.5 启用并启动服务# 设为开机自启并立刻启动[rootzhb-s1 ~]# systemctl enable dhcpd --now# 查看状态[rootzhb-s1 ~]# systemctl status dhcpdsystemctl enable --now等于「enable设开机自启」「start立刻启动」两条命令合一。3.6 查看租约记录日志看过程租约文件看结果——它记录着当前发出去了哪些地址、租到什么时候、对应哪块网卡# 日志实时看分配、报错、地址冲突、授权问题[rootzhb-s1 ~]# tail -f /var/log/messages# 租约库看已分配 IP、租期、客户端 MAC[rootzhb-s1 ~]# cat /var/lib/dhcpd/dhcpd.leases四、配置 DHCP 客户端4.1 用 nmcli 建一个自动获取的连接# 新建一个动态连接假设网卡为 ens192[rootzhb-m1 ~]# nmcli connection add con-name dynamic type ethernet ifname ens192# 激活它[rootzhb-m1 ~]# nmcli connection up dynamic# 验证[rootzhb-m1 ~]# ip addr show ens192link/ether 00:0c:29:26:13:b5 brd ff:ff:ff:ff:ff:ff inet10.1.8.101/24 brd10.1.8.255 scope global dynamic noprefixroute ens192 valid_lft 597sec preferred_lft 597secinet那行有两个信号说明地址是 DHCP 来的dynamic字样以及valid_lft 597sec这段剩余租期——刚拿到时接近租期上限600 秒会一路倒数。nmcli connection 参数说明参数含义英文原意connection操作对象是「连接」一套网卡配置而非设备本身connection连接add新建连接add新增up/down激活 / 停用连接up / down启用 / 停用modify修改已有连接的属性modify修改con-name连接的名称自定义connectionname连接名type连接类型ethernet表示有线以太网type类型ifname绑定的网卡设备名interfacename接口名ipv4.dns该连接的 DNS 服务器地址IPv4 DNSipv4.method auto用 DHCP 自动获取手动配则写manualmethod方式4.2 dhclient 手动管理租约dhclient是命令行 DHCP 客户端用来手动释放、重新申请地址排查「客户端到底发没发出请求」时很好用# 释放当前 DHCP 拿到的地址[rootzhb-m1 ~]# dhclient -r ens192# 重新申请并打印过程[rootzhb-m1 ~]# dhclient -v ens192dhclient 参数说明参数含义英文原意-r释放当前租约并停掉 dhclient 进程release释放-x只停掉 dhclient 进程不释放租约exit退出-v打开详细日志verbose啰嗦模式-1只尝试一次失败就以退出码 2 结束1try-4/-6指定用 DHCPv4 / DHCPv6IPv4/ IPv6-p 端口修改客户端监听与发送的 UDP 端口默认 68port-s 服务器指定先向哪台服务器发请求默认打到 255.255.255.255server-d前台运行隐含-v便于调试debug-q启动时不打印多余信息默认行为quiet-nw立即转入后台不等拿到地址nowait-w找不到可用的广播接口时也不退出wait-n不配置任何接口常与-w搭配no configure-e 变量值为 dhclient-script 追加环境变量可写多次environment-cf 文件指定备用配置文件configfile-lf 文件指定备用租约文件leasefile-pf 文件指定备用 PID 文件pidfile提示-r与-x的差别值得记牢——-r会通知服务器把地址收回去-x只是把本地进程杀掉、服务器那边租约照旧占着。想干净地交还地址用-r。五、按 MAC 地址固定 IP地址池分配适合普通终端但 Web、数据库这类服务器需要每次都拿到同一个地址。host声明就是干这个的把 MAC 地址绑定到固定 IP。先查客户端的 MAC[rootzhb-m1 ~]# ip link show ens192link/ether 00:0c:29:26:13:b5 brd ff:ff:ff:ff:ff:ff在/etc/dhcp/dhcpd.conf末尾追加host zhb-m1.zhb.cloud { hardware ethernet 00:0c:29:26:13:b5; fixed-address 10.1.8.30; }参数含义英文原意host 名称 { }为单台主机单独声明配置host主机hardware ethernet MAC绑定客户端的网卡 MAC 地址hardware ethernet以太网硬件地址fixed-address 地址固定分配给它的 IP注意不要落在 range 地址池里fixed address固定地址重启服务并验证[rootzhb-s1 ~]# systemctl restart dhcpd# 客户端重新激活连接[rootzhb-m1 ~]# nmcli connection up dynamic[rootzhb-m1 ~]# ip addr show ens192inet10.1.8.30/24 brd10.1.8.255 scope global dynamic noprefixroute ens192地址已经变成固定的10.1.8.30。⚠️注意fixed-address必须写在地址池range之外本例池子是.101–.130固定地址给.30。写进池子里服务器会在池子扩散到该地址时把它再分给别人出现冲突。六、多台 DHCP 服务器与权威性DHCP 协议允许一个物理网络里跑多台服务器但不建议——正常情况下一个网段只需要一台应答。多台共存时会这样新客户端广播 DHCPDISCOVER可能收到多个DHCPOFFER客户端只接受其中一台的配置然后广播含该服务器 IP 的 DHCPREQUEST其余服务器听到这次广播把替该客户端预留的地址释放掉。续约场景则取决于服务器是否权威非权威服务器会忽略 DHCPREQUEST 里它不认识的地址默默不管权威服务器如果收到的地址在自己管辖范围内、但自己从没发过会拒绝并发回DHCPNAK客户端收到 DHCPNAK 后不能再使用该地址必须重新申请。所以默认配置下 dhcpd不是权威服务器这正是为了防止一台新上线的服务器抢走老服务器正在服务的地址。要在自己说了算的网段里明确表态就在subnet块里写subnet 10.1.8.0 netmask 255.255.255.0 { authoritative; ... }七、跨网段分配DHCP 中继DHCPDISCOVER 是广播包路由器默认不转发广播所以客户端和服务器不在同一个网段时请求根本到不了服务器。解决办法是把路由设备配成DHCP 中继代理relay agent。它收到本网段的 DHCP 广播后改成单播转发给远端服务器服务器再把应答交给中继由中继发回客户端。对照两张图可以看出中继的两处改写客户端侧是广播、服务器侧是单播。中继还会把自己的地址填进报文的giaddr字段服务器靠这个字段判断该从哪个网段分配地址、应答该送回哪台中继。附命令英文全称速查表命令 / 缩写英文全称 / 原意作用DHCPDynamicHostConfigurationProtocol动态主机配置协议DORADiscover ·Offer ·Request ·Ack四步握手的四个报文dhcpdDHCPdaemonDHCP 服务端守护进程dhcpd.confdhcpdconfiguration服务端配置文件dhclientDHCPclient命令行 DHCP 客户端nmcliNetworkManagercommandlineinterface网络管理命令行leaselease租约地址的有效使用期rangerange地址池范围subnetsubnet子网netmasknetworkmask子网掩码fixed-addressfixed address固定分配的地址authoritativeauthoritative权威的对子网内的地址请求直接表态relayrelay中继代理转发跨网段 DHCP 报文MACMediaAccessControl网卡硬件地址RENEWINGrenewing续约状态单播找原服务器REBINDINGrebinding重绑定状态广播找任意服务器TCP/UDPTransmissionControlProtocol /UserDatagramProtocol传输层协议DHCP 走 UDP 参考资料官方文档 · 中英双语英文原版RFC 2131Dynamic Host Configuration ProtocolDORA 四步、端口 67/68、客户端状态机dhcpd.conf(5) 手册配置文件全部指令中文版搭建 DHCP 服务器阿里云 ECS 文档其余手册在服务器上直接查不依赖网络、不占链接数man8dhcpd# 服务端选项、-t 语法校验、启动参数man5dhcpd.conf# 配置文件全部指令range / fixed-address / authoritativeman5dhcp-options# option 语句可用的全部选项含 58 / 59man8dhclient# 客户端选项-r 释放租约、-x 仅杀进程总结DHCP 这条链路的顺序是「客户端广播 DISCOVER → 服务器 OFFER → 客户端广播 REQUEST 选定 → 服务器 ACK 确认 → 租期内用到期前 T1 单播续约、T2 广播重绑定」。配置侧只有三件事要记住服务器必须是静态 IP 且在同一个广播域、fixed-address不要落进range池子、改完先dhcpd -t再重启。觉得有用可以收藏遇到过地址冲突或客户端拿不到地址的情况欢迎在评论区聊聊排查过程。