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