Configure "device", "class" and "group" options
Beyond the global, network and subnet options already described, most sites will have a number of group or class based options, and have a requirement for setting reply parameters against individual devices.
In general, FreeRADIUS does not differentiate between "classes" (memberships defined by some attribute of the DHCP request) and "groups" (memberships defined by some manually aggregation related devices, typically based on lists of MAC address).
The sample DHCP configuration provided with FreeRADIUS makes use of an internal
attribute DHCP-Group-Name
to support the setting of different options for
different groups of devices.
In general the groups to which a device belongs is determined during the
processing of a request and these are added as instances of the
DHCP-Group-Name
attribute. This may be by performing a test on one or more
request parameters (akin to a "class"), hash-based lookup of up all of part of
an attribute in a local list (akin to a "subclass"), or doing the same using a
remote datastore (SQL, LDAP, REST API, etc).
FreeRADIUS can then iterate over DHCP-Group-Name
to set group-specific
options.
We describe some of these options in more detail.
Directly in Policy
Simple class options can be written directly into policy. This is most
suited to those options that rarely change and are based on attributes in the
request such as the User-Class
.
Consider the ISC DHCP configuration snippet:
filename "undionly.kpxe";
class "pxeclient" {
match option substring(user-class,0,4);
}
subclass "pxeclient" "iPXE" {
filename "http://my.web.server/boot_script.php";
}
Or the equivalent Kea configuration:
"Dhcp4": {
"option-data": [
{ "name": "boot-file-name", "data": "undionly.kpxe" }
],
"client-classes": [
{
"name": "pxeclient",
"test": "substring(option[77],0,4) == 'iPXE'",
"option-data": [
{
"name": "boot-file-name",
"data": "http://my.web.server/boot_script.php"
}
]
}
]
...
}
These define the "filename" DHCP option differently based on whether or not the supplied "user-class" option begins with "iPXE".
FreeRADIUS provides multiple ways for this to be configured.
For example, the following "unlang" policy implements the class options defined above:
if (&DHCP-User-Class && "%{substring:&DHCP-User-Class 0 4}" == "iPXE") {
update reply {
&DHCP-Boot-Filename := "http://my.web.server/boot_script.php"
}
} else {
update reply {
&DHCP-Boot-Filename := "undionly.kpxe"
}
}
Policy-based configuration of DHCP options is also useful for complex matching. For example, the following Unlang sets the DHCP-Boot-Filename parameter based on the request’s DHCP-Client-Identifier using regular expression captures, provided that it matches the given format:
if (&DHCP-Client-Identifier && \
"%{string:DHCP-Client-Identifier}" =~ /^RAS([0-9])-site([A-Z])$/) {
update reply {
&DHCP-Boot-Filename := "rasboot-%{1}-%{2}.kpxe"
}
}
In Text Files
The files
module that has already been described for global, network and
subnet options can also be used to apply options to groups of clients.
Firstly we must defined a mapping from a set of clients clients to their
respective groups. One option for this is to use the passwd
module, for
which a sample configuration is included.
Firstly symlink or copy the module configuration
<raddb>/mods-available/dhcp_passwd
into <raddb>/mods-enabled/
. The
suggested configuration expects the group membership file to be in
<raddb>/mods-config/files/dhcp_groups
and take the form of:
<group1 name>|<hardware address>,<hardware address>,<hardware address>
<group2 name>|<hardware address>,<hardware address>
i.e. one line for each group starting with the group name followed by a pipe character and then a comma-separated list of hardware addresses.
The allow_multiple_keys
option allows for a host to be a member of
more than one group.
Sample configuration for looking up group options is contained in
<raddb>/policy.d/dhcp
in the dhcp_group_options
policy and in
<raddb>/mods-available/dhcp_files
as the dhcp_set_group_options
instance.
The same data file <raddb>/mods-config/files/dhcp
is used to lookup
group options as was used for global and network options. In this instance,
add entries with the group name as the key such as:
group1
DHCP-Log-Server := 10.10.0.100,
DHCP-LPR-Server := 10.10.0.200
group2
DHCP-LPR-Server := 192.168.20.200
In the SQL Database
Policy and files are both read during startup and editing them while FreeRADIUS is running will not result in any changes in behaviour. If you require regular changes to DHCP options, then storing them in an SQL database provides greater flexibility since the queries will be run in response to each DHCP packet rather than requiring the server to be restarted.
DHCP reply options for devices (including network-specific options) can be fetched from SQL using an arbitrary lookup key. This can be performed multiple times as necessary using different contexts, for example to first set subnet-specific options and then to set group-specific options.
The default schema contains three tables to support this:
"dhcpreply" contains reply options for a given identifier (e.g. MAC Address):
Identifier | Attribute | Op | Value | Context |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"dhcpgroup" maps identifiers to a group of options that can be shared:
Identifier | GroupName | Priority | Context |
---|---|---|---|
|
|
|
|
"dhcpgroupreply" contains reply options for each group:
GroupName | Attribute | Op | Value | Context |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Within the context of assigning options directly to devices, as well as to manually-curated groups of devices keyed by their MAC address:
-
Place device-specific options in the "dhcpreply" table.
-
Add
Fall-Through := Yes
to the options in the "dhcpreply" table in order to trigger group lookups, which are disabled by default. -
Place entries in the "dhcpgroup"
identifier = <MAC-Address>, groupname = <group>, priority = <priority>
in the "dhcpgroup" table to map a device to its groups by priority. -
Place the grouped options in the "dhcpgroupreply" table.
-
For each of the above, set
Context
to something by which the option lookup is referred to in the policy, for exampleContext = 'by-mac'
.
For the above example you would add the following to the DHCP virtual server to
perform reply option lookup using the device’s MAC address against the by-mac
context:
update control {
&DHCP-SQL-Option-Context := "by-mac"
&DHCP-SQL-Option-Identifier := &request:DHCP-Client-Hardware-Address
}
dhcp_sql.authorize
In the above, the DHCP reply options would be assigned to a device with MAC address 02:01:aa:bb:cc:dd as follows:
-
Firstly, the
DHCP-Log-Server
option would be set to192.0.2.10
and theDHCP-LPR-Server
option set to192.0.2.11
. -
Fall-Through
is set, so the group mapping is then queried which determines that the device belongs to a singlesalesdept
group. -
Finally, the options for the
salesdept
group are now merged, setting aDHCP-NTP-Servers
option to192.0.2.20
, appending an additionalDHCP-Log-Server
option set to192.0.2.21
, and prepending an additionalDHCP-LPR-Server
option set to192.0.2.22
.
If instead you wanted to perform a "subclass" lookup based on the first three octets of the device’s MAC address then with tables containing the following sample data you could invoke an SQL lookup as shown:
Identifier | Attribute | Op | Value | Context |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Identifier | GroupName | Priority | Context |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
GroupName | Attribute | Op | Value | Context |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
update control {
&DHCP-SQL-Option-Context := "class-vendor"
&DHCP-SQL-Option-Identifier := \
"%{substring:%{hex:&DHCP-Client-Hardware-Address} 0 6}"
}
dhcp_sql.authorize
The file policy.d/dhcp
contains a policy named dhcp_policy_sql
which
provides further worked examples for different types of option lookups.
Testing "device", "class" and "group" options
You should now test that any device-related options that you have configured using the various methods available are applied successfully by generating packets containing those parameters based upon which the reply options are set.
For example, to test the iPXE user class example above you might want to generate a request as follows:
cat <<EOF > dhcp-packet-ipxe-boot.txt
DHCP-Message-Type := DHCP-Discover
DHCP-Client-Hardware-Address := 02:01:aa:bb:cc:dd
DHCP-User-Class := "iPXE-class-abc"
EOF
To which you would expect to see a response such as:
dhcpclient: ... ---------------------------------------------------------------------- Waiting for DHCP replies for: 5.000000 ---------------------------------------------------------------------- ... DHCP-Message-Type = DHCP-Offer DHCP-Your-IP-Address = 1.2.3.4 DHCP-Boot-Filename := "http://my.web.server/boot_script.php" ...