dhcp服务

        android联网最最开始就是要拿ip地址,dns地址,掩码,网关等,虽然可以静态设置,但90%的场景都是要用到dhcp动态获取地址。android中有dhcpcd这个服务端负责从网络中获得地址,而系统会通过一个库(libnetutils)去请求和控制服务端。并写入属性共享给开发者。

一、了解一下dhcp协议

        我们都知道设备为了上网,必须要有IP地址、掩码、网关地址等信息,上Internet还要有DNS服务器地址。配置静态地址又不是很友好,所以由DHCP协议自动获取配置。DHCP的前身是bootp,所以如果用wireshark抓dhcp包的话,最好用bootp过滤。DHCP分为两部分,一个服务端,一个客户端。所有IP网络配置都由DHCP服务端集中管理,并负责处理客户端的DHCP请求;而客户端则采用服务端分配的网络配置。这里要说一点,DHCP服务器提供两种分配地址的方式,一种是自动分配,客户端第一次从服务端申请到IP后就永久使用;另一种是动态分配,即服务器分配给客户端地址会携带一个续约周期,到期客户端要释放此IP地址,重新去服务器获取新地址或续约地址,动态的好处是一些不用了的设备就会回收地址,节约了IP地址。

以下是dhcp的报文结构并附上一个discoverry请求包对应着理解。

DHCP协议流程

以下是dhcp客户端请求流程及对应的抓包截图

二、dhcpcd的启动

        在android系统中,dhcp分为两个部分,一个是dhcpcd作为与网络上DHCP服务器的客户端用来与其通讯,获得网络地址资源;另一个是android系统与dhcpcd交互的(我们暂时称为dhcp client)用来控制和同步数据的。

        DHCP服务器与dhcpcd的交互协议之前已经简单说过了,这里主要介绍android系统中dhcp的使用,dhcpcd作为DHCP服务器的客户端又作为android系统的服务端存在于android系统,其源码位于external/dhcpcd下,根据android.mk可以看出,编译生成的一个dhcpcd执行文件,放在/system/bin下。下面我们来看看它又是如何与属性服务关联的。
          android属性服务是由init创建的,大家对windows的注册表这个东东有了解的话,就容易理解android的属性服务,一般,系统或应用程序会把自己的一些属性存储在注册表中,即使系统重启或应用重启,它能根据之前在注册表中设置的属性,进行相应的初始化。android提供这个功能就叫做属性服务(property service)。应用程序可通过这个属性机制查询或设置属性,也可以启动或停止一些服务。属性服务会在另一篇讲android启动的时候详细说明,这里只简单的介绍一下。属性服务由init创建,其本身是创建共享内存用于IPC共享,属性服务中的属性及服务来自default.prop,/system/build.prop,/system/default.prop,/data/local.prop和***.rc,属性服务对外是通过socket通信,客户端设置或操作属性服务中的属性或服务,也是通过soket来完成的。
         现在回归到dhcpcd的启动,首先dhcpcd是要注册到属性服务中,android系统通过属性服务控制dhcpcd的启动。注册属性服务就要看***.rc文件 例如
service dhcpcd_eth0 /system/bin/dhcpcd -ABKLG
    class main
    disabled
    oneshot
系统(libnetutils)通过 property_set(ctrl_prop, DAEMON_NAME);//向名字为dhcpcd的属性service,发送"ctrl.start"启动命令字 来启动dhcpcd,用"ctl.stop"停止命令停止dhcpcd。dhcpcd获得的资源会通过脚本设置到属性中。

三、dhcpcd的配置

        dhcpcd的配置,一般是启动的时候跟上参数或配置文件完成的,譬如 /system/bin/dhcpcd -ABKL -f dhcpcd.conf或 /system/bin/dhcpcd -n等等,参数的定义晚上都能查到,这里就简单的过一下
dhcpcd [-bdeknpqABDEGKLTV] [-c, --script script] [-f, --config file]
            [-h, --hostname hostname] [-i, --vendorclassid vendorclassid]
            [-l, --leasetime seconds] [-m, --metric metric]
            [-o, --option option] [-r, --request address]
            [-s, --inform address[/cidr]] [-t, --timeout seconds]
            [-u, --userclass class] [-v, --vendor code, value]
            [-y, --reboot seconds] [-z, --allowinterfaces pattern]
            [-C, --nohook hook] [-F, --fqdn FQDN] [-I, --clientid clientid]
            [-O, --nooption option] [-Q, --require option]
            [-S, --static value] [-X, --blacklist address[/cidr]]
            [-Z, --denyinterfaces pattern] [interface] [...]
     dhcpcd -k, --release [interface]

     dhcpcd -x, --exit [interface]

四、dhcpcd在android中数据传递流程

1、封装到netcfg中,可以使用netcfg+参数(netcfg dhcp eth0,netcfg up eth0等)使用。

        从 system\core\netcfg下的android.mk可以看出编译生成netcfg命令,而netcfg的功能都在netcfg.c中有一个结构体数组来定义如
struct 
{
    const char *name;
    int nargs;
    void *func;
} CMDS[] = {
    { "dhcp",   1, do_dhcp },
    { "up",     1, ifc_up },
    { "down",   1, ifc_down },
    { "deldefault", 1, ifc_remove_default_route },
    { "hwaddr", 2, set_hwaddr },
    { 0, 0, 0 },

};

