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.
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.
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";
}