Adding class support for DHCPv6 in ISC DHCP 4.3
  • 18 Jan 2019
  • 5 Minutes to read
  • Contributors
  • Dark
    Light
  • PDF

Adding class support for DHCPv6 in ISC DHCP 4.3

  • Dark
    Light
  • PDF

Article Summary

During the development of DHCP 4.3, a major priority was the extension of functionality existing in the DHCPv4 server to analogous features in DHCPv6. One of the most-requested features developed as part of this effort is the power to discriminate between clients, allowing or denying DHCPv6 clients based on class support similar to that found in ISC DHCP's DHCPv4 server.

DHCP 4.3 provides DHCPv6 server operators the ability to define client class and subclass membership using option attributes present in the DHCPv6 client request. However, while the syntax is designed to be similar, differences in the protocols mean that use cases are not always directly transferable.

This feature remains available in DHCP 4.4.

Protocol differences must be taken into account
Despite the similarity in their names, DHCPv4 and DHCPv6 are substantially different protocols and there is no direct correspondence between concepts and option fields familiar to DHCPv4 operators and counterparts available in the DHCPv6 world. Direct translation of a DHCPv4 configuration may not, therefore, be possible.

However, class matching in DHCPv6 works based on options which are present in the v6 protocol and these can be used to make similar kinds of distinctions between clients. Please see the dhcpd.options man page provided with DHCP 4.3 for a list of standard DHCPv6 option fields.

In order to assist server operators using this feature for the first time, syntax examples are attached and shown below.

Example Config 1

Example Config 2

Example Config 3

Note the examples below use /120 prefixes for simplicity. RFC7084 mandates that prefixes should be at least /64.

Example Config 1

# dhcpd.conf
# example config for testing v6 class support
# pools within a subnet

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

max-lease-time 60;
default-lease-time 60;

ddns-update-style none;

log-facility local7;

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

option dhcp6.name-servers 2001:db8::1;

# several classes to try out
class "class1" {
  log(info, concat("CLASS6 TEST Class1  ", option dhcp6.client-id));
  match if option dhcp6.client-id = "client_1";
}

class "class2" {
  log(info, concat("CLASS6 TEST Class2  ", option dhcp6.client-id));
  match if option dhcp6.client-id = "client_2";
}

class "class3" {
  log(info, concat("CLASS6 TEST Class3  ", option dhcp6.client-id));
  match if option dhcp6.client-id = "client_3";
}

subnet6 2001:db8::0/64 {
  pool6 {
    log(info, concat("CLASS6 TEST Pool1  ", option dhcp6.client-id));
    range6 2001:db8::0:100 2001:db8::0:1FF;
    range6 2001:db8::1:0/120 temporary;
    prefix6 2001:db8::10:0:0 2001:db8::1F:0:0 /120;
    allow members of "class1";
  }
  pool6 {
    log(info, concat("CLASS6 TEST Pool2  ", option dhcp6.client-id));
    range6 2001:db8::0:200 2001:db8::0:2FF;
    range6 2001:db8::2:0/120 temporary;
    prefix6 2001:db8::20:0:0 2001:db8::2F:0:0 /120;
    allow members of "class2";
  }
  pool6 {
    log(info, concat("CLASS6 TEST Pool3  ", option dhcp6.client-id));
    range6 2001:db8::0:300 2001:db8::0:3FF;
    range6 2001:db8::3:0/120 temporary;
    prefix6 2001:db8::30:0:0 2001:db8::3F:0:0 /120;
    allow known clients;
  }

  pool6 {
    log(info, concat("CLASS6 TEST Pool4  ", option dhcp6.client-id));
    range6 2001:DB8::0:400 2001:db8::0:4FF;
    range6 2001:DB8::4:0/120 temporary;
    prefix6 2001:DB8::40:0:0 2001:DB8::4F:0:0 /120;
    allow unknown clients;
  }
}

# host definition to get a name for DDNS update
host client_1 {
   host-identifier option dhcp6.client-id "client_1";
}

host client_2 {
   host-identifier option dhcp6.client-id "client_2";
}

host client_3 {
   host-identifier option dhcp6.client-id "client_3";
}

Example Config 2

# dhcpd.conf
# config for testing v6 class support
# pools within a subnet within a shared netowrk

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

max-lease-time 60;
default-lease-time 60;

ddns-update-style none;

log-facility local7;

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

option dhcp6.name-servers 2001:DB8::1;

# several classes to try out
class "class1" {
  log(info, concat("CLASS6 TEST Class1  ", option dhcp6.client-id));
  match if option dhcp6.client-id = "client_1";
}

