1 /* 2 * Copyright (C) 2013, 2015 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 31 ISC_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 66 typedef struct dns_rrl_hash dns_rrl_hash_t; 67 68 /* 69 * Response types. 70 */ 71 typedef 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 92 typedef union dns_rrl_key dns_rrl_key_t; 93 struct dns__rrl_key { 94 isc_uint32_t ip[DNS_RRL_MAX_PREFIX/32]; 95 isc_uint32_t qname_hash; 96 dns_rdatatype_t qtype; 97 isc_uint8_t qclass; 98 dns_rrl_rtype_t rtype :4; /* 3 bits + sign bit */ 99 isc_boolean_t ipv6 :1; 100 }; 101 union dns_rrl_key { 102 struct dns__rrl_key s; 103 isc_uint16_t w[sizeof(struct dns__rrl_key)/sizeof(isc_uint16_t)]; 104 }; 105 106 /* 107 * A rate-limit entry. 108 * This should be small to limit the total size of the table of entries. 109 */ 110 typedef struct dns_rrl_entry dns_rrl_entry_t; 111 typedef ISC_LIST(dns_rrl_entry_t) dns_rrl_bin_t; 112 struct dns_rrl_entry { 113 ISC_LINK(dns_rrl_entry_t) lru; 114 ISC_LINK(dns_rrl_entry_t) hlink; 115 dns_rrl_key_t key; 116 # define DNS_RRL_RESPONSE_BITS 24 117 signed int responses :DNS_RRL_RESPONSE_BITS; 118 # define DNS_RRL_QNAMES_BITS 8 119 unsigned int log_qname :DNS_RRL_QNAMES_BITS; 120 121 # define DNS_RRL_TS_GEN_BITS 2 122 unsigned int ts_gen :DNS_RRL_TS_GEN_BITS; 123 isc_boolean_t ts_valid :1; 124 # define DNS_RRL_HASH_GEN_BITS 1 125 unsigned int hash_gen :DNS_RRL_HASH_GEN_BITS; 126 isc_boolean_t logged :1; 127 # define DNS_RRL_LOG_BITS 11 128 unsigned int log_secs :DNS_RRL_LOG_BITS; 129 130 # define DNS_RRL_TS_BITS 12 131 unsigned int ts :DNS_RRL_TS_BITS; 132 133 # define DNS_RRL_MAX_SLIP 10 134 unsigned int slip_cnt :4; 135 }; 136 137 #define DNS_RRL_MAX_TIME_TRAVEL 5 138 #define DNS_RRL_FOREVER (1<<DNS_RRL_TS_BITS) 139 #define DNS_RRL_MAX_TS (DNS_RRL_FOREVER - 1) 140 141 #define DNS_RRL_MAX_RESPONSES ((1<<(DNS_RRL_RESPONSE_BITS-1))-1) 142 #define DNS_RRL_MAX_WINDOW 3600 143 #if DNS_RRL_MAX_WINDOW >= DNS_RRL_MAX_TS 144 #error "DNS_RRL_MAX_WINDOW is too large" 145 #endif 146 #define DNS_RRL_MAX_RATE 1000 147 #if DNS_RRL_MAX_RATE >= (DNS_RRL_MAX_RESPONSES / DNS_RRL_MAX_WINDOW) 148 #error "DNS_RRL_MAX_rate is too large" 149 #endif 150 151 #if (1<<DNS_RRL_LOG_BITS) >= DNS_RRL_FOREVER 152 #error DNS_RRL_LOG_BITS is too big 153 #endif 154 #define DNS_RRL_MAX_LOG_SECS 1800 155 #if DNS_RRL_MAX_LOG_SECS >= (1<<DNS_RRL_LOG_BITS) 156 #error "DNS_RRL_MAX_LOG_SECS is too large" 157 #endif 158 #define DNS_RRL_STOP_LOG_SECS 60 159 #if DNS_RRL_STOP_LOG_SECS >= (1<<DNS_RRL_LOG_BITS) 160 #error "DNS_RRL_STOP_LOG_SECS is too large" 161 #endif 162 163 164 /* 165 * A hash table of rate-limit entries. 166 */ 167 struct dns_rrl_hash { 168 isc_stdtime_t check_time; 169 unsigned int gen :DNS_RRL_HASH_GEN_BITS; 170 int length; 171 dns_rrl_bin_t bins[1]; 172 }; 173 174 /* 175 * A block of rate-limit entries. 176 */ 177 typedef struct dns_rrl_block dns_rrl_block_t; 178 struct dns_rrl_block { 179 ISC_LINK(dns_rrl_block_t) link; 180 int size; 181 dns_rrl_entry_t entries[1]; 182 }; 183 184 /* 185 * A rate limited qname buffer. 186 */ 187 typedef struct dns_rrl_qname_buf dns_rrl_qname_buf_t; 188 struct dns_rrl_qname_buf { 189 ISC_LINK(dns_rrl_qname_buf_t) link; 190 const dns_rrl_entry_t *e; 191 unsigned int index; 192 dns_fixedname_t qname; 193 }; 194 195 typedef struct dns_rrl_rate dns_rrl_rate_t; 196 struct dns_rrl_rate { 197 int r; 198 int scaled; 199 const char *str; 200 }; 201 202 /* 203 * Per-view query rate limit parameters and a pointer to database. 204 */ 205 typedef struct dns_rrl dns_rrl_t; 206 struct dns_rrl { 207 isc_mutex_t lock; 208 isc_mem_t *mctx; 209 210 isc_boolean_t log_only; 211 dns_rrl_rate_t responses_per_second; 212 dns_rrl_rate_t referrals_per_second; 213 dns_rrl_rate_t nodata_per_second; 214 dns_rrl_rate_t nxdomains_per_second; 215 dns_rrl_rate_t errors_per_second; 216 dns_rrl_rate_t all_per_second; 217 dns_rrl_rate_t slip; 218 int window; 219 double qps_scale; 220 int max_entries; 221 222 dns_acl_t *exempt; 223 224 int num_entries; 225 226 int qps_responses; 227 isc_stdtime_t qps_time; 228 double qps; 229 230 unsigned int probes; 231 unsigned int searches; 232 233 ISC_LIST(dns_rrl_block_t) blocks; 234 ISC_LIST(dns_rrl_entry_t) lru; 235 236 dns_rrl_hash_t *hash; 237 dns_rrl_hash_t *old_hash; 238 unsigned int hash_gen; 239 240 unsigned int ts_gen; 241 # define DNS_RRL_TS_BASES (1<<DNS_RRL_TS_GEN_BITS) 242 isc_stdtime_t ts_bases[DNS_RRL_TS_BASES]; 243 244 int ipv4_prefixlen; 245 isc_uint32_t ipv4_mask; 246 int ipv6_prefixlen; 247 isc_uint32_t ipv6_mask[4]; 248 249 isc_stdtime_t log_stops_time; 250 dns_rrl_entry_t *last_logged; 251 int num_logged; 252 int num_qnames; 253 ISC_LIST(dns_rrl_qname_buf_t) qname_free; 254 # define DNS_RRL_QNAMES (1<<DNS_RRL_QNAMES_BITS) 255 dns_rrl_qname_buf_t *qnames[DNS_RRL_QNAMES]; 256 }; 257 258 typedef enum { 259 DNS_RRL_RESULT_OK, 260 DNS_RRL_RESULT_DROP, 261 DNS_RRL_RESULT_SLIP, 262 } dns_rrl_result_t; 263 264 dns_rrl_result_t 265 dns_rrl(dns_view_t *view, 266 const isc_sockaddr_t *client_addr, isc_boolean_t is_tcp, 267 dns_rdataclass_t rdclass, dns_rdatatype_t qtype, 268 dns_name_t *qname, isc_result_t resp_result, isc_stdtime_t now, 269 isc_boolean_t wouldlog, char *log_buf, unsigned int log_buf_len); 270 271 void 272 dns_rrl_view_destroy(dns_view_t *view); 273 274 isc_result_t 275 dns_rrl_init(dns_rrl_t **rrlp, dns_view_t *view, int min_entries); 276 277 ISC_LANG_ENDDECLS 278 279 #endif /* DNS_RRL_H */ 280