介绍

DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)通常被应用在大型的局域网络环境中,主要作用是集中的管理、分配IP地址,使网络环境中的主机动态的获得IP地址、Gateway地址、DNS服务器地址等信息,并能够提升地址的使用率。

DHCP协议采用客户端/服务器模式。客户机登录服务器时可以自动获得DHCP服务器分配的IP地址和子网掩码,这也是现在接入网技术中供应商给用户(账号)提供IP地址的手段。

原理

端口

首先DHCP是基于UDP的两个端口实现的,DHCP提供服务时,客户端以68号端口进行数据传输,服务器端以67号端口进行数据传输。

DHCP报文类型

DHCP一共有8中报文,分别为DHCP Discover、DHCP Offer、DHCP Request、DHCP ACK、DHCP NAK、DHCP Release、DHCP Decline、DHCP Inform。

DHCP Discover: DHCP客户端在请求IP地址时并不知道DHCP服务器的位置,因此DHCP客户端会在本地网络内以广播方式发送Discover请求报文,以发现网络中的DHCP服务器。所有收到Discover报文的DHCP服务器都会发送应答报文,DHCP客户端据此可以知道网络中存在的DHCP服务器的位置。

DHCP Offer:DHCP服务器收到Discover报文后,就会在所配置的地址池中查找一个合适的IP地址,加上相应的租约期限和其他配置信息(如网关、DNS服务器等),构造一个Offer报文,发送给DHCP客户端,告知用户本服务器可以为其提供IP地址。但这个报文只是告诉DHCP客户端可以提供IP地址,最终还需要客户端通过ARP来检测该IP地址是否重复。

DHCP Request:DHCP客户端可能会收到很多Offer请求报文,所以必须在这些应答中选择一个。通常是选择第一个Offer应答报文的服务器作为自己的目标服务器,并向该服务器发送一个广播的Request请求报文,通告选择的服务器,希望获得所分配的IP地址。另外,DHCP客户端在成功获取IP地址后,在地址使用租期达到50%时,会向DHCP服务器发送单播Request请求报文请求续延租约,如果没有收到ACK报文,在租期达到87.5%时,会再次发送广播的Request请求报文以请求续延租约。

DHCP ACK:DHCP服务器收到Request请求报文后,根据Request报文中携带的用户MAC来查找有没有相应的租约记录,如果有则发送ACK应答报文,通知用户可以使用分配的IP地址。

DHCP NAK:如果DHCP服务器收到Request请求报文后,没有发现有相应的租约记录或者由于某些原因无法正常分配IP地址,则向DHCP客户端发送NAK应答报文,通知用户无法分配合适的IP地址。

DHCP Release:当DHCP客户端不再需要使用分配IP地址时,就会主动向DHCP服务器发送RELEASE请求报文,告知服务器用户不再需要分配IP地址,请求DHCP服务器释放对应的IP地址。

DHCP Decline:DHCP客户端收到DHCP服务器ACK应答报文后,通过地址冲突检测发现服务器分配的地址冲突或者由于其他原因导致不能使用,则会向DHCP服务器发送Decline请求报文,通知服务器所分配的IP地址不可用,以期获得新的IP地址。

DHCP Inform:DHCP客户端如果需要从DHCP服务器端获取更为详细的配置信息,则向DHCP服务器发送Inform请求报文;DHCP服务器在收到该报文后,将根据租约进行查找到相应的配置信息后,向DHCP客户端发送ACK应答报文。目前基本上不用了。

DHCP报文格式

我们通过抓包看一下DHCP的报文:

1.Message type:Boot Request(1)当为1时表示是client的请求,为2时是server的应答

2.Hardware type是网络硬件地址类型

3.Hardware address length表示网络硬件地址长度(6Bytes表示是以太网类型的MAC地址)

4.HOPS表示跳数,是当前的DHCP报文经过的DHCP RELAY的数目,每经过一个DHCP中继,此字段就会加1;当这个字段大于4时,DHCP报文直接丢弃。

5.Transaction id:事务ID,是DHCP请求报文时选择的随机数

6.Elapsed boot time描述,表示client开始DHCP请求后的时间流逝秒数

7.flags标志

8.Client self-assigned IP address:客户机IP地址

9.Client IP address:分配给client的IP地址

10.Next Server IP address:服务器IP地址

11.Relay AgentDHCP:中继代理IP地址

12.Client Hardware address客户机硬件地址MAC

13.Client Hardware address padding:客户机硬件MAC填充地址

14.Host Name:服务器的主机名

