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
|
.. ischooklib:: libdhcp_limits.so
.. _hooks-limits:
``libdhcp_limits.so``: Limits to Manage Lease Allocation and Packet Processing
==============================================================================
This hook library enables two types of limits:
1. Lease limiting: allow a maximum of ``n`` leases assigned at any one time.
2. Rate limiting: allow a maximum of ``n`` packets per ``time_unit`` to receive a response.
.. note::
:ischooklib:`libdhcp_limits.so` is available only to ISC customers with
a paid support contract. For more information on subscription options,
please complete the form at https://www.isc.org/contact.
.. _hooks-limits-configuration:
Configuration
~~~~~~~~~~~~~
The following examples are for :iscman:`kea-dhcp6`, but they apply equally to
:iscman:`kea-dhcp4`. The wildcards ``"<limit-type>"`` and ``"<limit-value>"`` need to be replaced
with the respective keys and values for each limit type described in the sections following this
one.
The library can be loaded by both :iscman:`kea-dhcp4` and :iscman:`kea-dhcp6` servers by adding its path in the
``"hooks-libraries"`` element of the server's configuration.
.. code-block:: json
{
"Dhcp6": {
"hooks-libraries": [
{
"library": "/usr/local/lib/libdhcp_limits.so"
}
]
}
}
This alone does not limit anything. The desired limits are added to the user context in the
configuration portion of the element that identifies the clients to be limited: a client class or a
subnet. Upon reconfiguration, if Kea picked up on the configured limits, it logs one line for
each configured limit. The log message contains ``LIMITS_CONFIGURED`` in its identifier.
This is how a lease limit is defined for a client class:
.. code-block:: json
{
"Dhcp6": {
"client-classes": [
{
"name": "cable-modem-1",
"test": "option[123].hex == 0x000C4B1E",
"user-context": {
"limits": {
"<limit>": "<limit-value>"
}
}
}
]
}
}
This is how a lease limit is defined for a global subnet:
.. code-block:: json
{
"Dhcp6": {
"subnet6": [
{
"id": 1,
"subnet": "2001:db8::/64",
"user-context": {
"limits": {
"<limit>": "<limit-value>"
}
}
}
]
}
}
This is how a lease limit is defined for a subnet inside a shared network:
.. code-block:: json
{
"Dhcp6": {
"shared-networks": [
{
"subnet6": [
{
"id": 1,
"subnet": "2001:db8::/64",
"user-context": {
"limits": {
"<limit>": "<limit-value>"
}
}
}
]
}
]
}
}
.. note::
The Limits hook library uses the class name to identify a client class and the subnet ID to
identify a subnet. Changing a test expression in a client class or the network range of a
subnet while leaving the name or ID unchanged does not reset the lease count for the
respective client class or subnet. To reset the lease count, change the client class name
or the subnet ID.
.. note::
Database connection retries are not attempted on startup if the
:ischooklib:`libdhcp_limits.so` is loaded because the hook library requires a
valid connection to the database to check if JSON format is supported and to
recount class limits.
.. _hooks-limits-lease-limiting:
Lease Limiting
~~~~~~~~~~~~~~
It is possible to limit the number of leases that a group of clients can get from a Kea DHCP server
or from a set of collaborating Kea DHCP servers.
The value of a lease limit can be specified as an unsigned integer in 32 bits, i.e. between ``0`` and
``4,294,967,295``. Each lease type can be limited individually. IPv4 leases and IPv6 IA_NA leases
are limited through the ``"address-limit"`` configuration entry. IPv6 IA_PD leases are limited
through the ``"prefix-limit"`` configuration entry. Here are some examples:
* ``"address-limit": 4``
* ``"prefix-limit": 2``
For lease limiting, client classes and the associated lease counts - which are
checked against the configured limits - are updated for each lease in the following hook callouts:
* ``lease4_select``
* ``lease4_renew``
* ``lease6_select``
* ``lease6_renew``
* ``lease6_rebind``
As a result, classes for which ``"only-if-required"`` is "true" cannot be lease-limited.
Please refer to :ref:`the classification steps <classify-classification-steps>` for more information on which
client classes can be used to limit the number of leases.
.. note::
Under load, a Kea DHCP server may allocate more leases than the limit strictly allows. This only has a chance of
happening during high traffic surges, coming from clients belonging to the same class or the
same subnet, depending on what is limited. Users may be interested in following the development of
`atomic lease limits <https://gitlab.isc.org/isc-projects/kea/-/issues/2449>`__ in ISC's GitLab instance.
.. _hooks-limits-rate-limiting:
Rate Limiting
~~~~~~~~~~~~~
It is possible to limit the frequency or rate at which inbound packets receive a response.
The value of a rate limit can be specified in the format ``"<p> packets per <time-unit>"``. ``<p>``
is any number that can be represented by an unsigned integer in 32 bits, i.e. between ``0`` and
``4,294,967,295``. ``<time-unit>`` can be any of ``second``, ``minute``, ``hour``, ``day``,
``week``, ``month``, or ``year``. A ``month`` is considered to be 30 days for
simplicity; similarly, a ``year`` is 365 days for limiting purposes. This syntax
covers a wide range of rates, from one lease per year to four billion leases per
second. This value is assigned to the ``"rate-limit"`` configuration entry.
Here are some examples:
* ``"rate-limit": 1 packet per second``
* ``"rate-limit": 4 packets per minute``
* ``"rate-limit": 16 packets per hour``
The configured value of ``0`` packets is a convenient way of disabling packet processing for certain
clients entirely. As such, it means its literal value and is not a special value for disabling
limiting altogether, as might be imagined. Disabling limiting entirely is achieved by removing
the ``"rate-limit"`` leaf configuration entry, the ``"limits"`` map or user context
around it, or the hook library configuration. The same applies to the value of ``0`` in lease
limiting. However, that use case is best achieved with rate limiting; it puts less computational
strain on Kea, since the action of dropping the request or sending a NAK is decided earlier.
In terms of rate limiting, client classes are evaluated at the ``pkt4_receive`` and the
``pkt6_receive`` callout, respectively, so that rate limits are checked as early as possible in the
packet-processing cycle. Thus, only those classes which are assigned to the packet solely via an
independent test expression can be used. Classes that depend on host reservations or the special
``BOOTP`` or ``KNOWN`` classes, and classes that are marked with ``"only-if-required": true``,
cannot be rate limited. See :ref:`the classification steps <classify-classification-steps>` for
more details on which client classes can be used to limit the packet rate.
Rate limits based on subnet are enforced only on the initially selected subnet for a given packet.
If the selected subnet is subsequently changed, as may be the case for subnets in a
shared network or when reselection is enabled in libraries such as the RADIUS hook, rate
limits on the newly selected subnet are ignored. In other words, packets are gated only by
the rate limit on the original subnet.
.. note::
It may seem logical to think that assigning a rate limit of ``n`` packets per time unit results
in ``n`` DORA or ``n`` SARR exchanges. However, by default, all inbound packets are counted - meaning
that a full message exchange accounts for two packets. To achieve the effect of counting an
exchange only once, use client-class rate-limiting with a test expression that binds
``pkt4.msgtype`` to DHCPDISCOVER messages or ``pkt6.msgtype`` to SOLICIT messages.
|