这里调用netcfg dhcp就会相应的调用到 do_dhcp(1为参数是一个譬如eth0)->dhcp_init_ifc->open_raw_socket,拿到socket的fd调用poll等待激活或超时后填充msg(init_dhcp_discover_msg或init_dhcp_request_msg)->send_message->send_packet->sendmsg(s, &msghdr, 0)发送给DHCP服务器,而在这个循环里也接收receive_packet和解析decode_dhcp_msg,处理dhcp的回复包信息(ack,nak,offer等)。这里要指出流程dhcp_init_ifc这里就已经在libnetutils这个库中处理了,所以dhcp的所有处理包括android调用的都是在此库中完成的。
int dhcp_init_ifc(const char *ifname)
{
    省略部分代码
    s = open_raw_socket (ifname, hwaddr, if_index);
    for (;;) {
        r = poll(&pfd, 1, timeout);
        if (r == 0) {
            if (timeout >= TIMEOUT_MAX) {
                printerr("timed out\n");
                if ( info.type == DHCPOFFER ) {
                    printerr("no acknowledgement from DHCP server\nconfiguring %s with offered parameters\n", ifname);
                    return dhcp_configure(ifname, &info);
                }
                errno = ETIME;
                close(s);
                return -1;
            }
            timeout = timeout * 2;
        transmit:
            size = 0;
            msg = NULL;
            switch(state) {
            case STATE_SELECTING:
                msg = &discover_msg;
                size = init_dhcp_discover_msg(msg, hwaddr, xid);
                break;
            case STATE_REQUESTING:
                msg = &request_msg;
                size = init_dhcp_request_msg(msg, hwaddr, xid, info.ipaddr, info.serveraddr);
                break;
            default:
                r = 0;
            }
            if (size != 0) {
                r = send_message(s, if_index, msg, size);
                if (r < 0) {
                    printerr("error sending dhcp msg: %s\n", strerror(errno));
                }
            }
            continue;
        }
        if (r < 0) {
            if ((errno == EAGAIN) || (errno == EINTR)) {
                continue;
            }
            return fatal("poll failed");
        }
        errno = 0;
        r = receive_packet(s, &reply);
        if (r < 0) {
            if (errno != 0) {
                ALOGD("receive_packet failed (%d): %s", r, strerror(errno));
                if (errno == ENETDOWN || errno == ENXIO) {
                    return -1;
                }
            }
            continue;
        }
        decode_dhcp_msg(&reply, r, &info);
        if (state == STATE_SELECTING) {
            valid_reply = is_valid_reply(&discover_msg, &reply, r);
        } else {
            valid_reply = is_valid_reply(&request_msg, &reply, r);
        }
        switch(state) {
        case STATE_SELECTING:
            if (info.type == DHCPOFFER) {
                state = STATE_REQUESTING;
                timeout = TIMEOUT_INITIAL;
                xid++;
                goto transmit;
            }
            break;
        case STATE_REQUESTING:
            if (info.type == DHCPACK) {
                printerr("configuring %s\n", ifname);
                close(s);
                return dhcp_configure(ifname, &info);
            } else if (info.type == DHCPNAK) {
                printerr("configuration request denied\n");
                close(s);
                return -1;
            } else {
                printerr("ignoring %s message in state %d\n",
                         dhcp_type_to_name(info.type), state);
            }
            break;
        }
    }
    close(s);
    return 0;
}
2、封装为libnetutils库中,提供给jni(android_net_netutils)调用。
        android中提供给java层的网络调用接口主要就是NetworkUtils类,其中封装了 android_net_netutils的native方法,而jni的方法又是调用libnetutils提供的方法,而libnetutils才是android主要维护dhcp服务的交互。举一个启动dhcpcd的例子来说明一下
    NetworkUtils.runDhcp(mIface, dhcpResults) 直接调用JNI的native函数 android_net_utils_runDhcp -> android_net_utils_runDhcpCommon-> ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength, dns, server, &lease, vendorInfo, domains, mtu)这里获取到ip信息利用 jmethodID回调java层函数设置这些信息到java层的类中。
int dhcp_do_request(const char *interface, char *ipaddr, char *gateway, uint32_t *prefixLength, char *dns[], char *server, uint32_t *lease, char *vendorInfo, char *domain, char *mtu)
{
   忽略一些代码
    const char *ctrl_prop = "ctl.start";
    const char *desired_status = "running";
     snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result",
            DHCP_PROP_NAME_PREFIX,
            p2p_interface); 
            DHCP_PROP_NAME_PREFIX,
            p2p_interface);  拼接字符串result_prop_name=‘dhcp.eth0.result’
     snprintf(daemon_prop_name, sizeof(daemon_prop_name), "%s_%s",
            DAEMON_PROP_NAME,
            p2p_interface);   拼接字符串daemon_prop_name=‘init.svc.dhcpcd_eth0’
    property_set(result_prop_name, "");
    if (property_get(HOSTNAME_PROP_NAME, prop_value, NULL) && (prop_value[0] != '\0'))
         snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:-f %s -h %s %s", DAEMON_NAME,
                 p2p_interface, DHCP_CONFIG_PATH, prop_value, interface);
    else
         snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:-f %s %s", DAEMON_NAME,
                 p2p_interface, DHCP_CONFIG_PATH, interface);
拼接字符串 daemon_cmd=‘dhcpcd_eth0:-f /system/etc/dhcpcd/dhcpcd.conf eth0’
    memset(prop_value, '\0', PROPERTY_VALUE_MAX);
     property_set(ctrl_prop, daemon_cmd);
    if ( wait_for_property(daemon_prop_name, desired_status, 10) < 0) {
        snprintf(errmsg, sizeof(errmsg), "%s", "Timed out waiting for dhcpcd to start");
        return -1;
    }
    if ( wait_for_property(result_prop_name, NULL, 60) < 0) {
        snprintf(errmsg, sizeof(errmsg), "%s", "Timed out waiting for DHCP to finish");
        return -1;
    }
    if (!property_get(result_prop_name, prop_value, NULL)) {
        /* shouldn't ever happen, given the success of wait_for_property() */
        snprintf(errmsg, sizeof(errmsg), "%s", "DHCP result property was not set");
        return -1;
    }
    if (strcmp(prop_value, "ok") == 0) {
        char dns_prop_name[PROPERTY_KEY_MAX];
        if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
                server, lease, vendorInfo, domain, mtu) == -1) {

            return -1;

        }

        return 0;

    } else {

        snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value);

        return -1;

    }

}

这里说明上述几个拼接字符串的作用, daemon_prop_name是用来同步获取dhcpcd当前启动状态的,result_prop_name是通知dhcpcd获取到非NULL结果的属性,启动dhcpcd则使用了启动属性服务的流程property_set(ctrl_prop, daemon_cmd);以后的章节中会详细介绍属性服务的内容,这里只需知道启动属性服务只需传ctl.start+属性服务名称:参数即可(这里为ctl.start+dhcpcd_eth0:-f /system/etc/dhcpcd/dhcpcd.conf eth0),而停止一个属性服务为ctl.stop+属性服务名称,重启一个属性服务ctl.restart+属性服务名称。

        启动dhcpcd属性服务后,就会调用dhcpcd的main函数,从而进入dhcpcd的工作流程。read_config(从配置文件中设置option)->parse_config_line->parse_option->add_options(从传入的参数中设置option)->之后创建了几个event(signal、socket、link_socket、ipv6rs_socket),添加到start_eloop中poll阻塞轮询->init_state->configure_interface->run_script(iface)以reason = "PREINIT"执行脚本->handle_carrier->handle_interface(1, ifname)->start_interface->start_discover->send_discover->send_message((struct interface *)arg, DHCP_DISCOVER, send_discover)->open_sockets中创建了另一个处理dhcp的event(handle_dhcp_packet->bind_interface它是更新reason状态的)->send_raw_packet->sendto发送DHCP_DISCOVER给DHCP服务器。而其中穿插着以reason值执行脚本,从而更新系统dhcp属性,脚本如下

if [[ $interface == p2p* ]]
    then
    intf=p2p
    else
    intf=$interface
fi
setprop dhcp.${intf}.reason "${reason}"
case "${reason}" in
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT)
    setprop dhcp.${intf}.ipaddress  "${new_ip_address}"
    setprop dhcp.${intf}.gateway    "${new_routers%% *}"
    setprop dhcp.${intf}.mask       "${new_subnet_mask}"
    setprop dhcp.${intf}.leasetime  "${new_dhcp_lease_time}"
    setprop dhcp.${intf}.server     "${new_dhcp_server_identifier}"
    setprop dhcp.${intf}.vendorInfo "${new_vendor_encapsulated_options}"
    setprop dhcp.${intf}.mtu        "${new_interface_mtu}"
    setprop dhcp.${intf}.result "ok"
    ;;
EXPIRE|FAIL|IPV4LL|STOP|NOCARRIER)
    setprop dhcp.${intf}.result "failed"
    ;;
RELEASE)
    setprop dhcp.${intf}.result "released"
    ;;
esac

dhcpcd各个状态的跳转,这里就不赘述了,因为这篇是介绍android的调用,并不是一片介绍dhcpcd流程的文章,如果以后有机会,也会有专门一篇介绍dhcpcd流程的,根据reason,大概有这几种状态STATIC,IPV4LL,INFORM,TIMEOUT,TEST,RENEW,REBIND,REBOOT,BOUND。

HCIA——DHCP协议及实验wireshark抓包_捕获dns、dhcp协议-CSDN博客

HCIA所有内容:

1、七层参考模型及IP讲解
2、TCP三次握手讲解
3、TCP四次挥手讲解及抓包分析
4、DHCP协议讲解及抓包分析
5、静态综合实验讲解
7、静态路由讲解
8、RIP路由信息协议讲解
9、动态路由协议讲解
10、抓包进行分析RIP以及OSPF的包
11、动态路由OSPF配置综合实验讲解
12、Vlan虚拟局域网技术讲解
13、ACL访问控制列表讲解
14、NAT技术讲解
15、网络综合实验讲解

DHCP协议(应用层)

认识DHCP

DHCP,动态主机配置协议

定义:

是 RFC 1541(已被 RFC 2131 取代)定义的标准协议,该协议允许服务器向客户端动态分配 IP 地址和配置信息。

两部分:

DHCP协议支持C/S(客户端/服务器)结构,
1、DHCP客户端: 通常为网络中的PC、打印机等终端设备,使用从DHCP服务器分配下来的IP信息,包括IP地址、DNS等。
2、DHCP服务器: 所有的IP网络设定信息都由DHCP服务器集中管理,并处理客户端的DHCP请求。

端口号:

常见的两个端口号:
67即为DHCP服务端(server)
68即为DHCP客户端(client)
DHCP采用UDP作为传输协议,客户端发送消息到DHCP服务器的的67号端口,服务器返回消息给客户端的68号端口。

服务:

通常DHCP 服务器向客户端提供以下信息:
IP 地址,子网掩码以及默认网关
还可以提供其他信息,比如域名服务 (DNS) 服务器等的地址。

服务形式:

DHCP服务器为客户端分配IP地址有三种形式:
第一种:手动分配:管理员将一个IP地址固定分配给一个客户端。
第二种:自动分配:随机地将地址永久性分配给客户端。
第三种:动态分配:随机地将地址分配给客户端使用一段时间。

第三种是 最常见 的使用形式。
地址的有效使用时间段称为租用期,租用期满之前,客户端必须向服务器请求继续租用。
服务器收到请求后才能继续使用,否则无条件放弃。

续租流程:

DHCP服务器向DHCP客户端出租的IP地址一般都有一个租借期限,期满后DHCP服务器便会收回出租的IP地址。 为了能继续使用原先的IP地址,DHCP客户端会向DHCP服务器发送续租的请求。
DHCP续租的工作流程描述如下:
1、在使用租期过去50%时刻处, 客户端向服务器发送单播DHCP REQUEST报文续延租期。
2、如果收到服务器的DHCP ACK报文,则租期相应向前延长,续租成功。
如果没有收到DHCP ACK报文,则客户端继续使用这个IP地址。
在使用租期过去87.5%时刻处,向服务器发送广播DHCP REQUEST报文续延租期。

3、如果收到服务器的DHCP ACK报文,则租期相应向前延长,续租成功。
如果没有收到DHCP ACK报文,则客户端继续使用这个IP地址。
在使用租期到期时,客户端自动放弃使用这个IP地址,并重新DHCP。

DHCP服务流程

在这里插入图片描述
服务流程:
1、客户端广播请求 :当计算机启动时,会向网络上广播一个特殊的DHCP请求,以寻求可用的IP地址,也就是DHCP请求包(DHCP Discover)广播
2、DHCP服务器提供回应: 当DHCP服务器收到客户端的广播请求后,它将从一个 IP 地址池中选择一个未被使用的IP地址,并通过广播方式将其发送回客户端,即为DHCP Offer包单播
3、DHCP 客户端确认地址:客户端接收到DHCP服务器发来的回应后,它将检查回应中是否包含了一个可用的IP地址,即为DHCP Request包
如果有,客户端将发送一个确认消息给DHCP服务器,以告知它已经确认了该IP地址。(进行广播)
4、DHCP服务器更新数据库:DHCP服务器接收了客户端的确认消息,它将确认下这个IP地址已经被分配出去。这个信息将保存在DHCP服务器的数据库中,以确保该IP地址在可用时间内不会被分配给其他客户端。即为DHCP ACK 包单播

一、客户端广播请求:

寻找DHCP服务器: 当DHCP客户端第一次登录网络,计算机如果发现本机没有IP地址设定,就会以广播发送DHCP discover包来寻找DHCP服务器即IP地址为255.255.255.255发送特定的广播信息。而在网络上成功安装了TCP/IP协议的主机就会接收这个广播信息,但只有DHCP服务器才会做出响应

DHCP Discover报文信息:

在这里插入图片描述
目标MAC为FF-FF-FF-FF-FF-FF (画图时候大多了,图没保存。。。)

二、DHCP服务器提供回应:

服务器分配IP地址: 接收到DHCP discover包的DHCP服务器就会做出响应,它从未分配的IP地址池中挑选一个分配给DHCP客户端,向DHCP客户端发送一个包含分配的IP地址和DHCP Offer

DHCP Offer报文信息:

在这里插入图片描述

三、DHCP客户端确认地址:

客户端接受IP地址: DHCP客户端接受到DHCP offer后,选择第一个接收到的提供信息,然后以广播的方式回应所有DHCP服务器 (DHCP request),该包中包含它所发送给DHCP服务器请求IP的内容以及服务器分给它的IP租期。

DHCP Request报文信息:

在这里插入图片描述

四、DHCP服务器更新数据库:

确认所分配的IP地址: 当DHCP服务器收到DHCP客户端发出的DHCP request之后,便向DHCP客户端单播发送一个包含它所提供的IP地址和DHCP ack,回应可以使用此IP地址。
之后,DHCP客户端将IP地址绑定。同时,其他的DHCP服务器就会收回曾经提供给客户端而客户端未使用的IP地址。

DHCP ACK报文信息:

在这里插入图片描述

wireshark抓DHCP包进行分析

通过Wireshark抓取DHCP获取IP过程的数据报文,这里我用的是Wireshark 4.0.5
这里我采用的是直接抓取,抓取电脑释放IP以及重新DHCP全过程里的数据包。

一、抓取过程:

1、打开Wireshark进行抓包WLAN:

在这里插入图片描述
我们可以看到WLAN有流量波动,所以我将抓取WLAN里交换的数据包。
在这里插入图片描述

2、释放IP并重新获取:


在这里插入图片描述
这里首先win加r调出运行窗口,接着输入cmd命令。
输入ipconfig /release进行释放IP
然后输入ipconfig /renew重新获取IP

如下图所示:
在这里插入图片描述
在这里插入图片描述
此时我们可以看到IP地址已经重新获取完成,wireshark也已经抓包到了全过程。
接着我们结束抓包。

3、使用bootp过滤报文

由于Wireshark在处理DHCP时,使用的是BOOTP协议,所以在Packet Detail 面板中看到的是Bootstrap Protocol,而不是DHCP。

在这里插入图片描述

二、分析所抓取的DHCP包

0.0.0.0表示要么没有IP地址,要么代表所有IP地址。这里则表示网卡还没有获取到ip地址,需要向DHCP服务器申请IP地址。
255.255.255.255用来表示本地网络的广播地址,它不能被转发,不能过过网关。

1、DHCP Release报文

在这里插入图片描述
DHCP客户端向服务器发送DHCP Release数据包,以释放IPv4地址并取消所有剩余的租约。
我们主要学习以下几个报文:

2、DHCP Discover报文

在这里插入图片描述
在这里插入图片描述
客户端使用0.0.0.0发送单播数据包目的地址是255.255.255.255向DHCP服务器请求分配192.168.123.112这个IP地址

详细说明:

Message type: Boot Request (1) DHCP消息类型,1表示请求包
Hardware type: Ethernet (0x01) 硬件类型为Ethernet
Hardware address length: 6 硬件地址长度为6
Hops: 0: 经过DHCP中继数为0
Transaction ID: 0xe007659f ID为0xe007659f
Seconds elapsed: 0 客户端启动时间
Bootp flags: 0x0000 (Unicast) BOOTP标志字段,此处是单播
0… … … … = Broadcast flag: Unicast
.000 0000 0000 0000 = Reserved flags: 0x0000
Client IP address: 0.0.0.0 (0.0.0.0) 客户端IP地址
Your (client) IP address: 0.0.0.0 (0.0.0.0) 自己的(客户端)IP地址
Next server IP address: 0.0.0.0 (0.0.0.0) 下一阶段使用的DHCP服务器的IP地址
Relay agent IP address: 0.0.0.0 (0.0.0.0) DHCP中继器的IP地址
Client MAC address: 02:00:04:78:01:7b (02:00:04:78:01:7b) 客户端的MAC地址
Client hardware address padding: 00000000000000000000 客户端硬件地址填充
Server host name not given 服务器主机名
Boot file name not given 启动文件名
Magic cookie: DHCP 与BOOTP兼容
Option: (53) DHCP Message Type (Discover) DHCP消息类型为53
Length: 1 长度为1
DHCP: Discover (1) 发现包
Option: (61) Client identifier 客户端标识符
Length: 7 长度为7
Hardware type: Ethernet (0x01) 硬件类型为Ethernet
Client MAC address: 02:00:04:78:01:7b (02:00:04:78:01:7b) 客户端MAC地址
Option: (50) Requested IP Address 请求IP地址
Length: 4 长度为4
Requested IP Address: 10.1.1.142 (10.1.1.142) 请求的IP地址
Option: (12) Host Name 客户端主机名
Length: 10 长度为10
Host Name: heetian-PC 主机名为heetian-PC
Option: (60) Vendor class identifier 供应商类标识符
Length: 8 长度为8
Vendor class identifier: MSFT 5.0 供应商标识符为MSFT 5.0
Option: (55) Parameter Request List 参数请求列表
Length: 12 长度是12
Parameter Request List Item: (1) Subnet Mask 子网掩码
Parameter Request List Item: (15) Domain Name 域名
Parameter Request List Item: (3) Router 路由
Parameter Request List Item: (6) Domain Name Server域名服务
Parameter Request List Item: (44) NetBIOS over TCP/IP Name Server #NetBIOS 名称服务
Parameter Request List Item: (46) NetBIOS over TCP/IP Node Type #NetBIOS 节点类型
Parameter Request List Item: (47) NetBIOS over TCP/IP Scope #NetBIOS 作用范围
Parameter Request List Item: (31) Perform Router Discover 完成路由发现
Parameter Request List Item: (33) Static Route 静态路由
Parameter Request List Item: (121) Classless Static Route 无类静态路由
Parameter Request List Item: (249) Private/Classless Static Route (Microsoft) 私有静态路由
Parameter Request List Item: (43) Vendor-Specific Information 供应商特定信息
Option: (255) End
Option End: 255
Padding

3、DHCP Offer报文

在这里插入图片描述
在这里插入图片描述
DHCP服务器以单播的形式,往客户端发送DHCP Offer,告诉客户端192.168.123.112地址可用,并给出IP的子网掩码、广播地址。也可以看到IP地址的租期是24个小时,租期的1/2是12小时,租期的7/8是21个半小时。

当拥有时长达到租赁时长一半的时候,机器将发送一个续约包给dhcp服务器,dhcp服务器将发送一个ack确认包,如果未收到,机器将在3/4租赁时长再次发送续约包

详细说明

Bootstrap Protocol (Offer)
Message type: Boot Reply (2) DHCP消息类型,2表示响应包
Hardware type: Ethernet (0x01) 硬件类型为Ethernet
Hardware address length: 6 硬件地址长度为6
Hops: 0 经过DHCP中继数为0
Transaction ID: 0xe007659f ID为0xe007659f
Seconds elapsed: 0 客户端启动时间
Bootp flags: 0x0000 (Unicast) BOOTP标志字段,此处是单播
0… … … … = Broadcast flag: Unicast
.000 0000 0000 0000 = Reserved flags: 0x0000
Client IP address: 0.0.0.0 (0.0.0.0) 客户端IP地址
Your (client) IP address: 10.1.1.142 (10.1.1.142) 自己的(客户端)IP地址
Next server IP address: 10.1.1.1 (10.1.1.1) 下一阶段使用的DHCP服务器的IP地址
Relay agent IP address: 0.0.0.0 (0.0.0.0) DHCP中继器的IP地址
Client MAC address: 02:00:04:78:01:7b (02:00:04:78:01:7b) 客户端的MAC地址
Client hardware address padding: 00000000000000000000 客户端硬件地址填充
Server host name not given 服务器主机名
Boot file name not given 启动文件名
Magic cookie: DHCP 与BOOTP兼容
Option: (53) DHCP Message Type (Discover) DHCP消息类型为53
Length: 1 长度为1
DHCP: Offer (2) 响应包
Option: (54) DHCP Server Identifier DHCP服务标识符
Length: 4 长度为4
DHCP Server Identifier: 10.1.1.1 (10.1.1.1) DHCP服务标识符
Option: (51) IP Address Lease Time IP地址租约的最短时间
Length: 4 长度为4
IP Address Lease Time: (4294967295s) infinity IP地址租约的最短时间为无限期
Option: (1) Subnet Mask 子网掩码
Length: 4 长度为4
Subnet Mask: 255.255.255.0 (255.255.255.0) 子网掩码值是255.255.255.0
Option: (28) Broadcast Address 广播地址
Length: 4 长度为4
Broadcast Address: 10.1.1.255 (10.1.1.255) 广播地址值为10.1.1.255
Option: (6) Domain Name Server 域名服务
Length: 12 长度为12
Domain Name Server: 10.1.1.1 (10.1.1.1) 域名服务地址为10.1.1.1
Domain Name Server: 8.8.8.8 (8.8.8.8) 域名服务地址为8.8.8.8
Domain Name Server: 8.8.8.8 (8.8.8.8) 域名服务地址为8.8.8.8
Option: (3) Router 路由
Length: 4
Router: 10.1.1.1 (10.1.1.1) 路由器地址为10.1.1.1
Option: (15) Domain Name 域名
Length: 17
Domain Name: cs2cloud.internal 域名为cs2cloud.internal
Option: (43) Vendor-Specific Information 供应商特定信息
Length: 7
Value: 020400000001ff
Option: (60) Vendor class identifier 供应商类标识符
Length: 8
Vendor class identifier: MSFT 5.0
Option: (255) End
Option End: 255
Padding

4、DHCP Request报文

在这里插入图片描述
在这里插入图片描述
客户端在得到DHCP服务器回复IP地址可用后,即请求分配192.168.123.112地址。 不过,客户端还没有获取到合法的IP地址,依然只能以0.0.0.0发送单播数据包,目的地址255.255.255.255。

详细说明:

Bootstrap Protocol (Request)
Message type: Boot Request (1) DHCP消息类型,1表示请求包
Hardware type: Ethernet (0x01) 硬件类型为Ethernet
Hardware address length: 6 硬件地址长度为6
Hops: 0 经过DHCP中继数为0
Transaction ID: 0xe007659f ID为0xe007659f
Seconds elapsed: 0 客户端启动时间
Bootp flags: 0x0000 (Unicast) BOOTP标志字段,此处是单播
0… … … … = Broadcast flag: Unicast
.000 0000 0000 0000 = Reserved flags: 0x0000
Client IP address: 0.0.0.0 (0.0.0.0) 客户端IP地址
Your (client) IP address: 0.0.0.0 (0.0.0.0) 自己的(客户端)IP地址
Next server IP address: 0.0.0.0 (0.0.0.0) 下一阶段使用的DHCP服务器的IP地址
Relay agent IP address: 0.0.0.0 (0.0.0.0) DHCP中继器的IP地址
Client MAC address: 02:00:04:78:01:7b (02:00:04:78:01:7b) 客户端的MAC地址
Client hardware address padding: 00000000000000000000 客户端硬件地址填充
Server host name not given 服务器主机名
Boot file name not given 启动文件名
Magic cookie: DHCP 与BOOTP兼容
Option: (53) DHCP Message Type (Request) DHCP消息类型为53
Length: 1 长度为1
DHCP: Discover (3) 请求包
Option: (61) Client identifier 客户端标识
Length: 7 长度为7
Hardware type: Ethernet (0x01) 硬件类型为Ethernet
Client MAC address: 02:00:04:78:01:7b (02:00:04:78:01:7b) 客户端MAC地址
Option: (50) Requested IP Address 请求IP地址
Length: 4 长度为4
Requested IP Address: 10.1.1.142 (10.1.1.142) 请求的IP地址
Option: (54) DHCP Server Identifier DHCP服务器标识符
Length: 4
DHCP Server Identifier: 10.1.1.1 (10.1.1.1) DHCP标识符为10.1.1.1
Option: (12) Host Name 客户端主机名
Length: 10 长度为10
Host Name: heetian-PC 主机名为heetian-PC
Option: (81) Client Fully Qualified Domain Name 客户端完全合格域名
Length: 13
Flags: 0x00 标志位
0000 … = Reserved flags: 0x00 保留标志位
… 0… = Server DDNS: Some server updates 服务器DDNS
… .0… = Encoding: ASCII encoding 编码格式
… …0. = Server overrides: No override 服务重写
… …0 = Server: Client
A-RR result: 0
PTR-RR result: 0
Client name: heetian-PC 客户端名称
Option: (60) Vendor class identifier 供应商类标识符
Length: 8 长度为8
Vendor class identifier: MSFT 5.0 供应商标识符为MSFT 5.0
Option: (55) Parameter Request List 参数请求列表
Length: 12 长度是12
Parameter Request List Item: (1) Subnet Mask 子网掩码
Parameter Request List Item: (15) Domain Name 域名
Parameter Request List Item: (3) Router 路由
Parameter Request List Item: (6) Domain Name Server 域名服务
Parameter Request List Item: (44) NetBIOS over TCP/IP Name Server NetBIOS名称服务
Parameter Request List Item: (46) NetBIOS over TCP/IP Node Type NetBIOS节点类型
Parameter Request List Item: (47) NetBIOS over TCP/IP Scope NetBIOS作用范围
Parameter Request List Item: (31) Perform Router Discover 完成路由发现
Parameter Request List Item: (33) Static Route 静态路由
Parameter Request List Item: (121) Classless Static Route 无类静态路由
Parameter Request List Item: (249) Private/Classless Static Route (Microsoft) 私有静态路由
Parameter Request List Item: (43) Vendor-Specific Information 供应商特定信息
Option: (255) End
Option End: 255
Padding

5、DHCP ACK报文

在这里插入图片描述
在这里插入图片描述
DHCP服务器收到客户端请求后,用ACK数据包回应,正式确认192.168.123.112分配给该客户端。

当拥有时长达到租赁时长一半的时候,机器将发送一个续约包给dhcp服务器,dhcp服务器将发送一个ack确认包,如果未收到,机器将在3/4租赁时长再次发送续约包。

详细说明:

Bootstrap Protocol (ACK)
Message type: Boot Reply (2) DHCP消息类型,2表示响应包
Hardware type: Ethernet (0x01) 硬件类型为Ethernet
Hardware address length: 6 硬件地址长度为6
Hops: 0 经过DHCP中继数为0
Transaction ID: 0xe007659f ID为0xe007659f
Seconds elapsed: 0 客户端启动时间=
Bootp flags: 0x0000 (Unicast) BOOTP标志字段,此处是单播
0… … … … = Broadcast flag: Unicast
.000 0000 0000 0000 = Reserved flags: 0x0000
Client IP address: 0.0.0.0 (0.0.0.0) 客户端IP地址
Your (client) IP address: 10.1.1.142 (10.1.1.142) 自己的(客户端)IP地址
Next server IP address: 10.1.1.1 (10.1.1.1) 下一阶段使用的DHCP服务器的IP地址
Relay agent IP address: 0.0.0.0 (0.0.0.0) DHCP中继器的IP地址
Client MAC address: 02:00:04:78:01:7b (02:00:04:78:01:7b) 客户端的MAC地址
Client hardware address padding: 00000000000000000000 客户端硬件地址填充
Server host name not given 服务器主机名
Boot file name not given 启动文件名
Magic cookie: DHCP 与BOOTP兼容
Option: (53) DHCP Message Type (ACK) DHCP消息类型为53
Length: 1 长度为1
DHCP: ACK (5) 确认包
Option: (54) DHCP Server Identifier DHCP服务标识符
Length: 4 长度为4
DHCP Server Identifier: 10.1.1.1 (10.1.1.1) DHCP服务标识符
Option: (51) IP Address Lease Time IP地址租约的最短时间
Length: 4 长度为4
IP Address Lease Time: (4294967295s) infinity IP地址租约的最短时间为无限期
Option: (1) Subnet Mask 子网掩码
Length: 4 长度为4
Subnet Mask: 255.255.255.0 (255.255.255.0) 子网掩码值是255.255.255.0
Option: (28) Broadcast Address 广播地址
Length: 4 长度为4
Broadcast Address: 10.1.1.255 (10.1.1.255) 广播地址值为10.1.1.255
Option: (81) Client Fully Qualified Domain Name 客户端完全合格域名
Length: 30
Flags: 0x03 标志位
0000 … = Reserved flags: 0x00 保留标志位
… 0… = Server DDNS: Some server updates 服务器DDNS
… .0… = Encoding: ASCII encoding 编码格式
… …1. = Server overrides: No override 服务重写
… …1 = Server: Client
A-RR result: 255
PTR-RR result: 255
Client name: Client name: win7-64-1.cs2cloud.internal 客户端名称
Option: (6) Domain Name Server 域名服务
Length: 12 长度为12
Domain Name Server: 10.1.1.1 (10.1.1.1) 域名服务地址为10.1.1.1
Domain Name Server: 8.8.8.8 (8.8.8.8) 域名服务地址为8.8.8.8
Domain Name Server: 8.8.8.8 (8.8.8.8) 域名服务地址为8.8.8.8
Option: (3) Router 路由
Length: 4
Router: 10.1.1.1 (10.1.1.1) 路由器地址为10.1.1.1
Option: (15) Domain Name 域名
Length: 17
Domain Name: cs2cloud.internal 域名为cs2cloud.internal
Option: (43) Vendor-Specific Information 供应商特定信息
Length: 7
Value: 020400000001ff
Option: (60) Vendor class identifier 供应商类标识符
Length: 8
Vendor class identifier: MSFT 5.0
Option: (255) End
Option End: 255
Padding

 

网络服务-DHCP

1.DHCP简介

DHCP(Dynamtic Host Configuraton Protocol,动态主机配置协议)是一个工作在应用层的局域网网络协议,数据传输时使用UDP不可靠谱传输协议工作,通常被应用在大型的局域网络环境中,主要作用是集中的管理、分配网络资源,使网络环境中的主机能动态的获得IP地址、Gatway地址、DNS服务器地址等信息,能够提升地址的使用率。

2.DHCP工作原理(租约四部曲+续租)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.DHCP 服务搭建

在这里插入图片描述在这里插入图片描述

4.DHCP实验部署

在这里插入图片描述
具体实验操作:
1.修改配置文件dhcpd.conf ,将其中前几个不用的subnet注释掉;
2.设置一个subnet要分配的网段和子网掩码,声明可用的IP地址,其余用不到的可以暂时不设置;
3.保留最小租约时间和最大租约时间;

[root@oracle dhcp]# vim dhcpd.conf
# dhcpd.conf
#
# Sample configuration file for ISC dhcpd
#

# option definitions common to all supported networks...
option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;

default-lease-time 600;
max-lease-time 7200;

# Use this to enble / disable dynamic dns updates globally.
#ddns-update-style none;

# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
#authoritative;

# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
log-facility local7;

# No service will be given on this subnet, but declaring it helps the 
# DHCP server to understand the network topology.

#subnet 10.152.187.0 netmask 255.255.255.0 {
#}

# This is a very basic subnet declaration.

#subnet 10.254.239.0 netmask 255.255.255.224 {
#  range 10.254.239.10 10.254.239.20;
#  option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org;
#}

# This declaration allows BOOTP clients to get dynamic addresses,
# which we don't really recommend.

#subnet 10.254.239.32 netmask 255.255.255.224 {
#  range dynamic-bootp 10.254.239.40 10.254.239.60;
#  option broadcast-address 10.254.239.31;
#  option routers rtr-239-32-1.example.org;
#}

# A slightly different configuration for an internal subnet.
subnet 192.168.197.0 netmask 255.255.255.0 {
  range 192.168.197.20 192.168.197.200;
#  option domain-name-servers ns1.internal.example.org;
#  option domain-name "internal.example.org";
#  option routers 10.5.5.1;
#  option broadcast-address 10.5.5.31;
  default-lease-time 600;
  max-lease-time 7200;
}

4.启动服务,service dhcpd start
5.查看是否启动成功

