Debian – ISC-DHCPD classes for ZTP (with Juniper)

debiandhcpjuniperprovisioning

I'm currently trying to setup a DHCP server to use it in a ZTP environment. My first goal is to be able to upgrade my Juniper devices automatically based on the hardware.

What I'm really trying to achieve is to dispatch the proper JUNOS software to the proper Juniper hardware. For example, a MX104 should download an MX104 targeted image and an EX4550 should download an EX4550 targeted image.

Until now, I have setup a DHCP server successfully with ISC's one. But that pretty simple until here.

Now I'm trying to play with classes and pools to match vendor-class-identifier set set it to the proper pool.

My DHCP server configuration is the following:

option domain-name "example.com";
option domain-name-servers 8.8.8.8, 8.8.4.4;
option domain-search "example.com";

set vendor-string = option vendor-class-identifier;
option ztp-file-server code 150 = { ip-address };
option space ztp-ops;
option ztp-ops.image-file-name code 0 = text;
option ztp-ops.config-file-name code 1 = text;
option ztp-ops.image-file-type code 2 = text;
option ztp-ops.transfer-mode code 3 = text;
option ztp-ops-encapsulation code 43 = encapsulate ztp-ops;

class "juniper-mx10003" {
  match if substring(option vendor-class-identifier, 0, 15) = "Juniper-mx10003";
}

subnet 10.24.0.0 netmask 255.255.0.0 {
  default-lease-time 600;
  max-lease-time 86400;
  option routers 10.24.0.1;
  range 10.24.254.0 10.24.254.254;
  # Address pool(s)
  pool {
    range 10.24.253.0 10.24.253.10;
    allow members of "juniper-mx10003";
    option ztp-file-server 10.24.1.2;
    option ztp-ops.transfer-mode "http";
    option ztp-ops.image-file-name "/junos-vmhost-install-mx-x86-64-18.1R1.9.tgz";
  }
}

And I have a Juniper configuration for my MX10003 like the following:

system {
    root-authentication {
        encrypted-password "YEAH"; ## SECRET-DATA
    }
    syslog {
        user * {
            any emergency;
        }
        file messages {
            any notice;
            authorization info;
        }
        file interactive-commands {
            interactive-commands any;
        }
    }
}
interfaces {
    fxp0 {
        unit 0 {
            family inet {
                dhcp {
                    vendor-id Juniper-mx10003;
                }
            }
        }
    }
}

When booting or clearing and requesting a lease, the MX is asking for an IP address but this is one of the range from 10.24.254.0 to 10.24.254.254 which is assigned and not from 10.24.253.0 to 10.24.253.10.

I tried dumping the DHCP exchanges with dhcpdump and here is what it finds:

  TIME: 2018-06-01 15:07:50.357
    IP: 0.0.0.0 (d8:18:d3:1e:a9:66) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
    OP: 1 (BOOTPREQUEST)
 HTYPE: 1 (Ethernet)
  HLEN: 6
  HOPS: 0
   XID: 52cccd10
  SECS: 0
 FLAGS: 7f80
CIADDR: 0.0.0.0
YIADDR: 0.0.0.0
SIADDR: 0.0.0.0
GIADDR: 0.0.0.0
CHADDR: d8:18:d3:1e:a9:66:00:00:00:00:00:00:00:00:00:00
 SNAME: .
 FNAME: .
OPTION:  53 (  1) DHCP message type         1 (DHCPDISCOVER)
OPTION:  60 ( 15) Vendor class identifier   Juniper-mx10003
OPTION:  51 (  4) IP address leasetime      86400 (24h)
---------------------------------------------------------------------------

  TIME: 2018-06-01 15:07:51.297
    IP: 10.24.1.2 (0:c:29:8:a6:dd) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
    OP: 2 (BOOTPREPLY)
 HTYPE: 1 (Ethernet)
  HLEN: 6
  HOPS: 0
   XID: 52cccd10
  SECS: 0
 FLAGS: 7f80
CIADDR: 0.0.0.0
YIADDR: 10.24.254.0
SIADDR: 0.0.0.0
GIADDR: 0.0.0.0
CHADDR: d8:18:d3:1e:a9:66:00:00:00:00:00:00:00:00:00:00
 SNAME: .
 FNAME: .
OPTION:  53 (  1) DHCP message type         2 (DHCPOFFER)
OPTION:  54 (  4) Server identifier         10.24.1.2
OPTION:  51 (  4) IP address leasetime      86400 (24h)
OPTION:   1 (  4) Subnet mask               255.255.0.0
OPTION:   3 (  4) Routers                   10.24.0.1
OPTION:   6 (  8) DNS server                8.8.8.8,8.8.4.4
OPTION: 119 ( 30) Domain Search             0a6c75786e657477 .example
                                            6f726b0269       .com.