class "class2" {
  log(info, concat("CLASS6 TEST Class2  ", option dhcp6.client-id));
  match if option dhcp6.client-id = "client_2";
}

class "class3" {
  log(info, concat("CLASS6 TEST Class3  ", option dhcp6.client-id));
  match if option dhcp6.client-id = "client_3";
}

shared-network class_test {
subnet6 2001:db8::0/64 {
  pool6 {
    log(info, concat("CLASS6 TEST Pool1  ", option dhcp6.client-id));
    range6 2001:db8::0:100 2001:DB8::0:1FF;
    range6 2001:db8::1:0/120 temporary;
    prefix6 2001:db8::10:0:0 2001:db8::1F:0:0 /120;
    allow members of "class1";
  }
  pool6 {
    log(info, concat("CLASS6 TEST Pool2  ", option dhcp6.client-id));
    range6 2001:db8::0:200 2001:DB8::0:2FF;
    range6 2001:db8::2:0/120 temporary;
    prefix6 2001:db8::20:0:0 2001:db8::2F:0:0 /120;
    allow members of "class2";
  }
  pool6 {
    log(info, concat("CLASS6 TEST Pool3  ", option dhcp6.client-id));
    range6 2001:db8::0:300 2001:db8::0:3FF;
    range6 2001:db8::3:0/120 temporary;
    prefix6 2001:db8::30:0:0 2001:db8::3F:0:0 /120;
    allow known clients;
  }

  pool6 {
    log(info, concat("CLASS6 TEST Pool4  ", option dhcp6.client-id));
    range6 2001:db8::0:400 2001:db8::0:4FF;
    range6 2001:db8::4:0/120 temporary;
    prefix6 2001:db8::40:0:0 2001:db8::4F:0:0 /120;
    allow unknown clients;
  }
}
}

# host definition to get a name for DDNS update
host client_1 {
   host-identifier option dhcp6.client-id "client_1";
}

host client_2 {
   host-identifier option dhcp6.client-id "client_2";
}

host client_3 {
   host-identifier option dhcp6.client-id "client_3";
}

Example Config 3

# dhcpd.conf
# config for testing v6 class support
# subclasses

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

max-lease-time 10;
default-lease-time 10;

ddns-update-style none;

log-facility local7;

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

option dhcp6.name-servers 2001:DB8::1;

# several classes to try out
class "class1" {
  log(info, concat("CLASS6 TEST Class1  ", option dhcp6.client-id));
  match option dhcp6.client-id;
}

class "class2" {
  log(info, concat("CLASS6 TEST Class2  ", option dhcp6.client-id));
  match option dhcp6.client-id;
}

class "class3" {
  log(info, concat("CLASS6 TEST Class3  ", option dhcp6.client-id));
  match option dhcp6.client-id;
}

subclass "class1" "client_1";
subclass "class2" "client_2";
subclass "class3" "client_3";

subnet6 2001:DB8::0/64 {
  pool6 {
    log(info, concat("CLASS6 TEST Pool1  ", option dhcp6.client-id));
    range6 2001:DB8::0:100 2001:DB8::0:1FF;
    range6 2001:DB8::1:0/120 temporary;
    prefix6 2001:DB8::10:0:0 2001:DB8::1F:0:0 /120;
    allow members of "class1";
  }
  pool6 {
    log(info, concat("CLASS6 TEST Pool2  ", option dhcp6.client-id));
    range6 2001:DB8::0:200 2001:DB8::0:2FF;
    range6 2001:DB8::2:0/120 temporary;
    prefix6 2001:DB8::20:0:0 2001:DB8::2F:0:0 /120;
    allow members of "class2";
  }
  pool6 {
    log(info, concat("CLASS6 TEST Pool3  ", option dhcp6.client-id));
    range6 2001:DB8::0:300 2001:DB8::0:3FF;
    range6 2001:DB8::3:0/120 temporary;
    prefix6 2001:DB8::30:0:0 2001:DB8::3F:0:0 /120;
    allow known clients;
  }

  pool6 {
    log(info, concat("CLASS6 TEST Pool4  ", option dhcp6.client-id));
    range6 2001:DB8::0:400 2001:DB8::0:4FF;
    range6 2001:DB8::4:0/120 temporary;
    prefix6 2001:DB8::40:0:0 2001:DB8::4F:0:0 /120;
    allow unknown clients;
  }
}

# host definition to get a name for DDNS update
host client_1 {
   host-identifier option dhcp6.client-id "client_1";
}

host client_2 {
   host-identifier option dhcp6.client-id "client_2";
}

host client_3 {
   host-identifier option dhcp6.client-id "client_3";
}