1. 概述
DHCP Client跟DHCP Server之间的交互同时存在广播包和单播包(在续租地址的时候用到)两种内容,我们知道一般的负载均衡设备都是对单播包的数据实现负载均衡,所以单纯的DHCP Client->DHCP Server架构基本上无法实现负载均衡。
但是对运营商或者一些大型公司来说,由于有很多用户,单台DHCP服务器的性能不足以满足众多客户端的DHCP分配,所以必须部署多台DHCP服务器。
如果部署方式划分为多个DHCP Client->DHCP Server的区域,会使网络结构变得复杂且难以部署和维护。因此一般会采用DHCP Server集中部署的方式。在这种方式中会用到DHCP Relay(中继)的功能,由于Relay设备跟DHCP Server之间是通过单播包来通信,这就为DHCP Server实现负载均衡带来了可能。
下面我们从头来了解DHCP的详细内容和处理过程。
在做负载均衡的时候,需要根据用户的不同需求,分析某些特定字段,然后转发到不同的服务器,所以我们要重点解一下
DHCP
报文格式。
2. DHCP数据包格式
DHCP是BOOTP协议的扩展,二者的数据包格式是相同的,其中包中某些字段是给BOOTP用的。
下面的是DHCP数据包格式:
以下为各栏位的简要说明:
OP
若是
client送给server的封包,设为1,反向为2。
HTYPE
硬件类别,
Ethernet为1。
HLEN
硬件地址长度,
Ethernet为6。
HOPS
若封包需经过
router传送,每站加1,若在同一网内,为0。
TRANSACTIONID
DHCPREQUEST时产生的数值,以作DHCPREPLY时的依据。
SECONDS
Client端启动时间(秒)。
FLAGS
从
0到15共16bits,最左一bit为1时表示server将以广播方式传送封包给client,其余尚未使用。
ciaddr
要是
client端想继续使用之前取得之IP地址,则列于这里。
yiaddr
从
server送回client之DHCPOFFER与DHCPACK封包中,此栏填写分配给client的IP地址。
siaddr
若
client需要透过网络开机,从server送出之DHCPOFFER、DHCPACK、DHCPNACK封包中,此栏填写开机程序所在server之地址。
giaddr
若需跨网段进行
DHCP分配,此栏为relayagent的地址,否则为0。
chaddr
Client之硬件地址。
sname
Server之名称字串,以0x00结尾。
file
若
client需要透过网络开机,此栏将指出开机程序名称,稍后以TFTP传送。
options
允许厂商定义选项(Vendor-SpecificArea),以提供更多的设定信息(如:Netmask、Gateway、DNS、等等)。其长度可变,同时可携带多个选项,每一选项之第一个byte为信息代码,其后一个byte为该项资料长度,最后为项目内容。CODE LEN VALUE 此字段完全兼容 BOOTP ,同时扩充了更多选项。其中,DHCP 封包可利用编码为 0x53 之选项来设定封包类别:
项值 类别
1 DHCP DISCOVER
2 DHCP OFFER
3 DHCP REQUEST
4 DHCP DECLIENT
5 DHCP ACK
6 DHCP NACK
7 DHCP RELEASE
DHCP 的选项非常多,需要更多了解请查阅 RFC 或相关文献
3. DHCP报文类型和处理流程介绍
DHCP协议有如下几种报文类型(通过数据包中的option 栏位指定):
1. DHCP Discover
此为client开始DHCP过程中的第一个请求报文。
当
client
启动并进行
DHCP
初始化时,它会在本地网络广播该请求报文,如果中间有
Relay
设备,则
Relay
设备会把该广播包改成单播包转发到
DHCP
服务器。
如果客户在发出
DHCP DISCOVER
包后一段时间内没有接收到回应,它有机会重新发送请求
10
次,否则就通知用户获取地址失败。
2. DHCP Offer
此为server 对DHCP Discover 报文的响应。
DHCP
服务器以
DHCP Offer
响应客户的DHCP Discover
,这个包内包括可用的
IP
地址和参数。如果存在
Relay
设备,服务器是以单播方式把该包发送到
Relay
设备,然后
Relay
设备通过广播方式发送到客户端。
3. DHCP Request
此为client 对DHCP Offer 报文的响应
客户端同样以广播方式发出该包,
如果中间有
Relay
设备,则
Relay
设备会把该广播包改成单播包转发到
DHCP
服务器。
如果客户端收到网络上多台
DHCP
服务器的响应,只会挑选其中一个
DHCP offer (
通常是最先抵达的那个
)
,并且会向网络发送一个
DHCP Request
广播封包,告诉所有
DHCP
服务器它将指定接受哪一台服务器提供的
IP
地址。
DHCP Request
还有一个用途是当客户端需要续租地址的时候,会以单播的形式直接发送
DHCP Request
包到之前分配给它
IP
的服务器地址。
4. DHCP Declient
当client发现server 分配给它的IP地址无法使用,如IP地址发生冲突时,将发出此报文让server禁止使用这次分配的IP地址。 在回应DHCP Offer的时候,跟DHCP Request二选一,检查分配的IP地址无效时,不是发送DHCP Request,而是发送DHCP Declient,如果存在Relay设备,同样是要把广播包改成单播包。
5. DHCP Ack
server对
DHCP requst 报文的响应,client收到此报文后才真正获得了IP地址和相关配置信息。
如果存在
Relay
设备,服务器是以单播方式把该包发送到
Relay
设备,然后
Relay
设备通过广播方式发送到客户端。
6. DHCP Nack
此报文是server对client的DHCP Requst报文的拒绝响应,client 收到此报文后,一般会重新开始DHCP过程。
如果存在
Relay
设备,服务器是以单播方式把该包发送到
Relay
设备,然后
Relay
设备通过广播方式发送到客户端。
7. DHCP Release
此报文是 client主动释放IP地址,当server 收到此报文后就可以收回IP地址,分配给其他的client。
如果中间有
Relay
设备,则
Relay
设备会把该广播包改成单播包转发到
DHCP
服务器。
总结上面报文处理的介绍,在包含了DHCP Relay设备的情况下,我们把一次成功的DHCP处理流程以下图更清晰地表示出来:
DHCP Client跟
DHCP Relay之间是通过广播包通信,DHCP Relay跟DHCP Server之间是通过单播包通信。
DHCP Relay或者client续租地址时与DHCP Server的交互是基于UDP的C/S结构进行通信。Client/
Relay端口为68,Server端口为67。
4. DHCP负载均衡分析
通过前面的分析,我们知道要对DHCP服务器实现负载均衡,采用的是:
DHCP Client->DHCP Relay->DHCP Server这样的架构。
根据客户的系统规划会有不同负载均衡实现需求:
1.如果多台DHCP服务器的内容完全相同,表示任何客户端的DHCP请求可发送到任意一台服务器来处理,这种负载均衡的难点在于会话保持,要保证同一用户的多个报文发给同一台服务器来处理。
2.DHCP服务器内容不相同,也就是不同用户的DHCP请求发送到指定的DHCP服务器才能处理,需要负载均衡能够分析每一个报文,并把报文转发到指定的服务器,该种方式实际上实现了会话保持。
下面我们来描述如何实现DHCP 服务器负载均衡的以上两种情况的特定需求。
针对需求1:
我们知道客户端发来的每个DHCP的报文中都会带有客户端终端的MAC地址,这是一个唯一值,那么只要能够把报文中MAC地址相同的包发给同一台服务器,就自然实现了每个客户端的会话保持。
这一般要求负载均衡设备支持脚本语言来分析这个数据包,例如,如下脚本实现基于每个客户端的MAC地址的会话保持:
when SERVER_DATA {
binary scan [UDP::payload 28 6] H12 mac
if { [persist lookup uie $mac] ne "" } {
persist add uie $mac
}
}
when CLIENT_DATA {
binary scan [UDP::payload 28 6] H12 mac
if { $mac ne "" } {
persist uie $mac
}
}
针对需求2:
假定用户的系统设计是用不同的DHCP Server为不同区域的用户分配相应的IP地址(多台DHCP Server负载分配的地址段不相同),例如,运营商往往会设定不同的Bras设备所接入的客户端需要分配为指定的某些网段的IP,比如服务器1负责分配192.16.1.0/24, 192.168.2.0/24,192.168.3.0/24这三个网段的IP,而这三个网段规划是分配给Bras1接入的用户,,那么当DHCP的请求信息来自于Bras1,需要由负载均衡设备转发给DHCP Server1,接着Server1会根据DHCP包中的某些属性和现有地址已分配的情况判断具体分配哪个地址给客户端。
我们通过下面逻辑图的示例来描述具体的处理过程:
Bras1,Bras2…是客户端的接入设备同时提供DHCP Relay功能,A10设备放在Relay设备和DHCP服务器之间实现各种DHCP报文的负载均衡。
假设目前有两台DHCP Server同时工作,两台Server同时会有备份服务器(如果只有一台备份服务器,则这台备份服务器同时为两台主的服务器做备份,本例中假定只有一台备份服务器为两台主的DHCP服务器做备份)。
假设DHCP Server1的IP 为:10.5.5.1, 备份服务器IP为10.5.5.3
DHCP Server2的IP为:10.5.5.2, 备份服务器IP为10.5.5.3。
以上的IP分配可以规划为不同网段,只要路由通就可以。
在负载均衡设备上做如下配置:
Slb service-group sg_DHCP1 udp
Member: 10.5.5.1:0 priority 10
Member: 10.5.5.3:0 priority 1
Slb service-group sg_DHCP2 udp
Member: 10.5.5.2:0 priority 10
Member: 10.5.5.3:0 priority 1
以上设置中Priority 值高的优先选择。
具体的处理过程是通过脚本判断DHCP的请求来自于哪台Bras,进而转发到指定的DHCP服务器,在写脚本前预先要知道不同用户要分配的IP段以及Bras地址跟具体的DHCP Server的对应关系。
具体处理过程如下:
1. Client1通过广播包发出DHCP Discovery包到达Bras1,Bras1通过单播方式把请求发到负载均衡设备。
2. 根据规划,来自于Bras1的请求需要让DHCP Server1来处理,负载均衡设备判断源地址是Bras1,就会把请求通过单播方式发送到Server1(在负载均衡设备的配置中是转发给上面所建的sg_DHCP1, 意思是Server1正常则
转发给
Server1
,如果Server1 down
掉,则转发给备份Server
)。由于Server1上有三段IP可以分配,具体分配哪段IP给用户,需要在Bras上进行配置,该配置在DHCP包的giaddr网段中指定。
3. Server1判断DHCP包中giaddr字段,例如发现该字段带有一个地址为192.168.1.1,那么就在192.168.1.0网段中选择一个IP分配给用户,如果giaddr中的地址为192.168.2.1,就在192.168.2.0网段中选择一个IP分配给用户。
4. Server1通过单播方式发送DHCP offer包给负载均衡设备,负载均衡设备通过单播方式返回给Bras1,然后Bras1通过广播方式把该包发送到Client1。
5. 接着Client1发送DHCP Requrest广播包到Bras1,Bras1改成单播包发送到负载均衡设备,负载均衡设备重复第二步的处理,仍然会把该包单播发送到Server1,然后Server1单播回复DHCP ACK或者NACK(当无法分配IP的时候发送该包)包到负载均衡设备,负载均衡设备单播发送给Bras1, Bras1广播发送给Client1, 整个过程处理完毕。
6. 如果一段时间后Client1租约到期,Client1需要续租之前分配的IP地址,Client1会通过单播的方式,直接发送DHCP Request请求到Server1(注#,不是发送给负载均衡设备的VIP),然后Server1直接将之前分配的IP再次确认分配给Client1即可。
7. 同样道理,如果是Client2发出请求,则会通过Bras2来转发,根据规划,要由DHCP Server2来处理,重复以上的处理流程即可。
8. 负载均衡设备部署为双机HA,运行方式为一主一备,当主机发生故障,或者检测到端口down掉,网关不通等现象时,会自动切换到备机。负载均衡设备会监控DHCP Server的健康状况,当发现主的DHCP Server Down掉,会自动把用户请求转发到备机。由于同一客户端的请求都是由同一台Bras来转发,所以同一Client的会话可以确保由同一台Server来处理,而主的Server与备份Server也能够做到信息同步,所以在各种情况下都不存在会话保持不一致的问题。
注#:在Client获得IP之后,同时会从数据包中知道是哪台DHCP Server分配了IP给它,在下次需要续租IP的时候,会直接发单播包的给该DHCP ServerIP。
负载均衡的脚本处理如下:
when CLIENT_DATA{
switch [IP::remote_addr] {
10.1.1.1 {
-----如果源地址是Bras1,则选择Server1/backup组
pool $sg_DHCP1
}
10.2.2.1 {
----如果源地址是Bras2,则选择Server2/backup组
pool $sg_DHCP2
}
default { -----没有指定的Bras发来的包丢弃
discard
}
}
}
关于需求2,上面的脚本只是最简单的情况,真实的需求可能会更复杂一些,例如运营商可能通过一台Bras设备对选择不同业务系统接入用户要求分配不同网段的IP,例如一台 Bras如果接入一般上网宽带用户要分配192.168.0.0/16这段地址,如果是接入单独选择VOIP业务的用户,则分配172.16.0.0/16这段地址,而两段地址由不同的DHCP Server来分配,那么单独判断Bras的源地址就不够用了,还要具体分析DHCP包中更多地选项,大家有兴趣可以研究一下是判断哪一个选项?
(wyl)