1262445Serwin/*
2262445Serwin * Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
3262445Serwin *
4262445Serwin * Permission to use, copy, modify, and/or distribute this software for any
5262445Serwin * purpose with or without fee is hereby granted, provided that the above
6262445Serwin * copyright notice and this permission notice appear in all copies.
7262445Serwin *
8262445Serwin * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9262445Serwin * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10262445Serwin * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11262445Serwin * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12262445Serwin * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13262445Serwin * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14262445Serwin * PERFORMANCE OF THIS SOFTWARE.
15262445Serwin */
16262445Serwin
17262445Serwin
18262445Serwin#ifndef DNS_RRL_H
19262445Serwin#define DNS_RRL_H 1
20262445Serwin
21262445Serwin/*
22262445Serwin * Rate limit DNS responses.
23262445Serwin */
24262445Serwin
25262445Serwin#include <isc/lang.h>
26262445Serwin
27262445Serwin#include <dns/fixedname.h>
28262445Serwin#include <dns/rdata.h>
29262445Serwin#include <dns/types.h>
30262445Serwin
31262445SerwinISC_LANG_BEGINDECLS
32262445Serwin
33262445Serwin
34262445Serwin/*
35262445Serwin * Memory allocation or other failures.
36262445Serwin */
37262445Serwin#define DNS_RRL_LOG_FAIL	ISC_LOG_WARNING
38262445Serwin/*
39262445Serwin * dropped or slipped responses.
40262445Serwin */
41262445Serwin#define DNS_RRL_LOG_DROP	ISC_LOG_INFO
42262445Serwin/*
43262445Serwin * Major events in dropping or slipping.
44262445Serwin */
45262445Serwin#define DNS_RRL_LOG_DEBUG1	ISC_LOG_DEBUG(3)
46262445Serwin/*
47262445Serwin * Limit computations.
48262445Serwin */
49262445Serwin#define DNS_RRL_LOG_DEBUG2	ISC_LOG_DEBUG(4)
50262445Serwin/*
51262445Serwin * Even less interesting.
52262445Serwin */
53262445Serwin#define DNS_RRL_LOG_DEBUG3	ISC_LOG_DEBUG(9)
54262445Serwin
55262445Serwin
56262445Serwin#define DNS_RRL_LOG_ERR_LEN	64
57262445Serwin#define DNS_RRL_LOG_BUF_LEN	(sizeof("would continue limiting") +	\
58262445Serwin				 DNS_RRL_LOG_ERR_LEN +			\
59262445Serwin				 sizeof(" responses to ") +		\
60262445Serwin				 ISC_NETADDR_FORMATSIZE +		\
61262445Serwin				 sizeof("/128 for IN ") +		\
62262445Serwin				 DNS_RDATATYPE_FORMATSIZE +		\
63262445Serwin				 DNS_NAME_FORMATSIZE)
64262445Serwin
65262445Serwin
66262445Serwintypedef struct dns_rrl_hash dns_rrl_hash_t;
67262445Serwin
68262445Serwin/*
69262445Serwin * Response types.
70262445Serwin */
71262445Serwintypedef enum {
72262445Serwin	DNS_RRL_RTYPE_FREE = 0,
73262445Serwin	DNS_RRL_RTYPE_QUERY,
74262445Serwin	DNS_RRL_RTYPE_REFERRAL,
75262445Serwin	DNS_RRL_RTYPE_NODATA,
76262445Serwin	DNS_RRL_RTYPE_NXDOMAIN,
77262445Serwin	DNS_RRL_RTYPE_ERROR,
78262445Serwin	DNS_RRL_RTYPE_ALL,
79262445Serwin	DNS_RRL_RTYPE_TCP,
80262445Serwin} dns_rrl_rtype_t;
81262445Serwin
82262445Serwin/*
83262445Serwin * A rate limit bucket key.
84262445Serwin * This should be small to limit the total size of the database.
85262445Serwin * The hash of the qname should be wide enough to make the probability
86262445Serwin * of collisions among requests from a single IP address block less than 50%.
87262445Serwin * We need a 32-bit hash value for 10000 qps (e.g. random qnames forged
88262445Serwin * by attacker) to collide with legitimate qnames from the target with
89262445Serwin * probability at most 1%.
90262445Serwin */
91262445Serwin#define DNS_RRL_MAX_PREFIX  64
92262445Serwintypedef union dns_rrl_key dns_rrl_key_t;
93262445Serwinunion dns_rrl_key {
94262445Serwin	struct {
95262445Serwin		isc_uint32_t	    ip[DNS_RRL_MAX_PREFIX/32];
96262445Serwin		isc_uint32_t	    qname_hash;
97262445Serwin		dns_rdatatype_t	    qtype;
98262445Serwin		isc_uint8_t         qclass;
99262445Serwin		dns_rrl_rtype_t	    rtype   :4; /* 3 bits + sign bit */
100262445Serwin		isc_boolean_t	    ipv6    :1;
101262445Serwin	} s;
102262445Serwin	isc_uint16_t	w[1];
103262445Serwin};
104262445Serwin
105262445Serwin/*
106262445Serwin * A rate-limit entry.
107262445Serwin * This should be small to limit the total size of the table of entries.
108262445Serwin */
109262445Serwintypedef struct dns_rrl_entry dns_rrl_entry_t;
110262445Serwintypedef ISC_LIST(dns_rrl_entry_t) dns_rrl_bin_t;
111262445Serwinstruct dns_rrl_entry {
112262445Serwin	ISC_LINK(dns_rrl_entry_t) lru;
113262445Serwin	ISC_LINK(dns_rrl_entry_t) hlink;
114262445Serwin	dns_rrl_key_t	key;
115262445Serwin# define DNS_RRL_RESPONSE_BITS	24
116262445Serwin	signed int	responses   :DNS_RRL_RESPONSE_BITS;
117262445Serwin# define DNS_RRL_QNAMES_BITS	8
118262445Serwin	unsigned int	log_qname   :DNS_RRL_QNAMES_BITS;
119262445Serwin
120262445Serwin# define DNS_RRL_TS_GEN_BITS	2
121262445Serwin	unsigned int	ts_gen	    :DNS_RRL_TS_GEN_BITS;
122262445Serwin	isc_boolean_t	ts_valid    :1;
123262445Serwin# define DNS_RRL_HASH_GEN_BITS	1
124262445Serwin	unsigned int	hash_gen    :DNS_RRL_HASH_GEN_BITS;
125262445Serwin	isc_boolean_t	logged	    :1;
126262445Serwin# define DNS_RRL_LOG_BITS	11
127262445Serwin	unsigned int	log_secs    :DNS_RRL_LOG_BITS;
128262445Serwin
129262445Serwin# define DNS_RRL_TS_BITS	12
130262445Serwin	unsigned int	ts	    :DNS_RRL_TS_BITS;
131262445Serwin
132262445Serwin# define DNS_RRL_MAX_SLIP	10
133262445Serwin	unsigned int	slip_cnt    :4;
134262445Serwin};
135262445Serwin
136262445Serwin#define DNS_RRL_MAX_TIME_TRAVEL	5
137262445Serwin#define DNS_RRL_FOREVER		(1<<DNS_RRL_TS_BITS)
138262445Serwin#define DNS_RRL_MAX_TS		(DNS_RRL_FOREVER - 1)
139262445Serwin
140262445Serwin#define DNS_RRL_MAX_RESPONSES	((1<<(DNS_RRL_RESPONSE_BITS-1))-1)
141262445Serwin#define DNS_RRL_MAX_WINDOW	3600
142262445Serwin#if DNS_RRL_MAX_WINDOW >= DNS_RRL_MAX_TS
143262445Serwin#error "DNS_RRL_MAX_WINDOW is too large"
144262445Serwin#endif
145262445Serwin#define DNS_RRL_MAX_RATE	1000
146262445Serwin#if DNS_RRL_MAX_RATE >= (DNS_RRL_MAX_RESPONSES / DNS_RRL_MAX_WINDOW)
147262445Serwin#error "DNS_RRL_MAX_rate is too large"
148262445Serwin#endif
149262445Serwin
150262445Serwin#if (1<<DNS_RRL_LOG_BITS) >= DNS_RRL_FOREVER
151262445Serwin#error DNS_RRL_LOG_BITS is too big
152262445Serwin#endif
153262445Serwin#define DNS_RRL_MAX_LOG_SECS	1800
154262445Serwin#if DNS_RRL_MAX_LOG_SECS >= (1<<DNS_RRL_LOG_BITS)
155262445Serwin#error "DNS_RRL_MAX_LOG_SECS is too large"
156262445Serwin#endif
157262445Serwin#define DNS_RRL_STOP_LOG_SECS	60
158262445Serwin#if DNS_RRL_STOP_LOG_SECS >= (1<<DNS_RRL_LOG_BITS)
159262445Serwin#error "DNS_RRL_STOP_LOG_SECS is too large"
160262445Serwin#endif
161262445Serwin
162262445Serwin
163262445Serwin/*
164262445Serwin * A hash table of rate-limit entries.
165262445Serwin */
166262445Serwinstruct dns_rrl_hash {
167262445Serwin	isc_stdtime_t	check_time;
168262445Serwin	unsigned int	gen	    :DNS_RRL_HASH_GEN_BITS;
169262445Serwin	int		length;
170262445Serwin	dns_rrl_bin_t	bins[1];
171262445Serwin};
172262445Serwin
173262445Serwin/*
174262445Serwin * A block of rate-limit entries.
175262445Serwin */
176262445Serwintypedef struct dns_rrl_block dns_rrl_block_t;
177262445Serwinstruct dns_rrl_block {
178262445Serwin	ISC_LINK(dns_rrl_block_t) link;
179262445Serwin	int		size;
180262445Serwin	dns_rrl_entry_t	entries[1];
181262445Serwin};
182262445Serwin
183262445Serwin/*
184262445Serwin * A rate limited qname buffer.
185262445Serwin */
186262445Serwintypedef struct dns_rrl_qname_buf dns_rrl_qname_buf_t;
187262445Serwinstruct dns_rrl_qname_buf {
188262445Serwin	ISC_LINK(dns_rrl_qname_buf_t) link;
189262445Serwin	const dns_rrl_entry_t *e;
190262445Serwin	unsigned int	    index;
191262445Serwin	dns_fixedname_t	    qname;
192262445Serwin};
193262445Serwin
194262445Serwintypedef struct dns_rrl_rate dns_rrl_rate_t;
195262445Serwinstruct dns_rrl_rate {
196262445Serwin	int	    r;
197262445Serwin	int	    scaled;
198262445Serwin	const char  *str;
199262445Serwin};
200262445Serwin
201262445Serwin/*
202262445Serwin * Per-view query rate limit parameters and a pointer to database.
203262445Serwin */
204262445Serwintypedef struct dns_rrl dns_rrl_t;
205262445Serwinstruct dns_rrl {
206262445Serwin	isc_mutex_t	lock;
207262445Serwin	isc_mem_t	*mctx;
208262445Serwin
209262445Serwin	isc_boolean_t	log_only;
210262445Serwin	dns_rrl_rate_t	responses_per_second;
211262445Serwin	dns_rrl_rate_t	referrals_per_second;
212262445Serwin	dns_rrl_rate_t	nodata_per_second;
213262445Serwin	dns_rrl_rate_t	nxdomains_per_second;
214262445Serwin	dns_rrl_rate_t	errors_per_second;
215262445Serwin	dns_rrl_rate_t	all_per_second;
216262445Serwin	dns_rrl_rate_t	slip;
217262445Serwin	int		window;
218262445Serwin	double		qps_scale;
219262445Serwin	int		max_entries;
220262445Serwin
221262445Serwin	dns_acl_t	*exempt;
222262445Serwin
223262445Serwin	int		num_entries;
224262445Serwin
225262445Serwin	int		qps_responses;
226262445Serwin	isc_stdtime_t	qps_time;
227262445Serwin	double		qps;
228262445Serwin
229262445Serwin	unsigned int	probes;
230262445Serwin	unsigned int	searches;
231262445Serwin
232262445Serwin	ISC_LIST(dns_rrl_block_t) blocks;
233262445Serwin	ISC_LIST(dns_rrl_entry_t) lru;
234262445Serwin
235262445Serwin	dns_rrl_hash_t	*hash;
236262445Serwin	dns_rrl_hash_t	*old_hash;
237262445Serwin	unsigned int	hash_gen;
238262445Serwin
239262445Serwin	unsigned int	ts_gen;
240262445Serwin# define DNS_RRL_TS_BASES   (1<<DNS_RRL_TS_GEN_BITS)
241262445Serwin	isc_stdtime_t	ts_bases[DNS_RRL_TS_BASES];
242262445Serwin
243262445Serwin	int		ipv4_prefixlen;
244262445Serwin	isc_uint32_t	ipv4_mask;
245262445Serwin	int		ipv6_prefixlen;
246262445Serwin	isc_uint32_t	ipv6_mask[4];
247262445Serwin
248262445Serwin	isc_stdtime_t	log_stops_time;
249262445Serwin	dns_rrl_entry_t	*last_logged;
250262445Serwin	int		num_logged;
251262445Serwin	int		num_qnames;
252262445Serwin	ISC_LIST(dns_rrl_qname_buf_t) qname_free;
253262445Serwin# define DNS_RRL_QNAMES	    (1<<DNS_RRL_QNAMES_BITS)
254262445Serwin	dns_rrl_qname_buf_t *qnames[DNS_RRL_QNAMES];
255262445Serwin};
256262445Serwin
257262445Serwintypedef enum {
258262445Serwin	DNS_RRL_RESULT_OK,
259262445Serwin	DNS_RRL_RESULT_DROP,
260262445Serwin	DNS_RRL_RESULT_SLIP,
261262445Serwin} dns_rrl_result_t;
262262445Serwin
263262445Serwindns_rrl_result_t
264262445Serwindns_rrl(dns_view_t *view,
265262445Serwin	const isc_sockaddr_t *client_addr, isc_boolean_t is_tcp,
266262445Serwin	dns_rdataclass_t rdclass, dns_rdatatype_t qtype,
267262445Serwin	dns_name_t *qname, isc_result_t resp_result, isc_stdtime_t now,
268262445Serwin	isc_boolean_t wouldlog, char *log_buf, unsigned int log_buf_len);
269262445Serwin
270262445Serwinvoid
271262445Serwindns_rrl_view_destroy(dns_view_t *view);
272262445Serwin
273262445Serwinisc_result_t
274262445Serwindns_rrl_init(dns_rrl_t **rrlp, dns_view_t *view, int min_entries);
275262445Serwin
276262445SerwinISC_LANG_ENDDECLS
277262445Serwin
278262445Serwin#endif /* DNS_RRL_H */
279