1.. _hooks-radius:
2
3radius: RADIUS Server Support
4=============================
5
6The RADIUS hooks library allows Kea to interact with two types of RADIUS
7servers: access and accounting. Although the most common DHCP and RADIUS
8integration is done on the DHCP relay-agent level (DHCP clients send
9DHCP packets to DHCP relays; those relays contact the RADIUS server and
10depending on the response either send the packet to the DHCP server or
11drop it), it does require DHCP relay hardware to support RADIUS
12communication. Also, even if the relay has the necessary support, it is
13often not flexible enough to send and receive additional RADIUS
14attributes. As such, the alternative looks more appealing: to extend the
15DHCP server to talk to RADIUS directly. That is the goal this library
16intends to fulfill.
17
18.. note::
19
20   This library may only be loaded by the ``kea-dhcp4`` or the
21   ``kea-dhcp6`` process.
22
23The major feature of this hooks library is the ability to use RADIUS
24authorization. When a DHCP packet is received, the Kea server sends an
25Access-Request to the RADIUS server and waits for a response. The server
26then sends back either an Access-Accept with specific client attributes,
27or an Access-Reject. There are two cases supported here: first, the
28Access-Accept includes a Framed-IP-Address (for DHCPv4) or
29Framed-IPv6-Address (for DHCPv6), which will be interpreted by Kea as an
30instruction to assign that specified IPv4 or IPv6 address. This
31effectively means RADIUS can act as an address-reservation database.
32
33The second case supported is the ability to assign clients to specific
34pools based on a RADIUS response. In this case, the RADIUS server sends
35back an Access-Accept with a Framed-Pool (IPv4) or Framed-IPv6-Pool
36(IPv6). In both cases, Kea interprets those attributes as client
37classes. With the addition of the ability to limit access to pools to
38specific classes (see :ref:`classification-pools`), RADIUS can be
39used to force the client to be assigned a dynamic address from a
40specific pool. Furthermore, the same mechanism can be used to control
41what kind of options the client will get if there are DHCP options
42specified for a particular class.
43
44.. _hooks-radius-install:
45
46Compilation and Installation of the RADIUS Hook
47~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48
49The following section describes how to compile and install the software
50on CentOS 7.0. Other systems may differ slightly.
51
52.. note::
53
54   Starting with Kea 1.7.0, ISC now provides Kea software and hooks in convenient to use
55   native DEB and RPM packages. This includes the RADIUS hook and the required patched version
56   of the FreeRADIUS client library. The software compilation for RADIUS is complicated. unless
57   you have specific reasons to compile it yourself, you should seriously consider using
58   native packages.
59
60STEP 1: Install dependencies
61
62Several tools are needed to build the dependencies and Kea itself. The
63following commands should install them:
64
65.. code-block:: console
66
67   $ sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
68   $ sudo yum install gcc-g++ openssl-devel log4cplus-devel wget git
69
70STEP 2: Install FreeRADIUS
71
72The Kea RADIUS hooks library uses the FreeRADIUS client library to
73conduct RADIUS communication. Unfortunately, the standard 1.1.7 release
74available from the project website https://freeradius.org/sub_projects/
75has several serious deficiencies; ISC engineers observed a segmentation
76fault during testing. Also, the base version of the library does not
77offer asynchronous transmissions, which are essential for effective
78accounting implementation. Both of these issues were addressed by ISC
79engineers, and the changes have been reported to the FreeRADIUS client
80project. Acceptance of those changes is outside of ISC's control, so
81until those are processed, it is strongly recommended to use the
82FreeRADIUS client with ISC's patches. To download and compile this
83version, please use the following steps:
84
85.. code-block:: console
86
87   $ git clone https://github.com/fxdupont/freeradius-client.git
88   $ cd freeradius-client/
89   $ git checkout iscdev
90   $ ./configure
91   $ make
92   $ sudo make install
93
94Additional parameters may be passed to the configure script, if needed.
95Once installed, the FreeRADIUS client will be installed in
96/usr/local. This is the default path where Kea will be looking for it.
97It can be installed in a different directory; if so,
98make sure to add that path to the configure script when compiling Kea.
99
100STEP 3: Install a recent BOOST version
101
102Kea requires a reasonably recent Boost version. Unfortunately, the
103version available in CentOS 7 is too old, so a newer Boost version is
104necessary. Furthermore, CentOS 7 has an old version of the g++ compiler
105that does not handle the latest Boost versions. Fortunately, Boost 1.65
106meets both requirements; it is both recent enough for Kea and able to be
107compiled using the g++ 4.8 version in CentOS.
108
109To download and compile Boost 1.65, please use the following commands:
110
111.. code-block:: console
112
113   $ wget -nd https://boostorg.jfrog.io/artifactory/main/release/1.65.1/source/boost_1_65_1.tar.gz
114   $ tar -zxvf boost_1_65_1.tar.gz
115   $ cd boost_1_65_1/
116   $ ./bootstrap.sh
117   $ ./b2 --without-python
118   $ sudo ./b2 install
119
120Note that the b2 script may optionally take extra parameters; one of
121them specifies the destination path where the sources are to be
122compiled.
123
124Alternatively, some systems provide newer boost packages. For example,
125CentOS 7 provides ``boost169-devel``. If you install it with
126``yum install boost169-devel``, you will need to point Kea to it with:
127
128.. code-block:: console
129
130   $ ./configure --with-boost-include=/usr/include/boost169 --with-boost-lib-dir=/usr/lib64/boost169
131
132STEP 4: Compile and install Kea
133
134Obtain the Kea sources either by downloading them from the git
135repository or extracting the tarball. Use one of those commands
136to obtain the Kea sources.
137
138Choice 1: get from github
139
140.. code-block:: console
141
142   $ git clone https://github.com/isc-projects/kea.git
143
144Choice 2: get a tarball and extract it
145
146.. parsed-literal::
147
148   $ tar -zxvf kea-|release|.tar.gz
149
150The next step is to extract the premium Kea package that contains the
151RADIUS repository into the Kea sources. After the tarball is extracted,
152the Kea sources should have a premium/ subdirectory.
153
154.. parsed-literal::
155
156     $ cd kea
157     $ tar -zxvf ../kea-premium-radius-|release|.tar.gz
158
159Once this is done, verify that the Kea sources look similar to this:
160
161.. code-block:: console
162
163   $ ls -l
164   total 952
165   -rw-r--r--   1 thomson  staff    6192 Apr 25 17:38 AUTHORS
166   -rw-r--r--   1 thomson  staff   29227 Apr 25 17:38 COPYING
167   -rw-r--r--   1 thomson  staff  360298 Apr 25 20:00 ChangeLog
168   -rw-r--r--   1 thomson  staff     645 Apr 25 17:38 INSTALL
169   -rw-r--r--   1 thomson  staff    5015 Apr 25 17:38 Makefile.am
170   -rw-r--r--   1 thomson  staff     587 Apr 25 17:38 README
171   -rw-r--r--   1 thomson  staff   62323 Apr 25 17:38 configure.ac
172   drwxr-xr-x  12 thomson  staff     408 Apr 26 19:04 doc
173   drwxr-xr-x   7 thomson  staff     238 Apr 25 17:38 examples
174   drwxr-xr-x   5 thomson  staff     170 Apr 26 19:04 ext
175   drwxr-xr-x   8 thomson  staff     272 Apr 26 19:04 m4macros
176   drwxr-xr-x  20 thomson  staff     680 Apr 26 11:22 premium
177   drwxr-xr-x  10 thomson  staff     340 Apr 26 19:04 src
178   drwxr-xr-x  14 thomson  staff     476 Apr 26 19:04 tools
179
180The makefiles must be regenerated using ``autoreconf``.
181
182The next step is to configure Kea, and there are several essential steps
183necessary here. Running ``autoreconf -if`` is necessary to compile the
184premium package that contains RADIUS. Also, the --with-freeradius option
185is necessary to tell Kea where the FreeRADIUS client sources can be
186found. Also, since the non-standard Boost is used, the path to it must
187be specified.
188
189.. code-block:: console
190
191   $ autoreconf -i
192   $ ./configure --with-freeradius=/path/to/freeradius --with-boost-include=/path/to/boost --with-boost-lib-dir=/path/to/boost/state/lib
193
194For example, assuming the FreeRADIUS client was installed in the default
195directory (/usr/local) and the Boost 1.65 sources were compiled in
196/home/thomson/devel/boost1_65_1, the configure path should look as
197follows:
198
199.. code-block:: console
200
201   $ ./configure --with-freeradius=/usr/local \
202         --with-boost-include=/home/thomson/devel/boost_1_65_1 \
203         --with-boost-lib-dir=/home/thomson/devel/boost_1_65_1/stage/lib
204
205After some checks, the configure script should print a report similar to
206the following:
207
208.. parsed-literal::
209
210          Kea source configure results:
211       -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
212
213   Package:
214     Name:              kea
215     Version:           |release|
216     Extended version:  |release| (tarball)
217     OS Family:         Linux
218
219     Hooks directory:   /usr/local/lib/kea/hooks
220     Premium hooks:     yes
221     Included Hooks:    forensic_log flex_id host_cmds subnet_cmds radius host_cache
222
223   C++ Compiler:
224     CXX:             g++ --std=c++11
225     CXX_VERSION:     g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16)
226     CXX_STANDARD:    201103
227     DEFS:            -DHAVE_CONFIG_H
228     CPPFLAGS:         -DOS_LINUX  -DBOOST_ASIO_HEADER_ONLY
229     CXXFLAGS:        -g -O2
230     LDFLAGS:          -lpthread
231     KEA_CXXFLAGS:     -Wall -Wextra -Wnon-virtual-dtor -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare -pthread -Wno-missing-field-initializers -fPIC
232
233   Python:
234     PYTHON_VERSION:  not needed (because kea-shell is disabled)
235
236   Boost:
237     BOOST_VERSION:   1.65.1
238     BOOST_INCLUDES:  -I/home/thomson/devel/boost_1_65_1
239     BOOST_LIBS:      -L/home/thomson/devel/boost_1_65_1/stage/lib  -lboost_system
240
241   OpenSSL:
242     CRYPTO_VERSION:  OpenSSL 1.0.2k  26 Jan 2017
243     CRYPTO_CFLAGS:
244     CRYPTO_INCLUDES:
245     CRYPTO_LDFLAGS:
246     CRYPTO_LIBS:     -lcrypto
247
248   Botan: no
249
250   Log4cplus:
251     LOG4CPLUS_VERSION:  1.1.3
252     LOG4CPLUS_INCLUDES: -I/usr/include
253     LOG4CPLUS_LIBS:     -L/usr/lib -L/usr/lib64 -llog4cplus
254
255   Flex/bison:
256     FLEX:  flex
257     BISON: bison -y
258
259   MySQL:
260     no
261
262   PostgreSQL:
263     no
264
265   Cassandra CQL:
266     no
267   Google Test:
268     no
269   Google Benchmark:
270     no
271
272   FreeRADIUS client:
273     FREERADIUS_INCLUDE:    -I/usr/local/include
274     FREERADIUS_LIB:        -L/usr/local/lib -lfreeradius-client
275     FREERADIUS_DICTIONARY: /usr/local/etc/radiusclient/dictionary
276
277   Developer:
278     Enable Debugging:       no
279     Google Tests:           no
280     Valgrind:               not found
281     C++ Code Coverage:      no
282     Logger checks:          no
283     Generate Documentation: no
284     Parser Generation:      no
285     Kea-shell:              no
286     Perfdhcp:               no
287
288Please make sure that the compilation includes the following:
289
290-  RADIUS listed in Included Hooks;
291-  FreeRADIUS client directories printed and pointing to the right
292   directories;
293-  Boost version at least 1.65.1. The versions available in CentOS 7
294   (1.48 and 1.53) are too old.
295
296Once the configuration is complete, compile Kea using make. If the
297system has more than one core, using the "-j N"
298option is recommended to speed up the build.
299
300.. code-block:: console
301
302       $ make -j5
303       $ sudo make install
304
305.. _hooks-radius-config:
306
307RADIUS Hook Configuration
308~~~~~~~~~~~~~~~~~~~~~~~~~
309
310The RADIUS hook is a library that has to be loaded by either DHCPv4 or
311DHCPv6 Kea servers. Unlike some other available hooks libraries, this one
312takes many parameters. For example, this configuration could be used:
313
314::
315
316     "Dhcp4": {
317
318     # Your regular DHCPv4 configuration parameters here.
319
320     "hooks-libraries": [
321     {
322         # Note that RADIUS requires host-cache for proper operation,
323         # so that library is loaded as well.
324         "library": "/usr/local/lib/kea/hooks/libdhcp_host_cache.so"
325     },
326     {
327         "library": "/usr/local/lib/kea/hooks/libdhc_radius.so",
328         "parameters": {
329
330             # Specify where FreeRADIUS dictionary could be located
331             "dictionary": "/usr/local/etc/freeradius/dictionary",
332
333             # Specify which address to use to communicate with RADIUS servers
334             "bindaddr": "*",
335
336             # more RADIUS parameters here
337         }
338     } ]
339
340RADIUS is a complicated environment. As such, it is not feasible
341to provide a default configuration that works for everyone.
342However, we do have one example that showcases some of the more common
343features. Please see doc/examples/kea4/hooks-radius.json in the Kea
344sources.
345
346The RADIUS hook library supports the following global configuration
347flags, which correspond to FreeRADIUS client library options:
348
349-  ``bindaddr`` (default "*") - specifies the address to be used by the
350   hooks library in communication with RADIUS servers. The "*" special
351   value tells the kernel to choose the address.
352
353-  ``canonical-mac-address`` (default false) - specifies whether MAC
354   addresses in attributes follow the canonical RADIUS format (lowercase
355   pairs of hexadecimal digits separated by '-').
356
357-  ``client-id-pop0`` (default false) - used with flex-id, removes the
358   leading zero (or pair of zeroes in DHCPv6) type in client-id (aka
359   duid in DHCPv6). Implied by client-id-printable.
360
361-  ``client-id-printable`` (default false) - checks whether the
362   client-id/duid content is printable and uses it as is instead of in
363   hexadecimal. Implies client-id-pop0 and extract-duid as 0 and 255 are
364   not printable.
365
366-  ``deadtime`` (default 0) is a mechanism to try unresponsive servers
367   after responsive servers. Its value specifies the number of seconds
368   after which a server is considered not to have answered, so 0
369   disables the mechanism. As the asynchronous communication does not
370   use locks or atomics, it is recommended that you do not use this
371   feature when running in this mode.
372
373-  ``dictionary`` (default set by configure at build time) - is the
374   attribute and value dictionary. Note that it is a critical parameter. You
375   may find dictionary examples in the FreeRADIUS repository under the etc
376   directory.
377
378-  ``extract-duid`` (default true) - extracts the embedded duid from an
379   RFC 4361-compliant DHCPv4 client-id. Implied by client-id-printable.
380
381-  ``identifier-type4`` (default client-id) - specifies the identifier
382   type to build the User-Name attribute. It should be the same as the
383   host identifier, and when the flex-id hook library is used the
384   replace-client-id must be set to true; client-id will be used with
385   client-id-pop0.
386
387-  ``identifier-type6`` (default duid) - specifies the identifier type to
388   build the User-Name attribute. It should be the same as the host
389   identifier, and when the flex-id hook library is used the
390   replace-client-id must be set to true; duid will be used with
391   client-id-pop0.
392
393-  ``realm`` (default "") - is the default realm.
394
395-  ``reselect-subnet-address`` (default false) - uses the Kea reserved
396   address/RADIUS Framed-IP-Address or Framed-IPv6-Address to reselect
397   subnets where the address is not in the subnet range.
398
399-  ``reselect-subnet-pool`` (default false) - uses the Kea
400   client-class/RADIUS Frame-Pool to reselect subnets where no available
401   pool can be found.
402
403-  ``retries`` (default 3) - is the number of retries before trying the
404   next server. Note that it is not supported for asynchronous
405   communication.
406
407-  ``session-history`` (default "") - is the name of the file providing
408   persistent storage for accounting session history.
409
410-  ``timeout`` (default 10) - is the number of seconds during which a
411   response is awaited.
412
413When ``reselect-subnet-pool`` or ``reselect-subnet-address`` is set to
414true at the reception of RADIUS Access-Accept, the selected subnet is
415checked against the client-class name or the reserved address; if it
416does not match, another subnet is selected among matching subnets.
417
418Two services are supported:
419
420-  ``access`` - the authentication service.
421
422-  ``accounting`` - the accounting service.
423
424Configuration of services is divided into two parts:
425
426-  Servers that define RADIUS servers that the library is expected to
427   contact. Each server may have the following items specified:
428
429   -  ``name`` - specifies the IP address of the server (it is
430      possible to use a name which will be resolved, but it is not
431      recommended).
432
433   -  ``port`` (default RADIUS authentication or accounting service) -
434      specifies the UDP port of the server. Note that the
435      FreeRADIUS client library by default uses ports 1812
436      (authorization) and 1813 (accounting). Some server implementations
437      use 1645 (authorization) and 1646 (accounting). The
438      "port" parameter may be used to adjust as needed.
439
440   -  ``secret`` - authenticates messages.
441
442   There may be up to eight servers. Note that when no server is
443   specified, the service is disabled.
444
445-  Attributes which define additional information that the Kea server
446   will send to a RADIUS server. The parameter must be identified either
447   by a name or type. Its value can be specified in one of three
448   possible ways: data (which defines a plain text value), raw (which
449   defines the value in hex), or expr (which defines an expression,
450   which will be evaluated for each incoming packet independently).
451
452   -  ``name`` - the name of the attribute.
453
454   -  ``type`` - the type of the attribute. Either the type or the name must be
455      provided, and the attribute must be defined in the dictionary.
456
457   -  ``data`` - the first of three ways to specify the attribute
458      content. The data entry is parsed by the FreeRADIUS library, so
459      values defined in the dictionary of the attribute may be used.
460
461   -  ``raw`` - the second of three ways to specify the attribute
462      content; it specifies the content in hexadecimal. Note that it
463      does not work with integer-content attributes (date, integer, and
464      IPv4 address); a string-content attribute (string, IPv6 address,
465      and IPv6 prefix) is required.
466
467   -  ``expr`` - the last way to specify the attribute content. It
468      specifies an evaluation expression which must return a not-empty
469      string when evaluated with the DHCP query packet. Currently this
470      is restricted to the access service.
471
472For example, to specify a single access server available on localhost
473that uses "xyz123" as a secret, and tell Kea to send three additional
474attributes (Password, Connect-Info, and Configuration-Token), the
475following snippet could be used:
476
477::
478
479   "parameters": {
480
481       # Other RADIUS parameters here
482
483       "access": {
484
485           # This starts the list of access servers
486           "servers": [
487           {
488               # These are parameters for the first (and only) access server
489               "name": "127.0.0.1",
490               "port": 1812,
491               "secret": "xyz123"
492           }
493           # Additional access servers could be specified here
494           ],
495
496           # This defines a list of additional attributes Kea will send to each
497           # access server in Access-Request.
498           "attributes": [
499           {
500               # This attribute is identified by name (must be present in the
501               # dictionary) and has static value (i.e. the same value will be
502               # sent to every server for every packet)
503               "name": "Password",
504               "data": "mysecretpassword"
505           },
506           {
507               # It is also possible to specify an attribute using its type,
508               # rather than a name. 77 is Connect-Info. The value is specified
509               # using hex. Again, this is a static value. It will be sent the
510               # same for every packet and to every server.
511               "type": 77,
512               "raw": "65666a6a71"
513           },
514           {
515               # This example shows how an expression can be used to send dynamic
516               # value. The expression (see Section 13) may take any value from
517               # the incoming packet or even its metadata (e.g. the interface
518               # it was received over from)
519               "name": "Configuration-Token",
520               "expr": "hexstring(pkt4.mac,':')"
521           }
522           ] # End of attributes
523       }, # End of access
524
525       # Accounting parameters.
526       "accounting": {
527           # This starts the list of accounting servers
528           "servers": [
529           {
530               # These are parameters for the first (and only) accounting server
531               "name": "127.0.0.1",
532               "port": 1813,
533               "secret": "sekret"
534           }
535           # Additional accounting servers could be specified here
536           ]
537       }
538
539   }
540
541Customization is sometimes required for certain attributes by devices belonging
542to various vendors. This is a great way to leverage the expression evaluation
543mechanism. For example, MAC addresses which you might use as a convenience
544value for the User-Name attribute most likely will appear in colon-hexadecimal
545notation ``de:ad:be:ef:ca:fe``, but it might need to be expressed in:
546
547* hyphen-hexadecimal notation ``de-ad-be-ef-ca-fe``
548
549.. code-block:: json
550
551   {
552      "parameters": {
553         "access": {
554            "attributes": [
555               {
556                  "name": "User-Name",
557                  "expr": "hexstring(pkt4.mac, '-')"
558               }
559            ]
560         }
561      }
562   }
563
564* period-separated hexadecimal notation ``dead.beef.cafe``, preferred by Cisco devices
565
566.. code-block:: json
567
568   {
569      "parameters": {
570         "access": {
571            "attributes": [
572               {
573                  "name": "User-Name",
574                  "expr": "concat(concat(concat(substring(hexstring(pkt4.mac, ''), 0, 4), '.'), concat(substring(hexstring(pkt4.mac, ''), 4, 4), '.'), concat(substring(hexstring(pkt4.mac, ''), 8, 4), '.'))"
575               }
576            ]
577         }
578      }
579   }
580
581
582For the RADIUS hooks library to operate properly in DHCPv4,
583the Host Cache hooks library must also be loaded. The reason for this
584is somewhat complex. In a typical deployment, the DHCP clients send
585their packets via DHCP relay which inserts certain Relay Agent
586Information options, such as circuit-id or remote-id. The values of
587those options are then used by the Kea DHCP server to formulate the
588necessary attributes in the Access-Request message sent to the RADIUS
589server. However, once the DHCP client gets its address, it then renews
590by sending packets directly to the DHCP server. As a result, the relays
591are not able to insert their RAI options, and the DHCP server cannot send
592the Access-Request queries to the RADIUS server by using just the
593information from incoming packets. Kea needs to keep the information
594received during the initial Discover/Offer exchanges and use it again
595later when sending accounting messages.
596
597This mechanism is implemented based on user context in host
598reservations. (See :ref:`user-context` and :ref:`user-context-hooks` for
599details.) The host cache mechanism allows the information retrieved by
600RADIUS to be stored and later used for sending accounting and access
601queries to the RADIUS server. In other words, the host-cache mechanism
602is mandatory, unless administrators do not want RADIUS communication for messages
603other than Discover and the first Request from each client.
604