15.Boot File name:是client的启动配置文件名

16.Magic cookie是服务器可以根据这个cookie直到该用户是否需要重新登录。

之后的字段会根据报文类型而有不同的改变:

17.DHCP Message Type:此字段表示DHCP报文类型

18.DHCP Server Identifier是DHCP Server的报文类型

19.Client identifier:客户端报文类型

交互过程

通过观察抓包顺序可以知道是,客户端首先从68端口发出广播(UDP报文)即discover报文寻找DHCP服务器,请求租用IP地址。该广播包中的源IP地址为0.0.0.0,目标IP地址由于是广播所以为255.255.255.255,报文中还包含客户机的MAC地址和计算机名。DHCP服务器会将67端口开启,收到客户端的discover报文后会回应一个offer报文,此报文的源IP地址为服务器的IP,目标IP地址为255.255.255.255,数据报中还包含着提供的IP地址、子网掩码、网关、DNS及租期等信息。

然后客户端就会广播一个request报文,表示自己已经接受了一个DHCP服务器提供的IP地址,广播包中包含所接受的IP地址和服务器的IP地址。服务器在接收到request广播后,会广播返回给客户机一个ACK消息包,表示已经接受了客户机的选择,并将这一IP地址的合法租用以及其他的配置信息都放入该广播包发给客户。此客户此时就已经获得一个可用的IP地址。整体流程如下图:

代码设计

首先工程的结构如下:

---dhcpserver
|
|--DHCPOptionEnum.h
|--maker.h--parser.h
|--stdafx.h
|--Mystruct.h
|
|--DHCPserver.cpp

代码是基于DHCP的原理、报文以及DavidAnson的DHCPLite0的代码逻辑框架。下面将逐一分析一下代码:

main函数

逻辑是首先获取运行环境下的网络设备所有网卡信息,然后以"链表"的形式存储在PIP_ADAPTER_INFO结构体所声明的 AdapterWalker对象中,然后将需要选择的网卡信息作为输入与bindInterfaceAddress进行绑定。以上都是初始化信息,主要是为了让用户选择需要进行绑定的网络设备。

然后m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (char*)&optval, sizeof(bool))将套接字设置为UDP格式,同时通过setsockopt对套接字的功能进行设置,是套接字是符合我们想做为DHCP的广播环境的。之后创建一个线程thread mThread(ClientListen, bindInterfaceAddress)用来模拟客户端进行广播消息的交互。

接下来就是服务端与客户端的报文交互了,我们需要处理好的就是报文格式以及相应的判断就行了。主要就是在客户端发来报文后,服务端进行解析(parse),解析完成后再回应一个报文,需要先制作(make)一个报文。通过这样完成报文的交互。

ClientListen

这个函数是在新线程下用来模拟客户端的,所以逻辑是与主函数相同的。由于是线程,可以模拟多个客户。

GetIpFromTable

在这里利用了一个unordered_map的存储方式,因为利用map存储数据不论是插入还是查询的速度都是非常快的。在这个结构里我们将已经申请了IP地址的客户放入这个结构中,如果有就返回信息;如果没有这个客户,则加入这个用户的IP地址及信息。

MyStruct.h

在这里定义了DHCP报文格式的结构体

struct DHCP_PACKET {
byte OP;
byte HTYPE;
byte HLEN;
byte HOPS;
UINT32 TRANSACTION_ID;
UINT16 SECONDS;
UINT16 FLAGS;
byte ciaddr[4];
byte yiaddr[4];
byte siaddr[4];
byte giaddr[4];
byte chaddr[16];
byte sname[64];
byte file[128];
UINT32 magicCode;
byte Options[308];
};

同时定义了Packet_Information的结构体:

struct Packet_Information {
char HostName[256];
USHORT BootFileSize;
char MeritDumpFile[256];
byte DHCPMessageType;
int IPLeaseTime; // client
byte ServerIdentifier[4]; // client
byte ClientIdentifier[4];
byte ParameterRequestList[256];
byte VendorClassIdentifier[256];
byte RequestedIPAddress[4];
byte Unsupport[256];
bool OptionToReplay[256];
};

parser.h与maker.h

这里直接调用了解析与封包的相关函数,主要是对IP地址、端口以及相应数据报格式字段信息的转换,判断与赋值。

DHCPOptionEnum.h

这个头文件定义了DHCP Option的所有情况,利用enum结构进行存储;在主函数中调用时就可以通过数字进行表示与区分。

结果

项目请见:Github

