2 * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
22 * Rate limit DNS responses.
27 #include <dns/fixedname.h>
28 #include <dns/rdata.h>
29 #include <dns/types.h>
35 * Memory allocation or other failures.
37 #define DNS_RRL_LOG_FAIL ISC_LOG_WARNING
39 * dropped or slipped responses.
41 #define DNS_RRL_LOG_DROP ISC_LOG_INFO
43 * Major events in dropping or slipping.
45 #define DNS_RRL_LOG_DEBUG1 ISC_LOG_DEBUG(3)
49 #define DNS_RRL_LOG_DEBUG2 ISC_LOG_DEBUG(4)
51 * Even less interesting.
53 #define DNS_RRL_LOG_DEBUG3 ISC_LOG_DEBUG(9)
56 #define DNS_RRL_LOG_ERR_LEN 64
57 #define DNS_RRL_LOG_BUF_LEN (sizeof("would continue limiting") + \
58 DNS_RRL_LOG_ERR_LEN + \
59 sizeof(" responses to ") + \
60 ISC_NETADDR_FORMATSIZE + \
61 sizeof("/128 for IN ") + \
62 DNS_RDATATYPE_FORMATSIZE + \
66 typedef struct dns_rrl_hash dns_rrl_hash_t;
72 DNS_RRL_RTYPE_FREE = 0,
74 DNS_RRL_RTYPE_REFERRAL,
76 DNS_RRL_RTYPE_NXDOMAIN,
83 * A rate limit bucket key.
84 * This should be small to limit the total size of the database.
85 * The hash of the qname should be wide enough to make the probability
86 * of collisions among requests from a single IP address block less than 50%.
87 * We need a 32-bit hash value for 10000 qps (e.g. random qnames forged
88 * by attacker) to collide with legitimate qnames from the target with
89 * probability at most 1%.
91 #define DNS_RRL_MAX_PREFIX 64
92 typedef union dns_rrl_key dns_rrl_key_t;
95 isc_uint32_t ip[DNS_RRL_MAX_PREFIX/32];
96 isc_uint32_t qname_hash;
97 dns_rdatatype_t qtype;
99 dns_rrl_rtype_t rtype :4; /* 3 bits + sign bit */
100 isc_boolean_t ipv6 :1;
106 * A rate-limit entry.
107 * This should be small to limit the total size of the table of entries.
109 typedef struct dns_rrl_entry dns_rrl_entry_t;
110 typedef ISC_LIST(dns_rrl_entry_t) dns_rrl_bin_t;
111 struct dns_rrl_entry {
112 ISC_LINK(dns_rrl_entry_t) lru;
113 ISC_LINK(dns_rrl_entry_t) hlink;
115 # define DNS_RRL_RESPONSE_BITS 24
116 signed int responses :DNS_RRL_RESPONSE_BITS;
117 # define DNS_RRL_QNAMES_BITS 8
118 unsigned int log_qname :DNS_RRL_QNAMES_BITS;
120 # define DNS_RRL_TS_GEN_BITS 2
121 unsigned int ts_gen :DNS_RRL_TS_GEN_BITS;
122 isc_boolean_t ts_valid :1;
123 # define DNS_RRL_HASH_GEN_BITS 1
124 unsigned int hash_gen :DNS_RRL_HASH_GEN_BITS;
125 isc_boolean_t logged :1;
126 # define DNS_RRL_LOG_BITS 11
127 unsigned int log_secs :DNS_RRL_LOG_BITS;
129 # define DNS_RRL_TS_BITS 12
130 unsigned int ts :DNS_RRL_TS_BITS;
132 # define DNS_RRL_MAX_SLIP 10
133 unsigned int slip_cnt :4;
136 #define DNS_RRL_MAX_TIME_TRAVEL 5
137 #define DNS_RRL_FOREVER (1<<DNS_RRL_TS_BITS)
138 #define DNS_RRL_MAX_TS (DNS_RRL_FOREVER - 1)
140 #define DNS_RRL_MAX_RESPONSES ((1<<(DNS_RRL_RESPONSE_BITS-1))-1)
141 #define DNS_RRL_MAX_WINDOW 3600
142 #if DNS_RRL_MAX_WINDOW >= DNS_RRL_MAX_TS
143 #error "DNS_RRL_MAX_WINDOW is too large"
145 #define DNS_RRL_MAX_RATE 1000
146 #if DNS_RRL_MAX_RATE >= (DNS_RRL_MAX_RESPONSES / DNS_RRL_MAX_WINDOW)
147 #error "DNS_RRL_MAX_rate is too large"
150 #if (1<<DNS_RRL_LOG_BITS) >= DNS_RRL_FOREVER
151 #error DNS_RRL_LOG_BITS is too big
153 #define DNS_RRL_MAX_LOG_SECS 1800
154 #if DNS_RRL_MAX_LOG_SECS >= (1<<DNS_RRL_LOG_BITS)
155 #error "DNS_RRL_MAX_LOG_SECS is too large"
157 #define DNS_RRL_STOP_LOG_SECS 60
158 #if DNS_RRL_STOP_LOG_SECS >= (1<<DNS_RRL_LOG_BITS)
159 #error "DNS_RRL_STOP_LOG_SECS is too large"
164 * A hash table of rate-limit entries.
166 struct dns_rrl_hash {
167 isc_stdtime_t check_time;
168 unsigned int gen :DNS_RRL_HASH_GEN_BITS;
170 dns_rrl_bin_t bins[1];
174 * A block of rate-limit entries.
176 typedef struct dns_rrl_block dns_rrl_block_t;
177 struct dns_rrl_block {
178 ISC_LINK(dns_rrl_block_t) link;
180 dns_rrl_entry_t entries[1];
184 * A rate limited qname buffer.
186 typedef struct dns_rrl_qname_buf dns_rrl_qname_buf_t;
187 struct dns_rrl_qname_buf {
188 ISC_LINK(dns_rrl_qname_buf_t) link;
189 const dns_rrl_entry_t *e;
191 dns_fixedname_t qname;
194 typedef struct dns_rrl_rate dns_rrl_rate_t;
195 struct dns_rrl_rate {
202 * Per-view query rate limit parameters and a pointer to database.
204 typedef struct dns_rrl dns_rrl_t;
209 isc_boolean_t log_only;
210 dns_rrl_rate_t responses_per_second;
211 dns_rrl_rate_t referrals_per_second;
212 dns_rrl_rate_t nodata_per_second;
213 dns_rrl_rate_t nxdomains_per_second;
214 dns_rrl_rate_t errors_per_second;
215 dns_rrl_rate_t all_per_second;
226 isc_stdtime_t qps_time;
230 unsigned int searches;
232 ISC_LIST(dns_rrl_block_t) blocks;
233 ISC_LIST(dns_rrl_entry_t) lru;
235 dns_rrl_hash_t *hash;
236 dns_rrl_hash_t *old_hash;
237 unsigned int hash_gen;
240 # define DNS_RRL_TS_BASES (1<<DNS_RRL_TS_GEN_BITS)
241 isc_stdtime_t ts_bases[DNS_RRL_TS_BASES];
244 isc_uint32_t ipv4_mask;
246 isc_uint32_t ipv6_mask[4];
248 isc_stdtime_t log_stops_time;
249 dns_rrl_entry_t *last_logged;
252 ISC_LIST(dns_rrl_qname_buf_t) qname_free;
253 # define DNS_RRL_QNAMES (1<<DNS_RRL_QNAMES_BITS)
254 dns_rrl_qname_buf_t *qnames[DNS_RRL_QNAMES];
264 dns_rrl(dns_view_t *view,
265 const isc_sockaddr_t *client_addr, isc_boolean_t is_tcp,
266 dns_rdataclass_t rdclass, dns_rdatatype_t qtype,
267 dns_name_t *qname, isc_result_t resp_result, isc_stdtime_t now,
268 isc_boolean_t wouldlog, char *log_buf, unsigned int log_buf_len);
271 dns_rrl_view_destroy(dns_view_t *view);
274 dns_rrl_init(dns_rrl_t **rrlp, dns_view_t *view, int min_entries);
278 #endif /* DNS_RRL_H */