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