1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * SPDX-License-Identifier: MPL-2.0
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 #ifndef DNS_RRL_H
15 #define DNS_RRL_H 1
16 
17 /*
18  * Rate limit DNS responses.
19  */
20 
21 #include <inttypes.h>
22 #include <stdbool.h>
23 
24 #include <isc/lang.h>
25 
26 #include <dns/fixedname.h>
27 #include <dns/rdata.h>
28 #include <dns/types.h>
29 
30 ISC_LANG_BEGINDECLS
31 
32 /*
33  * Memory allocation or other failures.
34  */
35 #define DNS_RRL_LOG_FAIL ISC_LOG_WARNING
36 /*
37  * dropped or slipped responses.
38  */
39 #define DNS_RRL_LOG_DROP ISC_LOG_INFO
40 /*
41  * Major events in dropping or slipping.
42  */
43 #define DNS_RRL_LOG_DEBUG1 ISC_LOG_DEBUG(3)
44 /*
45  * Limit computations.
46  */
47 #define DNS_RRL_LOG_DEBUG2 ISC_LOG_DEBUG(4)
48 /*
49  * Even less interesting.
50  */
51 #define DNS_RRL_LOG_DEBUG3 ISC_LOG_DEBUG(9)
52 
53 #define DNS_RRL_LOG_ERR_LEN 64
54 #define DNS_RRL_LOG_BUF_LEN                                        \
55 	(sizeof("would continue limiting") + DNS_RRL_LOG_ERR_LEN + \
56 	 sizeof(" responses to ") + ISC_NETADDR_FORMATSIZE +       \
57 	 sizeof("/128 for IN ") + DNS_RDATATYPE_FORMATSIZE +       \
58 	 DNS_NAME_FORMATSIZE)
59 
60 typedef struct dns_rrl_hash dns_rrl_hash_t;
61 
62 /*
63  * Response types.
64  */
65 typedef enum {
66 	DNS_RRL_RTYPE_FREE = 0,
67 	DNS_RRL_RTYPE_QUERY,
68 	DNS_RRL_RTYPE_REFERRAL,
69 	DNS_RRL_RTYPE_NODATA,
70 	DNS_RRL_RTYPE_NXDOMAIN,
71 	DNS_RRL_RTYPE_ERROR,
72 	DNS_RRL_RTYPE_ALL,
73 	DNS_RRL_RTYPE_TCP,
74 } dns_rrl_rtype_t;
75 
76 /*
77  * A rate limit bucket key.
78  * This should be small to limit the total size of the database.
79  * The hash of the qname should be wide enough to make the probability
80  * of collisions among requests from a single IP address block less than 50%.
81  * We need a 32-bit hash value for 10000 qps (e.g. random qnames forged
82  * by attacker) to collide with legitimate qnames from the target with
83  * probability at most 1%.
84  */
85 #define DNS_RRL_MAX_PREFIX 64
86 typedef union dns_rrl_key dns_rrl_key_t;
87 struct dns__rrl_key {
88 	uint32_t	ip[DNS_RRL_MAX_PREFIX / 32];
89 	uint32_t	qname_hash;
90 	dns_rdatatype_t qtype;
91 	uint8_t		qclass;
92 	unsigned int	rtype : 4; /* dns_rrl_rtype_t */
93 	unsigned int	ipv6  : 1;
94 };
95 union dns_rrl_key {
96 	struct dns__rrl_key s;
97 	uint16_t	    w[sizeof(struct dns__rrl_key) / sizeof(uint16_t)];
98 };
99 
100 /*
101  * A rate-limit entry.
102  * This should be small to limit the total size of the table of entries.
103  */
104 typedef struct dns_rrl_entry dns_rrl_entry_t;
105 typedef ISC_LIST(dns_rrl_entry_t) dns_rrl_bin_t;
106 struct dns_rrl_entry {
107 	ISC_LINK(dns_rrl_entry_t) lru;
108 	ISC_LINK(dns_rrl_entry_t) hlink;
109 	dns_rrl_key_t key;
110 #define DNS_RRL_RESPONSE_BITS 24
111 	signed int responses : DNS_RRL_RESPONSE_BITS;
112 #define DNS_RRL_QNAMES_BITS 8
113 	unsigned int log_qname : DNS_RRL_QNAMES_BITS;
114 
115 #define DNS_RRL_TS_GEN_BITS 2
116 	unsigned int ts_gen : DNS_RRL_TS_GEN_BITS;
117 	unsigned int ts_valid : 1;
118 #define DNS_RRL_HASH_GEN_BITS 1
119 	unsigned int hash_gen : DNS_RRL_HASH_GEN_BITS;
120 	unsigned int logged : 1;
121 #define DNS_RRL_LOG_BITS 11
122 	unsigned int log_secs : DNS_RRL_LOG_BITS;
123 
124 #define DNS_RRL_TS_BITS 12
125 	unsigned int ts : DNS_RRL_TS_BITS;
126 
127 #define DNS_RRL_MAX_SLIP 10
128 	unsigned int slip_cnt : 4;
129 };
130 
131 #define DNS_RRL_MAX_TIME_TRAVEL 5
132 #define DNS_RRL_FOREVER		(1 << DNS_RRL_TS_BITS)
133 #define DNS_RRL_MAX_TS		(DNS_RRL_FOREVER - 1)
134 
135 #define DNS_RRL_MAX_RESPONSES ((1 << (DNS_RRL_RESPONSE_BITS - 1)) - 1)
136 #define DNS_RRL_MAX_WINDOW    3600
137 #if DNS_RRL_MAX_WINDOW >= DNS_RRL_MAX_TS
138 #error "DNS_RRL_MAX_WINDOW is too large"
139 #endif /* if DNS_RRL_MAX_WINDOW >= DNS_RRL_MAX_TS */
140 #define DNS_RRL_MAX_RATE 1000
141 #if DNS_RRL_MAX_RATE >= (DNS_RRL_MAX_RESPONSES / DNS_RRL_MAX_WINDOW)
142 #error "DNS_RRL_MAX_rate is too large"
143 #endif /* if DNS_RRL_MAX_RATE >= (DNS_RRL_MAX_RESPONSES / DNS_RRL_MAX_WINDOW) \
144 	*/
145 
146 #if (1 << DNS_RRL_LOG_BITS) >= DNS_RRL_FOREVER
147 #error DNS_RRL_LOG_BITS is too big
148 #endif /* if (1 << DNS_RRL_LOG_BITS) >= DNS_RRL_FOREVER */
149 #define DNS_RRL_MAX_LOG_SECS 1800
150 #if DNS_RRL_MAX_LOG_SECS >= (1 << DNS_RRL_LOG_BITS)
151 #error "DNS_RRL_MAX_LOG_SECS is too large"
152 #endif /* if DNS_RRL_MAX_LOG_SECS >= (1 << DNS_RRL_LOG_BITS) */
153 #define DNS_RRL_STOP_LOG_SECS 60
154 #if DNS_RRL_STOP_LOG_SECS >= (1 << DNS_RRL_LOG_BITS)
155 #error "DNS_RRL_STOP_LOG_SECS is too large"
156 #endif /* if DNS_RRL_STOP_LOG_SECS >= (1 << DNS_RRL_LOG_BITS) */
157 
158 /*
159  * A hash table of rate-limit entries.
160  */
161 struct dns_rrl_hash {
162 	isc_stdtime_t check_time;
163 	unsigned int  gen : DNS_RRL_HASH_GEN_BITS;
164 	int	      length;
165 	dns_rrl_bin_t bins[1];
166 };
167 
168 /*
169  * A block of rate-limit entries.
170  */
171 typedef struct dns_rrl_block dns_rrl_block_t;
172 struct dns_rrl_block {
173 	ISC_LINK(dns_rrl_block_t) link;
174 	int		size;
175 	dns_rrl_entry_t entries[1];
176 };
177 
178 /*
179  * A rate limited qname buffer.
180  */
181 typedef struct dns_rrl_qname_buf dns_rrl_qname_buf_t;
182 struct dns_rrl_qname_buf {
183 	ISC_LINK(dns_rrl_qname_buf_t) link;
184 	const dns_rrl_entry_t *e;
185 	unsigned int	       index;
186 	dns_fixedname_t	       qname;
187 };
188 
189 typedef struct dns_rrl_rate dns_rrl_rate_t;
190 struct dns_rrl_rate {
191 	int	    r;
192 	int	    scaled;
193 	const char *str;
194 };
195 
196 /*
197  * Per-view query rate limit parameters and a pointer to database.
198  */
199 typedef struct dns_rrl dns_rrl_t;
200 struct dns_rrl {
201 	isc_mutex_t lock;
202 	isc_mem_t  *mctx;
203 
204 	bool	       log_only;
205 	dns_rrl_rate_t responses_per_second;
206 	dns_rrl_rate_t referrals_per_second;
207 	dns_rrl_rate_t nodata_per_second;
208 	dns_rrl_rate_t nxdomains_per_second;
209 	dns_rrl_rate_t errors_per_second;
210 	dns_rrl_rate_t all_per_second;
211 	dns_rrl_rate_t slip;
212 	int	       window;
213 	double	       qps_scale;
214 	int	       max_entries;
215 
216 	dns_acl_t *exempt;
217 
218 	int num_entries;
219 
220 	int	      qps_responses;
221 	isc_stdtime_t qps_time;
222 	double	      qps;
223 
224 	unsigned int probes;
225 	unsigned int searches;
226 
227 	ISC_LIST(dns_rrl_block_t) blocks;
228 	ISC_LIST(dns_rrl_entry_t) lru;
229 
230 	dns_rrl_hash_t *hash;
231 	dns_rrl_hash_t *old_hash;
232 	unsigned int	hash_gen;
233 
234 	unsigned int ts_gen;
235 #define DNS_RRL_TS_BASES (1 << DNS_RRL_TS_GEN_BITS)
236 	isc_stdtime_t ts_bases[DNS_RRL_TS_BASES];
237 
238 	int	 ipv4_prefixlen;
239 	uint32_t ipv4_mask;
240 	int	 ipv6_prefixlen;
241 	uint32_t ipv6_mask[4];
242 
243 	isc_stdtime_t	 log_stops_time;
244 	dns_rrl_entry_t *last_logged;
245 	int		 num_logged;
246 	int		 num_qnames;
247 	ISC_LIST(dns_rrl_qname_buf_t) qname_free;
248 #define DNS_RRL_QNAMES (1 << DNS_RRL_QNAMES_BITS)
249 	dns_rrl_qname_buf_t *qnames[DNS_RRL_QNAMES];
250 };
251 
252 typedef enum {
253 	DNS_RRL_RESULT_OK,
254 	DNS_RRL_RESULT_DROP,
255 	DNS_RRL_RESULT_SLIP,
256 } dns_rrl_result_t;
257 
258 dns_rrl_result_t
259 dns_rrl(dns_view_t *view, const isc_sockaddr_t *client_addr, bool is_tcp,
260 	dns_rdataclass_t rdclass, dns_rdatatype_t qtype,
261 	const dns_name_t *qname, isc_result_t resp_result, isc_stdtime_t now,
262 	bool wouldlog, char *log_buf, unsigned int log_buf_len);
263 
264 void
265 dns_rrl_view_destroy(dns_view_t *view);
266 
267 isc_result_t
268 dns_rrl_init(dns_rrl_t **rrlp, dns_view_t *view, int min_entries);
269 
270 ISC_LANG_ENDDECLS
271 
272 #endif /* DNS_RRL_H */
273