DHCP(Dynamic Host Configuration Protocol/动态主机配置协议)是到目前为止笔者接触到的比较复杂的协议,在传输过程中,DHCP有8种报文类型来实现不同的过程,而当客户端成功获取地址之后也会有多种状态的变化。因此笔者打算先从dhcp的报文入手,理清楚一台终端设备从无到有取得IP地址的过程。
为何要使用DHCP呢?首先,终端设备接入互联网一定是需要IP地址的,就像普通的电脑,而最初分配IP地址的方式就是手动输入IP地址,如有10台设备A/B/C/D…I/G那么就找出10个IP地址如192.168.0.2/3/4/5…11。只需要一对一的设定好每台设备的IP不冲突,设置好网关、掩码、dns等就可以正常上网了。笔者第一章架设linux服务器和第二章接入专网的时候都是用的这种方式。但随着接入量的增加,地址分配、更改会变得非常繁琐,有时候一个内网环境下用户接入量少则几千多则几万,这要是一个一个手动设置IP地址,工作量根本无法统计。
其实对于网管而言,哪台电脑是什么IP地址似乎并不是很重要,大多数人配置IP地址的目的也仅仅是为了上网。那么是否存在一种方式可以使得接入终端在连入互联网后可以自动获取一个IP地址,而网管可以看到一张IP对应电脑的关系表来进行维护呢?
方案上肯定是可行的,这就涉及到了IP地址的动态分配,即DHCP。如下所示是客户端一次完整的DHCP请求、续约的过程。其中涉及三次数据交互,分别为两次请求(Discover-Offer、Request-ACK)一次续约(Request-ACK)。基于这三次交互客户端就顺利获取并延续使用IP地址来访问互联网。
笔者来仔细看一下这几个请求过程:
DHCP Discover:客户端在刚接入网络时,本身是没有IP地址的,这时候,客户端需要在网络内发起一次discover的请求,这时候源地址是0.0.0.0,目的地址为255.255.255.255,来询问网络中哪台设备是dhcp server。Discover报文只是在客户端所在的子网内进行广播。
DHCP Offer:dhcp server收到客户端的discover报文后,为了响应客户端而回复一个offer报文。服务器会匹配客户端所在的子网信息后会送给客户端IP地址。并在地址池中暂时保留该地址。
DHCP Request:对于实际使用的网络,没有网络协议可以规定网络中只能有一台dhcp server。当客户端收到多个dhcp offer的时候会根据先到先得的原则从中选取最先获得的报文。之后客户端会再次广播一个名为request的报文告知所有响应的dhcp server。
DHCP ACK:dhcp server收到request报文,保留客户端ip-mac地址。
DHCP Request(Renew/ACK):当客户端到了最大租期的一半时,会向dhcp server发送一个request报文来申请续约,dhcp server给出回复(ACK)。
DHCP报文的8种类型:
经过上述步骤,客户端与服务器已经建立了连接并进行租期的续约。除了上述discover、offer、request、ack四种基础的报文类型,还有以下四种:
DHCP NAK:当DHCP收到客户端的request报文之后,没有发现相应的租约记录或某些原因(如地址池用尽)无法分配IP地址,则返回客户端NAK报文。
DHCP Release:当客户端不使用所分配的IP地址时,会发送release报文告知dhcp server。
DHCP Decline:当客户端收到dhcp的地址信息后,发现由于某些原因地址不可用(如地址冲突)会发送decline报文告知dhcp server。
DHCP Inform:当客户端希望获取dhcp server详细信息时会发送inform报文至服务器。
附:四种常见dhcp报文:https://ro.wikipedia.org/wiki/DHCP
DHCP协议:https://tools.ietf.org/html/rfc2131
熟悉了客户端自动获取IP地址的过程,下一步笔者就开始搭建一台DHCP服务器了。老样子,先把上一章的TFTP服务停掉:/bin/systemctl stop xinetd.service
查看一下状态确认关闭:/bin/systemctl status xinetd.service
查看yum已经安装的dhcp软件:yum list installed | grep dhcp
查看yum源关于dhcp的安装软件:yum list | grep dhcp
yum安装DHCP:yum install dhcp.x86_64
安装好之后,和之前TFTP一样,笔者先对其进行初始化设置:
cd /etc/dhcp/
cat dhcpd.conf
笔者看到第四行似乎有个example的配置文件,果断进去看了看语句的格式。熟悉之后笔者开始对dhcp的策略配置: cat /usr/share/doc/dhcp-4.2.5/dhcpd.conf.example
先介绍一下笔者的网络情况,笔者之前配的马赛克地址(一直以来称作192.168.101.2)是笔者园区网络的地址,这段地址在笔者的数据中心,一般是固定地址供服务器使用。其余的一些地址则是由现网中的DHCP server分配,园区网络中除了客户端获取地址之外,基于ap-ac架构的无线接入点也需要获取地址,并同时需要下发option选项。而笔者园区网络比较复杂,现网业务不能中断,因此笔者考虑找两段没有用过的地址,在专网(10.150.101.0/24)中进行测试。首先笔者在10.150.101.0/24网段中测试一下同网段前半部分地址分发,并为某台设备绑定地址;其次笔者新建一段地址10.150.100.0/24通过dhcp relay的方式为option 60字符为Aruba的设备下发ac地址。
明确了测试目标,笔者进行dhcpd.conf的配置:
vi dhcpd.conf
首先进行全局设置:
ddns-update-style none;
调整ddns的方式为none,DDNS为域名解析提供了一种动态关联的机制,其目的是为了实现客户端地址变动时,dns解析可以跟随主机的IP地址变动。由于客户端完全可以通过mac-ip的绑定不使其地址变动,所以该功能在网络中应用意义不大,就直接设置为none了。
http://www.zytrax.com/books/dns/ch9/dhcp.html
ignore client-updates;
同上,客户端更新,直接关闭。
default-lease-time 3600;
该字段是标识dhcp租约的时间,笔者在全局模式下设置为1小时=3600秒。
max-lease-time 86400;
最大租约时间,如果某地址池设置的租约时间大于该阈值,则生效。设置为1天。
option domain-name "hbai.com";
option domain-name-servers 10.150.101.249;
设置dns服务器为本机地址,使得dhcp server可以同时下发dns供服务器域名解析。
class "aruba" {
match if substring (option vendor-class-identifier, 0, 7) = "ArubaAP";
}
定义一个class规则,匹配字符“ArubaAP”。
option serverip code 43 = string;
option serverip31:31:2e:31:31:31:2e:31:2e:31:31:31;
设置option 43下发的ac地址为11.111.1.111以ascii来表示。
全局模式下配置差不多就这些,下面就是定义一些地址池,新建两段地址用做测试。整个文件的配置如下:
配置中,笔者新建了同网段的一个地址池10.150.101.10-10.150.101.100,对匹配到字符为Aruba的设备下发地址,同时,笔者有台mac后四位为137d的设备,对其绑定地址10.150.101.55。
同时,笔者新建了一段10.150.100.0的网段,进行地址分配。
配置参数完成后参考之前的策略,开放防火墙udp67端口。
firewall-cmd --list-all
firewall-cmd --zone=public --del-port=67/udp–permanent
firewall-cmd –reload
cd /etc/firewalld/zones/
cat public.xml
开启dhcp服务:systemctl start dhcpd
开启dns服务:systemctl start named
对于一台客户机而言,取到地址是一件非常简单的事情,只要在操作系统上设置为自动获取地址,等待地址获取就可以了。由于故障排查的要求,笔者需要对整个dhcp地址获取、续租、释放等过程都需要有深刻的理解,因此笔者在内网的一台跳板机抓包分析dhcp的获取过程和option字段。
在同网段的某台内网windows设备上开启wireshark,选择网卡后在搜索栏中筛选关于dhcp的报文:bootp
(wireshark官网地址:https://www.wireshark.org/#download)
很幸运,笔者的专网比较干净(无大量设备自动获取地址),因此抓到了一个完整的dhcp四次交互过程:
如上图所示,是笔者一台mac末尾为137d的设备进行dhcp获取地址的过程。在这台设备接入网络后,即开始发送DHCP Discover报文,当笔者的dhcp服务器在67端口监听到该报文后就会恢复客户端DHCP Offer报文,由于笔者在配置文件中将其mac绑定了地址10.150.101.55,因此服务器将该地址返回给客户端,再经过request和ack两个阶段后客户端成功获取地址。
首先笔者查看discover报文,在该报文中首先看option 55的请求参数列表,客户端会向服务器请求如下option参数。
在报文中并没有看到客户端请求option 43的信息,笔者的客户端在发起dhcp请求时,除了获取到想要的IP地址之外,还请求了包括子网掩码、广播地址、网关、dns、主机名、NTP、MTU的信息。
查看一下discover报文中的option 60,是F5Nerworks。该字段标识了客户端的厂商信息。
当客户端发起一次请求之后,dhcp服务器就会对其进行响应,这个报文就是DHCP offer报文。
查看报文中的option 53、option 54信息,看到报文类型为offer,dhcp服务器地址为笔者服务器的地址。
查看报文中option 51,看到笔者在服务器端设置的默认lease time为1H。
查看报文中option 1、option 3,看到笔者设置的掩码和网关。
查看该报文中的option 15、option 6,看到笔者下发的dns server ip为10.150.101.249,dns下发成功。
后面两个交互的报文是客户端和服务器确认地址获取成功,option信息基本相同,就不再细看了。
最后再看一下dhcp的租约信息。Linux的租约目录在/var/lib/dhcpd/下,进入该目录cat dhcpd.leases文件就可以看到地址和租约了~
该文件记录了某时间点IP地址和客户端MAC地址的对应关系,一旦需要溯源,就可以以这个文件为准了。笔者测试时间测试跨度比较长,其间地址绑定等操作陆陆续续测试了多次,这个租约是某周末前后笔者截取的一段log,其中137d的地址绑定已经被笔者释放了,这个测试阶段测试了已经获取地址设备的续约,使用了两台设备分别下发了地址池第一个和最后一个地址。
还有一些遗憾,由于出差笔者没法找到合适的设备测试option 60字段是否下发成功,文中关于option 60的一些配置是查看相关的文档资料配置的,这个在文件“cat /usr/share/doc/dhcp-4.2.5/dhcpd.conf.example”中就有配置的例子,但要抓到option 43的报文还需要进行下一步的验证。
附上一个客户端dhcp状态图,度娘上直接搜的。可以更方便的理解客户端在不同状态间的转换,有兴趣的朋友可以根据不同的状态抓取相应的报文仔细分析。到此为止客户端获取地址并续约的过程已经实现。
CSDN一篇对DHCP option解读:http://blog.csdn.net/nosodeep/article/details/45971677
网友评论