DHCP服务器的设计的更多相关文章

  1. DHCP服务器

    DHCP指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码.首先,DHCP服务器必须是一台安装有Windows 2000 Server/Advanced ...

  2. DHCP服务器 出现的故障

    系统版本:Windows Server 2008 R2 Standard 故障现象:近段时间,我们核心网络DHCP服务器,总是发现有掉线重起现象,大约每10分钟至30分钟不定时会重起. 故障代码:关键 ...

  3. Windows DHCP服务器

    DHCP服务器 编辑 动态主机配置协议是一个局域网的网络协议.指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码.首先, DHCP服务器必须是一台安装有 ...

  4. Ubuntu Linux 学习篇 配置DHCP服务器

    isc-dhcp-server 动态主机配置协议是一个局域网的网络协议.指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码.首先, DHCP服务器必须是 ...

  5. 7、二种 为二个不同的子网配置DHCP服务器(中继代理服务器)

    环境如下:        (参考之前,保证二个子网可以互相ping通) 虚拟机vm1        192.168.170.3                    VMnet8 (NAT模式) 虚拟 ...

  6. DHCP服务器原理

    DHCP服务器   port:67 DHCP 这个服务可以自动的分配 IP 与相关的网络参数给客户端, 来提供客户端自动以服务器提供的参数来设定他们的网络   12.1 DHCP 运作的原理      ...

  7. DHCP服务器的开始方式

    方法一:采用DHCP服务器接口开启的方式 [Huawei]dhcp enable [Huawei]int g0/0/0[Huawei-GigabitEthernet0/0/0]ip add 192.1 ...

  8. 搭建DHCP服务器以及DHCP中继服务器

    一.DHCP服务器   1.首先配置DHCP服务器的IP地址(DHCP服务器网卡桥接在VMnet1)   .配置好IP后重启DHCP服务 3.安装DHCP服务器,在这里我用的是YUM安装的(关于YUM ...

  9. 使用Dhcpstarv解决DHCP服务器冲突问题

    场景: 内网环境需要开启多个DHCP服务器,分别给不同的设备进行PXE安装. 存在的问题: 多个DHCP的情况下,设备在启动时随机从一个DHCP服务器获取IP(哪个DHCP服务器先响应就从哪个获取)并 ...

随机推荐

  1. ACM学习历程—FZU2191完美的数字(数学)

    Description Bob是个很喜欢数字的孩子,现在他正在研究一个与数字相关的题目,我们知道一个数字的完美度是 把这个数字分解成三个整数相乘A*A*B(0<A<=B)的方法数,例如数字 ...

  2. JVM类加载(4)—加载器

    定义: 虚拟机设计团队把类加载阶段中“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称之为“类加载器 ...

  3. tomcat solr 限制ip

    <Context path="/solr" reloadable="false" docBase="/var/www"> < ...

  4. Break 、Continue 和ReadOnly、Const和Ref和Out params

    Break和Continue区别 之前对于Break和Continue:ReadOnly和Const:ref和out,params之类的基础东东学习过,但是一直没有仔细去研究到底是怎么一回事儿,最近在 ...

  5. js数组中的reverse()方法

    reverse方法是将数组中的元素的顺序进行反转,在原数组上操作,然后返回原数组.由于本人是学习js的新人,对reverse函数进行了几个小实验,以下实验均在Chrome浏览器上运行 实验一:reve ...

  6. window下rails4.1 发生TZInfo::DataSourceNotFound 错误 - smallbottle

    在官网上学习rails 4.1 ,启动rails server之后发生了如下错误 $ rails server Booting WEBrick Rails 4.1.0 application star ...

  7. mongodb循环插入测试数据

    for (var i = 1; i <= 100000; i++) {   db.testdata2.insert( { x : i , name: "MACLEAN" , ...

  8. HBase 官方文档

    HBase 官方文档 Copyright © 2010 Apache Software Foundation, 盛大游戏-数据仓库团队-颜开(译) Revision History Revision ...

  9. groupadd添加新组

    一.groupadd命令用于将新组加入系统. 格式groupadd [-g gid] [-o]] [-r] [-f] groupname 主要参数 -g gid:指定组ID号. -o:允许组ID号,不 ...

  10. SharePoint 2013 搜索高级配置

    SharePoint2013里面的搜索配置. 1.首先,新建页面,用于搜索, 2.添加搜索框.搜索结果部件: 选择<搜索>类别,找到”搜索框”.”搜索结果”两个部件,添加到页面: 3.配置 ...