OPTION:  15 ( 13) Domainname                example.com
---------------------------------------------------------------------------

  TIME: 2018-06-01 15:07:51.302
    IP: 0.0.0.0 (d8:18:d3:1e:a9:66) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
    OP: 1 (BOOTPREQUEST)
 HTYPE: 1 (Ethernet)
  HLEN: 6
  HOPS: 0
   XID: 52cccd10
  SECS: 0
 FLAGS: 7f80
CIADDR: 0.0.0.0
YIADDR: 0.0.0.0
SIADDR: 0.0.0.0
GIADDR: 0.0.0.0
CHADDR: d8:18:d3:1e:a9:66:00:00:00:00:00:00:00:00:00:00
 SNAME: .
 FNAME: .
OPTION:  54 (  4) Server identifier         10.24.1.2
OPTION:  55 ( 14) Parameter Request List      3 (Routers)
                                             51 (IP address leasetime)
                                              1 (Subnet mask)
                                             15 (Domainname)
                                              6 (DNS server)
                                             66 (TFTP server name)
                                             67 (Bootfile name)
                                            120 (SIP Servers DHCP Option)
                                             44 (NetBIOS name server)
                                             43 (Vendor specific info)
                                            150 (???)
                                             12 (Host name)
                                              7 (Log server)
                                             42 (NTP servers)

OPTION:  50 (  4) Request IP address        10.24.254.0
OPTION:  53 (  1) DHCP message type         3 (DHCPREQUEST)
OPTION:  60 ( 15) Vendor class identifier   Juniper-mx10003
OPTION:  51 (  4) IP address leasetime      86400 (24h)
---------------------------------------------------------------------------

  TIME: 2018-06-01 15:07:51.398
    IP: 10.24.1.2 (0:c:29:8:a6:dd) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
    OP: 2 (BOOTPREPLY)
 HTYPE: 1 (Ethernet)
  HLEN: 6
  HOPS: 0
   XID: 52cccd10
  SECS: 0
 FLAGS: 7f80
CIADDR: 0.0.0.0
YIADDR: 10.24.254.0
SIADDR: 0.0.0.0
GIADDR: 0.0.0.0
CHADDR: d8:18:d3:1e:a9:66:00:00:00:00:00:00:00:00:00:00
 SNAME: .
 FNAME: .
OPTION:  53 (  1) DHCP message type         5 (DHCPACK)
OPTION:  54 (  4) Server identifier         10.24.1.2
OPTION:  51 (  4) IP address leasetime      86400 (24h)
OPTION:   1 (  4) Subnet mask               255.255.0.0
OPTION:   3 (  4) Routers                   10.24.0.1
OPTION:  15 ( 13) Domainname                example.com
OPTION:   6 (  8) DNS server                8.8.8.8,8.8.4.4
---------------------------------------------------------------------------

Did anybody try to do the same thing?
Maybe there something obvious that I am missing?

Best Answer

After removing the range 10.24.254.0 10.24.254.254; config line everything is OK. The class and match statements are actually working and I was able to confirm this by defining a new class for another kind of hardware.

Here is the proper configuration used now:

#
# Classes
#
class "juniper-mx10003" {
  match if (option vendor-class-identifier = "Juniper-mx10003");
}
class "juniper-qfx5110" {
  match if (option vendor-class-identifier = "Juniper-qfx5110-48s-4c");
}
#
# Subnet declarations
#
subnet 10.24.0.0 netmask 255.255.0.0 {
  default-lease-time 600;
  max-lease-time 86400;
  option routers 10.24.0.1;
  # Address pool(s)
  pool {
    range 10.24.253.0 10.24.253.9;
    allow members of "juniper-mx10003";
    option ztp-file-server 10.24.1.2;
    option ztp-ops.transfer-mode "http";
    option ztp-ops.image-file-name "/junos-vmhost-install-mx-x86-64-18.1R1.9.tgz";
  }
  pool {
    range 10.24.253.10 10.24.253.19;
    allow members of "juniper-qfx5110";
    option ztp-file-server 10.24.1.2;
    option ztp-ops.transfer-mode "http";
    option ztp-ops.image-file-name "/jinstall-host-qfx-5e-flex-15.1X53-D233.1-secure-domestic-signed.tgz";
  }
}