summaryrefslogtreecommitdiffstats
path: root/doc/sphinx/arm/hooks-radius.rst
blob: fc8c44db026e67e8f0c3cd0bbb4efa3db79674bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
.. _hooks-radius:

``radius``: RADIUS Server Support
=================================

This hook library allows Kea to interact with two types of RADIUS
servers: access and accounting. Although the most common DHCP and RADIUS
integration is done on the DHCP relay-agent level (DHCP clients send
DHCP packets to DHCP relays; those relays contact the RADIUS server and
depending on the response either send the packet to the DHCP server or
drop it), it does require DHCP relay hardware to support RADIUS
communication. Also, even if the relay has the necessary support, it is
often not flexible enough to send and receive additional RADIUS
attributes. As such, the alternative looks more appealing: to extend the
DHCP server to talk to RADIUS directly. That is the goal of this library.

.. note::

   This library can only be loaded by the ``kea-dhcp4`` or the
   ``kea-dhcp6`` process.

The major feature of this hook library is the ability to use RADIUS
authorization. When a DHCP packet is received, the Kea server sends an
Access-Request to the RADIUS server and waits for a response. The server
then sends back either an Access-Accept with specific client attributes,
or an Access-Reject. There are two cases supported here: first, the
Access-Accept includes a Framed-IP-Address attribute (for DHCPv4) or a
Framed-IPv6-Address attribute (for DHCPv6), which are interpreted by Kea as
instructions to assign the specified IPv4 or IPv6 address. This
effectively means RADIUS can act as an address-reservation database.

The second supported case is the ability to assign clients to specific
pools based on a RADIUS response. In this case, the RADIUS server sends
back an Access-Accept with a Framed-Pool attribute.
For both DHCPv4 and DHCPv6, Kea interprets this attribute as a client class.
With the addition of the ability to limit access to pools to
specific classes (see :ref:`classification-pools`), RADIUS can be
used to force the client to be assigned a dynamic address from a
specific pool. Furthermore, the same mechanism can be used to control
what kind of options the client gets if there are DHCP options
specified for a particular class.

.. _hooks-radius-install:

Compilation and Installation of the RADIUS Hook
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following section describes how to compile and install the software
on CentOS 7.0. Other systems may differ slightly.

.. note::

   ISC provides Kea software and hooks in convenient-to-use
   native Alpine, deb, and RPM packages. This includes the RADIUS hook and the required patched version
   of the FreeRADIUS client library. The software compilation for RADIUS is complicated; unless
   there are specific reasons to compile it, administrators should seriously consider using
   native packages.

STEP 1: Install dependencies

Several tools are needed to build the dependencies and Kea itself. The
following commands should install them:

.. code-block:: console

   $ sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
   $ sudo yum install gcc-g++ openssl-devel log4cplus-devel wget git

STEP 2: Install FreeRADIUS

The Kea RADIUS hook library uses the FreeRADIUS client library to
conduct RADIUS communication. Unfortunately, the standard 1.1.7 release
available from the project website https://freeradius.org/sub_projects/
has several serious deficiencies; ISC engineers observed a segmentation
fault during testing. Also, the base version of the library does not
offer asynchronous transmissions, which are essential for effective
accounting implementation. Both of these issues were addressed by ISC
engineers, and the changes have been reported to the FreeRADIUS client
project. Acceptance of those changes is outside of ISC's control, so
until those are processed, it is strongly recommended to use the
FreeRADIUS client with ISC's patches. To download and compile this
version, please use the following steps:

.. code-block:: console

   $ git clone https://github.com/fxdupont/freeradius-client.git
   $ cd freeradius-client/
   $ git checkout iscdev
   $ ./configure
   $ make
   $ sudo make install

Additional parameters may be passed to the configure script, if needed.
The FreeRADIUS client will be installed in
/usr/local, which is the default path where Kea will look for it.
It can be installed in a different directory; if so,
make sure to add that path to the configure script when compiling Kea.

STEP 3: Install a recent Boost version

Kea requires a reasonably recent Boost version. Unfortunately, the
version available in CentOS 7 is too old, so a newer Boost version is
necessary. Furthermore, CentOS 7 has an old version of the g++ compiler
that does not handle the latest Boost versions. Fortunately, Boost 1.65
meets both requirements; it is both recent enough for Kea and can be
compiled using the g++ 4.8 version in CentOS.

To download and compile Boost 1.65, please use the following commands:

.. code-block:: console

   $ wget -nd https://boostorg.jfrog.io/artifactory/main/release/1.65.1/source/boost_1_65_1.tar.gz
   $ tar -zxvf boost_1_65_1.tar.gz
   $ cd boost_1_65_1/
   $ ./bootstrap.sh
   $ ./b2 --without-python
   $ sudo ./b2 install

Note that the ``b2`` script may optionally take extra parameters; one of
them specifies the destination path where the sources are to be
compiled.

Alternatively, some systems provide newer Boost packages. For example,
CentOS 7 provides ``boost169-devel``. If it is installed with
``yum install boost169-devel``, Kea must be pointed to it with:

.. code-block:: console

   $ ./configure --with-boost-include=/usr/include/boost169 --with-boost-lib-dir=/usr/lib64/boost169

STEP 4: Compile and install Kea

Obtain the Kea sources either by downloading them from the git
repository or extracting the tarball. Use one of these commands
to obtain the Kea sources.

Choice 1: Retrieve from GitHub

.. code-block:: console

   $ git clone https://github.com/isc-projects/kea.git

Choice 2: Retrieve a tarball and extract it

.. parsed-literal::

   $ tar -zxvf kea-|release|.tar.gz

The next step is to extract the premium Kea package that contains the
RADIUS repository into the Kea sources. After the tarball is extracted,
the Kea sources should have a premium/ subdirectory.

.. parsed-literal::

     $ cd kea
     $ tar -zxvf ../kea-premium-radius-|release|.tar.gz

Once this is done, verify that the Kea sources look similar to this:

.. code-block:: console

   $ ls -l
   total 952
   -rw-r--r--   1 thomson  staff    6192 Apr 25 17:38 AUTHORS
   -rw-r--r--   1 thomson  staff   29227 Apr 25 17:38 COPYING
   -rw-r--r--   1 thomson  staff  360298 Apr 25 20:00 ChangeLog
   -rw-r--r--   1 thomson  staff     645 Apr 25 17:38 INSTALL
   -rw-r--r--   1 thomson  staff    5015 Apr 25 17:38 Makefile.am
   -rw-r--r--   1 thomson  staff     587 Apr 25 17:38 README
   -rw-r--r--   1 thomson  staff   62323 Apr 25 17:38 configure.ac
   drwxr-xr-x  12 thomson  staff     408 Apr 26 19:04 doc
   drwxr-xr-x   7 thomson  staff     238 Apr 25 17:38 examples
   drwxr-xr-x   5 thomson  staff     170 Apr 26 19:04 ext
   drwxr-xr-x   8 thomson  staff     272 Apr 26 19:04 m4macros
   drwxr-xr-x  20 thomson  staff     680 Apr 26 11:22 premium
   drwxr-xr-x  10 thomson  staff     340 Apr 26 19:04 src
   drwxr-xr-x  14 thomson  staff     476 Apr 26 19:04 tools

The makefiles must be regenerated using ``autoreconf``.

The next step is to configure Kea, and there are several essential steps
necessary here. Running ``autoreconf -if`` is necessary to compile the
premium package that contains RADIUS. Also, the ``--with-freeradius`` option
is necessary to tell Kea where the FreeRADIUS client sources can be
found. Also, since the non-standard Boost is used, the path to it must
be specified.

.. code-block:: console

   $ autoreconf -i
   $ ./configure --with-freeradius=/path/to/freeradius --with-boost-include=/path/to/boost --with-boost-lib-dir=/path/to/boost/state/lib

For example, assuming the FreeRADIUS client was installed in the default
directory (/usr/local) and the Boost 1.65 sources were compiled in
/home/thomson/devel/boost1_65_1, the configure path should look as
follows:

.. code-block:: console

   $ ./configure --with-freeradius=/usr/local \
         --with-boost-include=/home/thomson/devel/boost_1_65_1 \
         --with-boost-lib-dir=/home/thomson/devel/boost_1_65_1/stage/lib

After some checks, the configure script should print a report similar to
the following:

.. parsed-literal::

          Kea source configure results:
       -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

   Package:
     Name:              kea
     Version:           |release|
     Extended version:  |release| (tarball)
     OS Family:         Linux

     Hooks directory:   /usr/local/lib/kea/hooks
     Premium hooks:     yes
     Included Hooks:    forensic_log flex_id host_cmds subnet_cmds radius host_cache

   C++ Compiler:
     CXX:             g++ --std=c++11
     CXX_VERSION:     g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16)
     CXX_STANDARD:    201103
     DEFS:            -DHAVE_CONFIG_H
     CPPFLAGS:         -DOS_LINUX  -DBOOST_ASIO_HEADER_ONLY
     CXXFLAGS:        -g -O2
     LDFLAGS:          -lpthread
     KEA_CXXFLAGS:     -Wall -Wextra -Wnon-virtual-dtor -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare -pthread -Wno-missing-field-initializers -fPIC

   Python:
     PYTHON_VERSION:  not needed (because kea-shell is disabled)

   Boost:
     BOOST_VERSION:   1.65.1
     BOOST_INCLUDES:  -I/home/thomson/devel/boost_1_65_1
     BOOST_LIBS:      -L/home/thomson/devel/boost_1_65_1/stage/lib  -lboost_system

   OpenSSL:
     CRYPTO_VERSION:  OpenSSL 1.0.2k  26 Jan 2017
     CRYPTO_CFLAGS:
     CRYPTO_INCLUDES:
     CRYPTO_LDFLAGS:
     CRYPTO_LIBS:     -lcrypto

   Botan: no

   Log4cplus:
     LOG4CPLUS_VERSION:  1.1.3
     LOG4CPLUS_INCLUDES: -I/usr/include
     LOG4CPLUS_LIBS:     -L/usr/lib -L/usr/lib64 -llog4cplus

   Flex/bison:
     FLEX:  flex
     BISON: bison -y

   MySQL:
     no

   PostgreSQL:
     no

   Google Test:
     no

   FreeRADIUS client:
     FREERADIUS_INCLUDE:    -I/usr/local/include
     FREERADIUS_LIB:        -L/usr/local/lib -lfreeradius-client
     FREERADIUS_DICTIONARY: /usr/local/etc/radiusclient/dictionary

   Developer:
     Enable Debugging:       no
     Google Tests:           no
     Valgrind:               not found
     C++ Code Coverage:      no
     Logger checks:          no
     Generate Documentation: no
     Parser Generation:      no
     Kea-shell:              no
     Perfdhcp:               no

Please make sure that the compilation includes the following:

-  RADIUS listed in Included Hooks;
-  FreeRADIUS client directories printed and pointing to the right
   directories;
-  Boost version at least 1.65.1. The versions available in CentOS 7
   (1.48 and 1.53) are too old.

Once the configuration is complete, compile Kea using ``make``. If the
system has more than one core, using the ``-jN``
option is recommended to speed up the build.

.. code-block:: console

       $ make -j5
       $ sudo make install

.. _hooks-radius-config:

RADIUS Hook Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~

The RADIUS hook is a library that must be loaded by either DHCPv4 or
DHCPv6 Kea servers. Unlike some other available hook libraries, this one
takes many parameters. For example, this configuration could be used:

::

     "Dhcp4": {

     # Your regular DHCPv4 configuration parameters here.

     "hooks-libraries": [
     {
         # Note that RADIUS requires host-cache for proper operation,
         # so that library is loaded as well.
         "library": "/usr/local/lib/kea/hooks/libdhcp_host_cache.so"
     },
     {
         "library": "/usr/local/lib/kea/hooks/libdhc_radius.so",
         "parameters": {

             # Specify where FreeRADIUS dictionary could be located
             "dictionary": "/usr/local/etc/freeradius/dictionary",

             # Specify which address to use to communicate with RADIUS servers
             "bindaddr": "*",

             # more RADIUS parameters here
         }
     } ]

RADIUS is a complicated environment. As such, it is not feasible
to provide a default configuration that works for everyone.
However, we do have an example that showcases some of the more common
features. Please see ``doc/examples/kea4/hooks-radius.json`` in the Kea
sources.

The RADIUS hook library supports the following global configuration
flags, which correspond to FreeRADIUS client library options:

-  ``bindaddr`` (default ``*``) - specifies the address to be used by the
   hook library in communication with RADIUS servers. The ``*`` special
   value tells the kernel to choose the address.

-  ``canonical-mac-address`` (default ``false``) - specifies whether MAC
   addresses in attributes follow the canonical RADIUS format (lowercase
   pairs of hexadecimal digits separated by ``-``).

-  ``client-id-pop0`` (default ``false``) - used with ``flex-id``, removes the
   leading zero (or pair of zeroes in DHCPv6) type in ``client-id``
   (``duid`` in DHCPv6). Implied by ``client-id-printable``.

-  ``client-id-printable`` (default ``false``) - checks whether the
   ``client-id``/``duid`` content is printable and uses it as is instead of in
   hexadecimal. Implies ``client-id-pop0`` and ``extract-duid`` as 0 and 255 are
   not printable.

-  ``deadtime`` (default ``0``) - is a mechanism to try unresponsive servers
   after responsive servers. Its value specifies the number of seconds
   after which a server is considered not to have answered, so 0
   disables the mechanism. As the asynchronous communication does not
   use locks or atomics, it is recommended not to use this
   feature when running in this mode.

-  ``dictionary`` (default set by configure at build time) - is the
   attribute and value dictionary. Note that it is a critical parameter.
   Dictionary examples can be found in the FreeRADIUS repository under the etc/
   directory.

-  ``extract-duid`` (default ``true``) - extracts the embedded ``duid`` from an
   RFC 4361-compliant DHCPv4 ``client-id``. Implied by ``client-id-printable``.

-  ``identifier-type4`` (default ``client-id``) - specifies the identifier
   type to build the User-Name attribute. It should be the same as the
   host identifier, and when the ``flex-id`` hook library is used the
   ``replace-client-id`` must be set to ``true``; ``client-id`` is used with
   ``client-id-pop0``.

-  ``identifier-type6`` (default ``duid``) - specifies the identifier type to
   build the User-Name attribute. It should be the same as the host
   identifier, and when the ``flex-id`` hook library is used the
   ``replace-client-id`` must be set to ``true``; ``duid`` is used with
   ``client-id-pop0``.

-  ``realm`` (default ``""``) - is the default realm.

-  ``reselect-subnet-address`` (default ``false``) - uses the Kea reserved
   address/RADIUS Framed-IP-Address or Framed-IPv6-Address to reselect
   subnets where the address is not in the subnet range.

-  ``reselect-subnet-pool`` (default ``false``) - uses the Kea
   ``client-class``/RADIUS Frame-Pool to reselect subnets where no available
   pool can be found.

-  ``retries`` (default ``3``) - is the number of retries before trying the
   next server. Note that it is not supported for asynchronous
   communication.

-  ``session-history`` (default ``""``) - is the name of the file providing
   persistent storage for accounting session history.

-  ``timeout`` (default ``10``) - is the number of seconds during which a
   response is awaited.

When ``reselect-subnet-pool`` or ``reselect-subnet-address`` is set to
``true`` at the reception of RADIUS Access-Accept, the selected subnet is
checked against the ``client-class`` name or the reserved address; if it
does not match, another subnet is selected among matching subnets.

Two services are supported:

-  ``access`` - the authentication service.

-  ``accounting`` - the accounting service.

Configuration of services is divided into two parts:

-  Servers that define RADIUS servers that the library is expected to
   contact. Each server may have the following items specified:

   -  ``name`` - specifies the IP address of the server (it is
      possible to use a name which will be resolved, but it is not
      recommended).

   -  ``port`` (default RADIUS authentication or accounting service) -
      specifies the UDP port of the server. Note that the
      FreeRADIUS client library by default uses ports 1812
      (authorization) and 1813 (accounting). Some server implementations
      use 1645 (authorization) and 1646 (accounting). The
      ``port`` parameter may be used to adjust as needed.

   -  ``secret`` - authenticates messages.

   There may be up to eight servers. Note that when no server is
   specified, the service is disabled.

-  Attributes which define additional information that the Kea server
   sends to a RADIUS server. The parameter must be identified either
   by a name or type. Its value can be specified in one of three
   possible ways: ``data`` (which defines a plain text value), ``raw`` (which
   defines the value in hex), or ``expr`` (which defines an expression
   that is evaluated for each incoming packet independently).

   -  ``name`` - the name of the attribute.

   -  ``type`` - the type of the attribute. Either the type or the name must be
      provided, and the attribute must be defined in the dictionary.

   -  ``data`` - the first of three ways to specify the attribute
      content. The data entry is parsed by the FreeRADIUS library, so
      values defined in the dictionary of the attribute may be used.

   -  ``raw`` - the second of three ways to specify the attribute
      content; it specifies the content in hexadecimal. Note that it
      does not work with integer-content attributes (date, integer, and
      IPv4 address); a string-content attribute (string, IPv6 address,
      and IPv6 prefix) is required.

   -  ``expr`` - the last way to specify the attribute content. It
      specifies an evaluation expression which must return a not-empty
      string when evaluated with the DHCP query packet. Currently this
      is restricted to the access service.

For example, to specify a single access server available on localhost
that uses "xyz123" as a secret, and tell Kea to send three additional
attributes (Password, Connect-Info, and Configuration-Token), the
following snippet could be used:

::

   "parameters": {

       # Other RADIUS parameters here

       "access": {

           # This starts the list of access servers
           "servers": [
           {
               # These are parameters for the first (and only) access server
               "name": "127.0.0.1",
               "port": 1812,
               "secret": "xyz123"
           }
           # Additional access servers could be specified here
           ],

           # This defines a list of additional attributes Kea will send to each
           # access server in Access-Request.
           "attributes": [
           {
               # This attribute is identified by name (must be present in the
               # dictionary) and has static value (i.e. the same value will be
               # sent to every server for every packet)
               "name": "Password",
               "data": "mysecretpassword"
           },
           {
               # It is also possible to specify an attribute using its type,
               # rather than a name. 77 is Connect-Info. The value is specified
               # using hex. Again, this is a static value. It will be sent the
               # same for every packet and to every server.
               "type": 77,
               "raw": "65666a6a71"
           },
           {
               # This example shows how an expression can be used to send dynamic
               # value. The expression (see Section 13) may take any value from
               # the incoming packet or even its metadata (e.g. the interface
               # it was received over from)
               "name": "Configuration-Token",
               "expr": "hexstring(pkt4.mac,':')"
           }
           ] # End of attributes
       }, # End of access

       # Accounting parameters.
       "accounting": {
           # This starts the list of accounting servers
           "servers": [
           {
               # These are parameters for the first (and only) accounting server
               "name": "127.0.0.1",
               "port": 1813,
               "secret": "sekret"
           }
           # Additional accounting servers could be specified here
           ]
       }

   }

Customization is sometimes required for certain attributes by devices belonging
to various vendors. This is a great way to leverage the expression evaluation
mechanism. For example, MAC addresses which might be used as a convenience
value for the User-Name attribute are most likely to appear in colon-hexadecimal
notation (``de:ad:be:ef:ca:fe``), but they might need to be expressed in
hyphen-hexadecimal notation (``de-ad-be-ef-ca-fe``). Here's how to specify that:

.. code-block:: json

   {
      "parameters": {
         "access": {
            "attributes": [
               {
                  "name": "User-Name",
                  "expr": "hexstring(pkt4.mac, '-')"
               }
            ]
         }
      }
   }

And here's how to specify period-separated hexadecimal notation (``dead.beef.cafe``), preferred by Cisco devices:

.. code-block:: json

   {
      "parameters": {
         "access": {
            "attributes": [
               {
                  "name": "User-Name",
                  "expr": "concat(concat(concat(substring(hexstring(pkt4.mac, ''), 0, 4), '.'), concat(substring(hexstring(pkt4.mac, ''), 4, 4), '.'), concat(substring(hexstring(pkt4.mac, ''), 8, 4), '.'))"
               }
            ]
         }
      }
   }


For the RADIUS hook library to operate properly in DHCPv4,
the Host Cache hook library must also be loaded. The reason for this
is somewhat complex. In a typical deployment, the DHCP clients send
their packets via DHCP relay, which inserts certain Relay Agent
Information options, such as ``circuit-id`` or ``remote-id``. The values of
those options are then used by the Kea DHCP server to formulate the
necessary attributes in the Access-Request message sent to the RADIUS
server. However, once the DHCP client gets its address, it then renews
by sending packets directly to the DHCP server. As a result, the relays
are not able to insert their RAI options, and the DHCP server cannot send
the Access-Request queries to the RADIUS server by using just the
information from incoming packets. Kea needs to keep the information
received during the initial Discover/Offer exchanges and use it again
later when sending accounting messages.

This mechanism is implemented based on user context in host
reservations. (See :ref:`user-context` and :ref:`user-context-hooks` for
details.) The host-cache mechanism allows the information retrieved by
RADIUS to be stored and later used for sending accounting and access
queries to the RADIUS server. In other words, the host-cache mechanism
is mandatory, unless administrators do not want RADIUS communication for messages
other than Discover and the first Request from each client.

.. note::

   Currently the RADIUS hook library is incompatible with the
   ``early-global-reservations-lookup`` global parameter i.e.
   setting the parameter to ``true`` raises an error when the
   hook library is loaded.