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