rrl.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 
00018 #ifndef DNS_RRL_H
00019 #define DNS_RRL_H 1
00020 
00021 /*
00022  * Rate limit DNS responses.
00023  */
00024 
00025 #include <isc/lang.h>
00026 
00027 #include <dns/fixedname.h>
00028 #include <dns/rdata.h>
00029 #include <dns/types.h>
00030 
00031 ISC_LANG_BEGINDECLS
00032 
00033 
00034 /*
00035  * Memory allocation or other failures.
00036  */
00037 #define DNS_RRL_LOG_FAIL        ISC_LOG_WARNING
00038 /*
00039  * dropped or slipped responses.
00040  */
00041 #define DNS_RRL_LOG_DROP        ISC_LOG_INFO
00042 /*
00043  * Major events in dropping or slipping.
00044  */
00045 #define DNS_RRL_LOG_DEBUG1      ISC_LOG_DEBUG(3)
00046 /*
00047  * Limit computations.
00048  */
00049 #define DNS_RRL_LOG_DEBUG2      ISC_LOG_DEBUG(4)
00050 /*
00051  * Even less interesting.
00052  */
00053 #define DNS_RRL_LOG_DEBUG3      ISC_LOG_DEBUG(9)
00054 
00055 
00056 #define DNS_RRL_LOG_ERR_LEN     64
00057 #define DNS_RRL_LOG_BUF_LEN     (sizeof("would continue limiting") +    \
00058                                  DNS_RRL_LOG_ERR_LEN +                  \
00059                                  sizeof(" responses to ") +             \
00060                                  ISC_NETADDR_FORMATSIZE +               \
00061                                  sizeof("/128 for IN ") +               \
00062                                  DNS_RDATATYPE_FORMATSIZE +             \
00063                                  DNS_NAME_FORMATSIZE)
00064 
00065 
00066 typedef struct dns_rrl_hash dns_rrl_hash_t;
00067 
00068 /*
00069  * Response types.
00070  */
00071 typedef enum {
00072         DNS_RRL_RTYPE_FREE = 0,
00073         DNS_RRL_RTYPE_QUERY,
00074         DNS_RRL_RTYPE_REFERRAL,
00075         DNS_RRL_RTYPE_NODATA,
00076         DNS_RRL_RTYPE_NXDOMAIN,
00077         DNS_RRL_RTYPE_ERROR,
00078         DNS_RRL_RTYPE_ALL,
00079         DNS_RRL_RTYPE_TCP,
00080 } dns_rrl_rtype_t;
00081 
00082 /*
00083  * A rate limit bucket key.
00084  * This should be small to limit the total size of the database.
00085  * The hash of the qname should be wide enough to make the probability
00086  * of collisions among requests from a single IP address block less than 50%.
00087  * We need a 32-bit hash value for 10000 qps (e.g. random qnames forged
00088  * by attacker) to collide with legitimate qnames from the target with
00089  * probability at most 1%.
00090  */
00091 #define DNS_RRL_MAX_PREFIX  64
00092 typedef union dns_rrl_key dns_rrl_key_t;
00093 union dns_rrl_key {
00094         struct {
00095                 isc_uint32_t        ip[DNS_RRL_MAX_PREFIX/32];
00096                 isc_uint32_t        qname_hash;
00097                 dns_rdatatype_t     qtype;
00098                 isc_uint8_t         qclass;
00099                 dns_rrl_rtype_t     rtype   :4; /* 3 bits + sign bit */
00100                 isc_boolean_t       ipv6    :1;
00101         } s;
00102         isc_uint16_t    w[1];
00103 };
00104 
00105 /*
00106  * A rate-limit entry.
00107  * This should be small to limit the total size of the table of entries.
00108  */
00109 typedef struct dns_rrl_entry dns_rrl_entry_t;
00110 typedef ISC_LIST(dns_rrl_entry_t) dns_rrl_bin_t;
00111 struct dns_rrl_entry {
00112         ISC_LINK(dns_rrl_entry_t) lru;
00113         ISC_LINK(dns_rrl_entry_t) hlink;
00114         dns_rrl_key_t   key;
00115 # define DNS_RRL_RESPONSE_BITS  24
00116         signed int      responses   :DNS_RRL_RESPONSE_BITS;
00117 # define DNS_RRL_QNAMES_BITS    8
00118         unsigned int    log_qname   :DNS_RRL_QNAMES_BITS;
00119 
00120 # define DNS_RRL_TS_GEN_BITS    2
00121         unsigned int    ts_gen      :DNS_RRL_TS_GEN_BITS;
00122         isc_boolean_t   ts_valid    :1;
00123 # define DNS_RRL_HASH_GEN_BITS  1
00124         unsigned int    hash_gen    :DNS_RRL_HASH_GEN_BITS;
00125         isc_boolean_t   logged      :1;
00126 # define DNS_RRL_LOG_BITS       11
00127         unsigned int    log_secs    :DNS_RRL_LOG_BITS;
00128 
00129 # define DNS_RRL_TS_BITS        12
00130         unsigned int    ts          :DNS_RRL_TS_BITS;
00131 
00132 # define DNS_RRL_MAX_SLIP       10
00133         unsigned int    slip_cnt    :4;
00134 };
00135 
00136 #define DNS_RRL_MAX_TIME_TRAVEL 5
00137 #define DNS_RRL_FOREVER         (1<<DNS_RRL_TS_BITS)
00138 #define DNS_RRL_MAX_TS          (DNS_RRL_FOREVER - 1)
00139 
00140 #define DNS_RRL_MAX_RESPONSES   ((1<<(DNS_RRL_RESPONSE_BITS-1))-1)
00141 #define DNS_RRL_MAX_WINDOW      3600
00142 #if DNS_RRL_MAX_WINDOW >= DNS_RRL_MAX_TS
00143 #error "DNS_RRL_MAX_WINDOW is too large"
00144 #endif
00145 #define DNS_RRL_MAX_RATE        1000
00146 #if DNS_RRL_MAX_RATE >= (DNS_RRL_MAX_RESPONSES / DNS_RRL_MAX_WINDOW)
00147 #error "DNS_RRL_MAX_rate is too large"
00148 #endif
00149 
00150 #if (1<<DNS_RRL_LOG_BITS) >= DNS_RRL_FOREVER
00151 #error DNS_RRL_LOG_BITS is too big
00152 #endif
00153 #define DNS_RRL_MAX_LOG_SECS    1800
00154 #if DNS_RRL_MAX_LOG_SECS >= (1<<DNS_RRL_LOG_BITS)
00155 #error "DNS_RRL_MAX_LOG_SECS is too large"
00156 #endif
00157 #define DNS_RRL_STOP_LOG_SECS   60
00158 #if DNS_RRL_STOP_LOG_SECS >= (1<<DNS_RRL_LOG_BITS)
00159 #error "DNS_RRL_STOP_LOG_SECS is too large"
00160 #endif
00161 
00162 
00163 /*
00164  * A hash table of rate-limit entries.
00165  */
00166 struct dns_rrl_hash {
00167         isc_stdtime_t   check_time;
00168         unsigned int    gen         :DNS_RRL_HASH_GEN_BITS;
00169         int             length;
00170         dns_rrl_bin_t   bins[1];
00171 };
00172 
00173 /*
00174  * A block of rate-limit entries.
00175  */
00176 typedef struct dns_rrl_block dns_rrl_block_t;
00177 struct dns_rrl_block {
00178         ISC_LINK(dns_rrl_block_t) link;
00179         int             size;
00180         dns_rrl_entry_t entries[1];
00181 };
00182 
00183 /*
00184  * A rate limited qname buffer.
00185  */
00186 typedef struct dns_rrl_qname_buf dns_rrl_qname_buf_t;
00187 struct dns_rrl_qname_buf {
00188         ISC_LINK(dns_rrl_qname_buf_t) link;
00189         const dns_rrl_entry_t *e;
00190         unsigned int        index;
00191         dns_fixedname_t     qname;
00192 };
00193 
00194 typedef struct dns_rrl_rate dns_rrl_rate_t;
00195 struct dns_rrl_rate {
00196         int         r;
00197         int         scaled;
00198         const char  *str;
00199 };
00200 
00201 /*
00202  * Per-view query rate limit parameters and a pointer to database.
00203  */
00204 typedef struct dns_rrl dns_rrl_t;
00205 struct dns_rrl {
00206         isc_mutex_t     lock;
00207         isc_mem_t       *mctx;
00208 
00209         isc_boolean_t   log_only;
00210         dns_rrl_rate_t  responses_per_second;
00211         dns_rrl_rate_t  referrals_per_second;
00212         dns_rrl_rate_t  nodata_per_second;
00213         dns_rrl_rate_t  nxdomains_per_second;
00214         dns_rrl_rate_t  errors_per_second;
00215         dns_rrl_rate_t  all_per_second;
00216         dns_rrl_rate_t  slip;
00217         int             window;
00218         double          qps_scale;
00219         int             max_entries;
00220 
00221         dns_acl_t       *exempt;
00222 
00223         int             num_entries;
00224 
00225         int             qps_responses;
00226         isc_stdtime_t   qps_time;
00227         double          qps;
00228 
00229         unsigned int    probes;
00230         unsigned int    searches;
00231 
00232         ISC_LIST(dns_rrl_block_t) blocks;
00233         ISC_LIST(dns_rrl_entry_t) lru;
00234 
00235         dns_rrl_hash_t  *hash;
00236         dns_rrl_hash_t  *old_hash;
00237         unsigned int    hash_gen;
00238 
00239         unsigned int    ts_gen;
00240 # define DNS_RRL_TS_BASES   (1<<DNS_RRL_TS_GEN_BITS)
00241         isc_stdtime_t   ts_bases[DNS_RRL_TS_BASES];
00242 
00243         int             ipv4_prefixlen;
00244         isc_uint32_t    ipv4_mask;
00245         int             ipv6_prefixlen;
00246         isc_uint32_t    ipv6_mask[4];
00247 
00248         isc_stdtime_t   log_stops_time;
00249         dns_rrl_entry_t *last_logged;
00250         int             num_logged;
00251         int             num_qnames;
00252         ISC_LIST(dns_rrl_qname_buf_t) qname_free;
00253 # define DNS_RRL_QNAMES     (1<<DNS_RRL_QNAMES_BITS)
00254         dns_rrl_qname_buf_t *qnames[DNS_RRL_QNAMES];
00255 };
00256 
00257 typedef enum {
00258         DNS_RRL_RESULT_OK,
00259         DNS_RRL_RESULT_DROP,
00260         DNS_RRL_RESULT_SLIP,
00261 } dns_rrl_result_t;
00262 
00263 dns_rrl_result_t
00264 dns_rrl(dns_view_t *view,
00265         const isc_sockaddr_t *client_addr, isc_boolean_t is_tcp,
00266         dns_rdataclass_t rdclass, dns_rdatatype_t qtype,
00267         dns_name_t *qname, isc_result_t resp_result, isc_stdtime_t now,
00268         isc_boolean_t wouldlog, char *log_buf, unsigned int log_buf_len);
00269 
00270 void
00271 dns_rrl_view_destroy(dns_view_t *view);
00272 
00273 isc_result_t
00274 dns_rrl_init(dns_rrl_t **rrlp, dns_view_t *view, int min_entries);
00275 
00276 ISC_LANG_ENDDECLS
00277 
00278 #endif /* DNS_RRL_H */

Generated on Tue Apr 28 17:40:57 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha