记录DHCP IPV6遇到的问题(一)

进行DHCP IPV6连接的时候,经常遇到设备获取过一次地址后,在短时间内再次重新主动进行一次DHCP IPV6连接,会连接失败,从抓包来分析就是上行服务器不响应。

 通过与服务器方的沟通,了解到一点,服务器会记录请求设备的mac和DUID(是唯一标识一台DHCPv6设备(包括客户端、中继和服务器)的标识符,用于DHCPv6设备之间的相互验证),发现的设备DUID会一直变动,导致校验失败,所以服务器就不响应了。

找到原因,接下来就到了分析源码的时候了:

    /*
     * 2 bytes for the 'duid type' field.
     * 2 bytes for the 'htype' field.
     * (not stateless) 4 bytes for the 'current time'.
     * enough bytes for the hardware address (note that hw_address has
     * the 'htype' on byte zero).
     */
    len = 4 + (ip->hw_address.hlen - 1);
    if (duid_type == DUID_LLT)
        len += 4;
    if (!buffer_allocate(&duid->buffer, len, MDL))
        log_fatal("no memory for default DUID!");
    duid->data = duid->buffer->data;
    duid->len = len;

    /* Basic Link Local Address type of DUID. */
    if (duid_type == DUID_LLT) {
        putUShort(duid->buffer->data, DUID_LLT);
        putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
        putULong(duid->buffer->data + 4, cur_time - DUID_TIME_EPOCH);
        memcpy(duid->buffer->data + 8, ip->hw_address.hbuf + 1,
               ip->hw_address.hlen - 1);
    } else {
        putUShort(duid->buffer->data, DUID_LL);
        putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
        memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
               ip->hw_address.hlen - 1);
    }

这里就是填充DUID字段的地方,发现DUID有两种类型,一种是LL类型,也就是Link-Layer Address,DUID填充内容为设备mac地址;另外一种就是LLT类型,也就是Link-Layer Address Plus Time,DUID填充内容为设备地址加上时间。前面报文中的设备使用的就是LLT类型DUID,加上了4字节的当前时间,所以肯定每次DHCP IPV6请求的DUID字段内容就会不同。

所以针对会校验 DUID的服务器,我们就需要将DUID类型改变为LL,即字段内容为设备mac地址,这样就保证了每次的请求DUID都相同了。

一般的开源DHCPv6代码,DUID类型都是可以通过参数可配置的,所以启动时加上使用LL类型的DUID参数即可,修改后的DUID如下图报文所示:


版权声明:本文为cc0410原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。