[root@oracle dhcp]# service dhcpd start
Starting dhcpd:                                            [  OK  ]
[root@oracle dhcp]# netstat -tluna     
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State      
tcp        0      0 0.0.0.0:55647               0.0.0.0:*                   LISTEN      
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      
tcp        0      0 0.0.0.0:21                  0.0.0.0:*                   LISTEN      
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      
tcp        0      0 127.0.0.1:631               0.0.0.0:*                   LISTEN      
tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN      
tcp        0      0 192.168.197.134:22          192.168.197.1:58794         ESTABLISHED 
tcp        0      0 192.168.197.134:22          192.168.197.1:60712         ESTABLISHED 
tcp        0      0 192.168.197.134:22          192.168.197.135:63025       ESTABLISHED 
tcp        0      0 :::51618                    :::*                        LISTEN      
tcp        0      0 :::33060                    :::*                        LISTEN      
tcp        0      0 :::3306                     :::*                        LISTEN      
tcp        0      0 :::111                      :::*                        LISTEN      
tcp        0      0 :::22                       :::*                        LISTEN      
tcp        0      0 ::1:631                     :::*                        LISTEN      
tcp        0      0 ::1:25                      :::*                        LISTEN      
udp        0      0 127.0.0.1:1001              0.0.0.0:*                               
udp        0      0 0.0.0.0:111                 0.0.0.0:*                               
udp        0      0 0.0.0.0:631                 0.0.0.0:*                               
udp        0      0 0.0.0.0:24840               0.0.0.0:*                               
udp        0      0 0.0.0.0:67                  0.0.0.0:*                               
udp        0      0 0.0.0.0:838                 0.0.0.0:*                               
udp        0      0 :::111                      :::*                                    
udp        0      0 :::36291                    :::*                                    
udp        0      0 :::838                      :::*    

6.验证,将局域网内的另外一台主机B,ip获取方式改成DHCP
在这里插入图片描述
7.重启另一台主机B的网卡,service network restart (该命令会重启所有网卡,如果怕影响别的网卡服务,可以使用下面这条语句,只启动特定的网卡)

[root@135 ~]# ifdown eth0;ifup eth0

验证主机B,通过DHCP服务来获取IP的新ip地址(之前是静态设置的ip135,现在变成了129)

[root@135 Desktop]# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0C:29:C1:E2:78  
          inet addr:192.168.197.129  Bcast:192.168.197.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fec1:e278/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:12562 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12696 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1132479 (1.0 MiB)  TX bytes:1389920 (1.3 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:5784 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5784 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:522236 (509.9 KiB)  TX bytes:522236 (509.9 KiB)

8.回到搭建有DHCP服务的主机A上,查看DHCP的服务日志/var/log/messages,进一步了解,DHCP的工作原理(即租约四部曲)。

[root@oracle dhcp]# tail -10 /var/log/messages
Jun 23 06:56:49 oracle dhcpd: Wrote 0 leases to leases file.
Jun 23 06:56:49 oracle dhcpd: Listening on LPF/eth0/00:0c:29:64:b4:6d/192.168.197.0/24
Jun 23 06:56:49 oracle dhcpd: Sending on   LPF/eth0/00:0c:29:64:b4:6d/192.168.197.0/24
Jun 23 06:56:49 oracle dhcpd: Sending on   Socket/fallback/fallback-net
Jun 23 07:00:31 oracle dhcpd: DHCPDISCOVER from 00:0c:29:c1:e2:78 via eth0
Jun 23 07:00:31 oracle dhcpd: ns1.example.org: temporary name server failure
Jun 23 07:00:31 oracle dhcpd: ns2.example.org: temporary name server failure
Jun 23 07:00:31 oracle dhcpd: DHCPOFFER on 192.168.197.129 to 00:0c:29:c1:e2:78 (135) via eth0
Jun 23 07:00:31 oracle dhcpd: DHCPREQUEST for 192.168.197.129 (192.168.197.134) from 00:0c:29:c1:e2:78 (135) via eth0
Jun 23 07:00:31 oracle dhcpd: DHCPACK on 192.168.197.129 to 00:0c:29:c1:e2:78 (135) via eth0

获取请求:MAC地址为00:0c:29:c1:e2:78的主机发出来的

Jun 23 07:00:31 oracle dhcpd: DHCPDISCOVER from 00:0c:29:c1:e2:78 via eth0

向客户机B发送OFFER

Jun 23 07:00:31 oracle dhcpd: DHCPOFFER on 192.168.197.129 to 00:0c:29:c1:e2:78 (135) via eth0

收到来自客户机B的确认IP消息DHCPREQUEST

Jun 23 07:00:31 oracle dhcpd: DHCPREQUEST for 192.168.197.129 (192.168.197.134) from 00:0c:29:c1:e2:78 (135) via eth0

发送给客户机B的最终租约确认

Jun 23 07:00:31 oracle dhcpd: DHCPACK on 192.168.197.129 to 00:0c:29:c1:e2:78 (135) via eth0

4.2.DHCP的地址保留实验(固定地址分配)

目的:使得客户机B每次利用DHCP服务获取的IP地址是一样的,保持不变的IP
在这里插入图片描述
修改配置文件:/etc/dhcp/dhcpd.conf
在这里插入图片描述
重启DHCPD服务 :service dhcpd restart

[root@oracle dhcp]# service dhcpd restart
Shutting down dhcpd:                                       [  OK  ]
Starting dhcpd:                                            [  OK  ]

在客户机上执行 :ifdown eth0;ifup eth0 重启eth0网卡,检查IP地址
在这里插入图片描述

4.3超级作用域(同一局域网)

当局域网的主机台数超过一个网段的台数时,多于255了,需要在不改变为B类网段的情况下,添加主机台数,和之前的局域网主机能够通信。在生产环境中只需要利用路由器(路由器有DHCP的功能)的单臂路由的功能,在原来的基础上,添加另一个IP地址,就可以通过路由器,让不同网段的局域网主机进行通信。
下面为模拟实验环境
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.4 DHCP中继

模拟的环境就是,局域网A网段的主机A,通过DHCP服务+一台DHCP中继器,可以将局域网B网段的主机B进行连接,使得DHCP服务可以为不同网段的主机,实现分配IP的功能,依靠的就是DHCP中继服务的能力。
下图为本人粗略根据理解所画的草图,正确性不敢保证
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

posted @ 2024-03-14 09:47  CharyGao  阅读(399)  评论(0)    收藏  举报