rrl.h revision 262445
1/* 2 * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") 3 * 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. 7 * 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. 15 */ 16 17 18#ifndef DNS_RRL_H 19#define DNS_RRL_H 1 20 21/* 22 * Rate limit DNS responses. 23 */ 24 25#include <isc/lang.h> 26 27#include <dns/fixedname.h> 28#include <dns/rdata.h> 29#include <dns/types.h> 30 31ISC_LANG_BEGINDECLS 32 33 34/* 35 * Memory allocation or other failures. 36 */ 37#define DNS_RRL_LOG_FAIL ISC_LOG_WARNING 38/* 39 * dropped or slipped responses. 40 */ 41#define DNS_RRL_LOG_DROP ISC_LOG_INFO 42/* 43 * Major events in dropping or slipping. 44 */ 45#define DNS_RRL_LOG_DEBUG1 ISC_LOG_DEBUG(3) 46/* 47 * Limit computations. 48 */ 49#define DNS_RRL_LOG_DEBUG2 ISC_LOG_DEBUG(4) 50/* 51 * Even less interesting. 52 */ 53#define DNS_RRL_LOG_DEBUG3 ISC_LOG_DEBUG(9) 54 55 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 + \ 63 DNS_NAME_FORMATSIZE) 64 65 66typedef struct dns_rrl_hash dns_rrl_hash_t; 67 68/* 69 * Response types. 70 */ 71typedef enum { 72 DNS_RRL_RTYPE_FREE = 0, 73 DNS_RRL_RTYPE_QUERY, 74 DNS_RRL_RTYPE_REFERRAL, 75 DNS_RRL_RTYPE_NODATA, 76 DNS_RRL_RTYPE_NXDOMAIN, 77 DNS_RRL_RTYPE_ERROR, 78 DNS_RRL_RTYPE_ALL, 79 DNS_RRL_RTYPE_TCP, 80} dns_rrl_rtype_t; 81 82/* 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%. 90 */ 91#define DNS_RRL_MAX_PREFIX 64 92typedef union dns_rrl_key dns_rrl_key_t; 93union dns_rrl_key { 94 struct { 95 isc_uint32_t ip[DNS_RRL_MAX_PREFIX/32]; 96 isc_uint32_t qname_hash; 97 dns_rdatatype_t qtype; 98 isc_uint8_t qclass; 99 dns_rrl_rtype_t rtype :4; /* 3 bits + sign bit */ 100 isc_boolean_t ipv6 :1; 101 } s; 102 isc_uint16_t w[1]; 103}; 104 105/* 106 * A rate-limit entry. 107 * This should be small to limit the total size of the table of entries. 108 */ 109typedef struct dns_rrl_entry dns_rrl_entry_t; 110typedef ISC_LIST(dns_rrl_entry_t) dns_rrl_bin_t; 111struct dns_rrl_entry { 112 ISC_LINK(dns_rrl_entry_t) lru; 113 ISC_LINK(dns_rrl_entry_t) hlink; 114 dns_rrl_key_t key; 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; 119 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; 128 129# define DNS_RRL_TS_BITS 12 130 unsigned int ts :DNS_RRL_TS_BITS; 131 132# define DNS_RRL_MAX_SLIP 10 133 unsigned int slip_cnt :4; 134}; 135 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) 139 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" 144#endif 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" 148#endif 149 150#if (1<<DNS_RRL_LOG_BITS) >= DNS_RRL_FOREVER 151#error DNS_RRL_LOG_BITS is too big 152#endif 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" 156#endif 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" 160#endif 161 162 163/* 164 * A hash table of rate-limit entries. 165 */ 166struct dns_rrl_hash { 167 isc_stdtime_t check_time; 168 unsigned int gen :DNS_RRL_HASH_GEN_BITS; 169 int length; 170 dns_rrl_bin_t bins[1]; 171}; 172 173/* 174 * A block of rate-limit entries. 175 */ 176typedef struct dns_rrl_block dns_rrl_block_t; 177struct dns_rrl_block { 178 ISC_LINK(dns_rrl_block_t) link; 179 int size; 180 dns_rrl_entry_t entries[1]; 181}; 182 183/* 184 * A rate limited qname buffer. 185 */ 186typedef struct dns_rrl_qname_buf dns_rrl_qname_buf_t; 187struct dns_rrl_qname_buf { 188 ISC_LINK(dns_rrl_qname_buf_t) link; 189 const dns_rrl_entry_t *e; 190 unsigned int index; 191 dns_fixedname_t qname; 192}; 193 194typedef struct dns_rrl_rate dns_rrl_rate_t; 195struct dns_rrl_rate { 196 int r; 197 int scaled; 198 const char *str; 199}; 200 201/* 202 * Per-view query rate limit parameters and a pointer to database. 203 */ 204typedef struct dns_rrl dns_rrl_t; 205struct dns_rrl { 206 isc_mutex_t lock; 207 isc_mem_t *mctx; 208 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; 216 dns_rrl_rate_t slip; 217 int window; 218 double qps_scale; 219 int max_entries; 220 221 dns_acl_t *exempt; 222 223 int num_entries; 224 225 int qps_responses; 226 isc_stdtime_t qps_time; 227 double qps; 228 229 unsigned int probes; 230 unsigned int searches; 231 232 ISC_LIST(dns_rrl_block_t) blocks; 233 ISC_LIST(dns_rrl_entry_t) lru; 234 235 dns_rrl_hash_t *hash; 236 dns_rrl_hash_t *old_hash; 237 unsigned int hash_gen; 238 239 unsigned int ts_gen; 240# define DNS_RRL_TS_BASES (1<<DNS_RRL_TS_GEN_BITS) 241 isc_stdtime_t ts_bases[DNS_RRL_TS_BASES]; 242 243 int ipv4_prefixlen; 244 isc_uint32_t ipv4_mask; 245 int ipv6_prefixlen; 246 isc_uint32_t ipv6_mask[4]; 247 248 isc_stdtime_t log_stops_time; 249 dns_rrl_entry_t *last_logged; 250 int num_logged; 251 int num_qnames; 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]; 255}; 256 257typedef enum { 258 DNS_RRL_RESULT_OK, 259 DNS_RRL_RESULT_DROP, 260 DNS_RRL_RESULT_SLIP, 261} dns_rrl_result_t; 262 263dns_rrl_result_t 264dns_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); 269 270void 271dns_rrl_view_destroy(dns_view_t *view); 272 273isc_result_t 274dns_rrl_init(dns_rrl_t **rrlp, dns_view_t *view, int min_entries); 275 276ISC_LANG_ENDDECLS 277 278#endif /* DNS_RRL_H */ 279