diff options
Diffstat (limited to 'contrib/unbound/daemon')
-rw-r--r-- | contrib/unbound/daemon/cachedump.c | 16 | ||||
-rw-r--r-- | contrib/unbound/daemon/daemon.c | 2 | ||||
-rw-r--r-- | contrib/unbound/daemon/remote.c | 141 | ||||
-rw-r--r-- | contrib/unbound/daemon/stats.c | 12 | ||||
-rw-r--r-- | contrib/unbound/daemon/stats.h | 2 | ||||
-rw-r--r-- | contrib/unbound/daemon/worker.c | 42 | ||||
-rw-r--r-- | contrib/unbound/daemon/worker.h | 4 |
7 files changed, 177 insertions, 42 deletions
diff --git a/contrib/unbound/daemon/cachedump.c b/contrib/unbound/daemon/cachedump.c index 20a46ae4dffb..4b0a583a6547 100644 --- a/contrib/unbound/daemon/cachedump.c +++ b/contrib/unbound/daemon/cachedump.c @@ -56,9 +56,9 @@ #include "iterator/iter_utils.h" #include "iterator/iter_fwd.h" #include "iterator/iter_hints.h" -#include "ldns/sbuffer.h" -#include "ldns/wire2str.h" -#include "ldns/str2wire.h" +#include "sldns/sbuffer.h" +#include "sldns/wire2str.h" +#include "sldns/str2wire.h" /** dump one rrset zonefile line */ static int @@ -223,6 +223,8 @@ copy_msg(struct regional* region, struct lruhash_entry* e, struct query_info** k, struct reply_info** d) { struct reply_info* rep = (struct reply_info*)e->data; + if(rep->rrset_count > RR_COUNT_MAX) + return 0; /* to protect against integer overflow */ *d = (struct reply_info*)regional_alloc_init(region, e->data, sizeof(struct reply_info) + sizeof(struct rrset_ref) * (rep->rrset_count-1) + @@ -470,6 +472,10 @@ load_rrset(SSL* ssl, sldns_buffer* buf, struct worker* worker) log_warn("bad rrset without contents"); return 0; } + if(rr_count > RR_COUNT_MAX || rrsig_count > RR_COUNT_MAX) { + log_warn("bad rrset with too many rrs"); + return 0; + } d->count = (size_t)rr_count; d->rrsig_count = (size_t)rrsig_count; d->security = (enum sec_status)security; @@ -646,6 +652,10 @@ load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker) rep.ttl = (time_t)ttl; rep.prefetch_ttl = PREFETCH_TTL_CALC(rep.ttl); rep.security = (enum sec_status)security; + if(an > RR_COUNT_MAX || ns > RR_COUNT_MAX || ar > RR_COUNT_MAX) { + log_warn("error too many rrsets"); + return 0; /* protect against integer overflow in alloc */ + } rep.an_numrrsets = (size_t)an; rep.ns_numrrsets = (size_t)ns; rep.ar_numrrsets = (size_t)ar; diff --git a/contrib/unbound/daemon/daemon.c b/contrib/unbound/daemon/daemon.c index f693a0285a2c..0cd37ae8231c 100644 --- a/contrib/unbound/daemon/daemon.c +++ b/contrib/unbound/daemon/daemon.c @@ -84,7 +84,7 @@ #include "util/random.h" #include "util/tube.h" #include "util/net_help.h" -#include "ldns/keyraw.h" +#include "sldns/keyraw.h" #include <signal.h> /** How many quit requests happened. */ diff --git a/contrib/unbound/daemon/remote.c b/contrib/unbound/daemon/remote.c index 3ce55ee7ea1a..93d0eda28b86 100644 --- a/contrib/unbound/daemon/remote.c +++ b/contrib/unbound/daemon/remote.c @@ -78,10 +78,10 @@ #include "iterator/iter_delegpt.h" #include "services/outbound_list.h" #include "services/outside_network.h" -#include "ldns/str2wire.h" -#include "ldns/parseutil.h" -#include "ldns/wire2str.h" -#include "ldns/sbuffer.h" +#include "sldns/str2wire.h" +#include "sldns/parseutil.h" +#include "sldns/wire2str.h" +#include "sldns/sbuffer.h" #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> @@ -140,34 +140,45 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d) /* * The following function was generated using the openssl utility, using - * the command : "openssl dhparam -dsaparam -C 512" + * the command : "openssl dhparam -dsaparam -C 1024" + * (some openssl versions reject DH that is 'too small', eg. 512). */ #ifndef S_SPLINT_S -DH *get_dh512() -{ - static unsigned char dh512_p[]={ - 0xC9,0xD7,0x05,0xDA,0x5F,0xAB,0x14,0xE8,0x11,0x56,0x77,0x85, - 0xB1,0x24,0x2C,0x95,0x60,0xEA,0xE2,0x10,0x6F,0x0F,0x84,0xEC, - 0xF4,0x45,0xE8,0x90,0x7A,0xA7,0x03,0xFF,0x5B,0x88,0x53,0xDE, - 0xC4,0xDE,0xBC,0x42,0x78,0x71,0x23,0x7E,0x24,0xA5,0x5E,0x4E, - 0xEF,0x6F,0xFF,0x5F,0xAF,0xBE,0x8A,0x77,0x62,0xB4,0x65,0x82, - 0x7E,0xC9,0xED,0x2F, - }; - static unsigned char dh512_g[]={ - 0x8D,0x3A,0x52,0xBC,0x8A,0x71,0x94,0x33,0x2F,0xE1,0xE8,0x4C, - 0x73,0x47,0x03,0x4E,0x7D,0x40,0xE5,0x84,0xA0,0xB5,0x6D,0x10, - 0x6F,0x90,0x43,0x05,0x1A,0xF9,0x0B,0x6A,0xD1,0x2A,0x9C,0x25, - 0x0A,0xB9,0xD1,0x14,0xDC,0x35,0x1C,0x48,0x7C,0xC6,0x0C,0x6D, - 0x32,0x1D,0xD3,0xC8,0x10,0xA8,0x82,0x14,0xA2,0x1C,0xF4,0x53, - 0x23,0x3B,0x1C,0xB9, - }; +DH *get_dh1024() +{ + static unsigned char dh1024_p[]={ + 0xB3,0x67,0x2E,0x3B,0x68,0xC5,0xDA,0x58,0x46,0xD6,0x2B,0xD3, + 0x41,0x78,0x97,0xE4,0xE1,0x61,0x71,0x68,0xE6,0x0F,0x1D,0x78, + 0x05,0xAA,0xF0,0xFF,0x30,0xDF,0xAC,0x49,0x7F,0xE0,0x90,0xFE, + 0xB9,0x56,0x4E,0x3F,0xE2,0x98,0x8A,0xED,0xF5,0x28,0x39,0xEF, + 0x2E,0xA6,0xB7,0x67,0xB2,0x43,0xE4,0x53,0xF8,0xEB,0x2C,0x1F, + 0x06,0x77,0x3A,0x6F,0x62,0x98,0xC1,0x3B,0xF7,0xBA,0x4D,0x93, + 0xF7,0xEB,0x5A,0xAD,0xC5,0x5F,0xF0,0xB7,0x24,0x35,0x81,0xF7, + 0x7F,0x1F,0x24,0xC0,0xDF,0xD3,0xD8,0x40,0x72,0x7E,0xF3,0x19, + 0x2B,0x26,0x27,0xF4,0xB6,0xB3,0xD4,0x7D,0x08,0x23,0xBE,0x68, + 0x2B,0xCA,0xB4,0x46,0xA8,0x9E,0xDD,0x6C,0x3D,0x75,0xA6,0x48, + 0xF7,0x44,0x43,0xBF,0x91,0xC2,0xB4,0x49, + }; + static unsigned char dh1024_g[]={ + 0x5F,0x37,0xB5,0x80,0x4D,0xB4,0xC4,0xB2,0x37,0x12,0xD5,0x2F, + 0x56,0x81,0xB0,0xDF,0x3D,0x27,0xA2,0x54,0xE7,0x14,0x65,0x2D, + 0x72,0xA8,0x97,0xE0,0xA9,0x4A,0x09,0x5E,0x89,0xBE,0x34,0x9A, + 0x90,0x98,0xC1,0xE8,0xBB,0x01,0x2B,0xC2,0x74,0x74,0x90,0x59, + 0x0B,0x72,0x62,0x5C,0xFD,0x49,0x63,0x4B,0x38,0x91,0xF1,0x7F, + 0x13,0x25,0xEB,0x52,0x50,0x47,0xA2,0x8C,0x32,0x28,0x42,0xAC, + 0xBD,0x7A,0xCC,0x58,0xBE,0x36,0xDA,0x6A,0x24,0x06,0xC7,0xF1, + 0xDA,0x8D,0x8A,0x3B,0x03,0xFA,0x6F,0x25,0xE5,0x20,0xA7,0xD6, + 0x6F,0x74,0x61,0x53,0x14,0x81,0x29,0x04,0xB5,0x61,0x12,0x53, + 0xA3,0xD6,0x09,0x98,0x0C,0x8F,0x1C,0xBB,0xD7,0x1C,0x2C,0xEE, + 0x56,0x4B,0x74,0x8F,0x4A,0xF8,0xA9,0xD5, + }; DH *dh; if ((dh=DH_new()) == NULL) return(NULL); - dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL); - dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL); + dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL); + dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL); if ((dh->p == NULL) || (dh->g == NULL)) - { DH_free(dh); return(NULL); } + { DH_free(dh); return(NULL); } dh->length = 160; return(dh); } @@ -218,7 +229,7 @@ daemon_remote_create(struct config_file* cfg) /* Since we have no certificates and hence no source of * DH params, let's generate and set them */ - if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh512())) { + if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh1024())) { log_crypto_err("Wanted to set DH param, but failed"); return NULL; } @@ -358,7 +369,8 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err, } /* open fd */ - fd = create_tcp_accept_sock(res, 1, &noproto, 0); + fd = create_tcp_accept_sock(res, 1, &noproto, 0, + cfg->ip_transparent); freeaddrinfo(res); } @@ -725,6 +737,8 @@ print_stats(SSL* ssl, const char* nm, struct stats_info* s) (long long)avg.tv_sec, (int)avg.tv_usec)) return 0; if(!ssl_printf(ssl, "%s.recursion.time.median"SQ"%g\n", nm, s->mesh_time_median)) return 0; + if(!ssl_printf(ssl, "%s.tcpusage"SQ"%lu\n", nm, + (unsigned long)s->svr.tcp_accept_usage)) return 0; return 1; } @@ -1889,6 +1903,21 @@ do_insecure_remove(SSL* ssl, struct worker* worker, char* arg) send_ok(ssl); } +static void +do_insecure_list(SSL* ssl, struct worker* worker) +{ + char buf[257]; + struct trust_anchor* a; + if(worker->env.anchors) { + RBTREE_FOR(a, struct trust_anchor*, worker->env.anchors->tree) { + if(a->numDS == 0 && a->numDNSKEY == 0) { + dname_str(a->name, buf); + ssl_printf(ssl, "%s\n", buf); + } + } + } +} + /** do the status command */ static void do_status(SSL* ssl, struct worker* worker) @@ -2074,7 +2103,7 @@ dump_infra_host(struct lruhash_entry* e, void* arg) d->rtt.srtt, d->rtt.rttvar, rtt_notimeout(&d->rtt), d->rtt.rto, d->timeout_A, d->timeout_AAAA, d->timeout_other, (int)d->edns_lame_known, (int)d->edns_version, - (int)(a->now<d->probedelay?d->probedelay-a->now:0), + (int)(a->now<d->probedelay?(d->probedelay - a->now):0), (int)d->isdnsseclame, (int)d->rec_lame, (int)d->lame_type_A, (int)d->lame_other)) { a->ssl_failed = 1; @@ -2249,6 +2278,54 @@ do_list_local_data(SSL* ssl, struct worker* worker) lock_rw_unlock(&zones->lock); } +/** struct for user arg ratelimit list */ +struct ratelimit_list_arg { + /** the infra cache */ + struct infra_cache* infra; + /** the SSL to print to */ + SSL* ssl; + /** all or only ratelimited */ + int all; + /** current time */ + time_t now; +}; + +/** list items in the ratelimit table */ +static void +rate_list(struct lruhash_entry* e, void* arg) +{ + struct ratelimit_list_arg* a = (struct ratelimit_list_arg*)arg; + struct rate_key* k = (struct rate_key*)e->key; + struct rate_data* d = (struct rate_data*)e->data; + char buf[257]; + int lim = infra_find_ratelimit(a->infra, k->name, k->namelen); + int max = infra_rate_max(d, a->now); + if(a->all == 0) { + if(max < lim) + return; + } + dname_str(k->name, buf); + ssl_printf(a->ssl, "%s %d limit %d\n", buf, max, lim); +} + +/** do the ratelimit_list command */ +static void +do_ratelimit_list(SSL* ssl, struct worker* worker, char* arg) +{ + struct ratelimit_list_arg a; + a.all = 0; + a.infra = worker->env.infra_cache; + a.now = *worker->env.now; + a.ssl = ssl; + arg = skipwhite(arg); + if(strcmp(arg, "+a") == 0) + a.all = 1; + if(a.infra->domain_rates==NULL || + (a.all == 0 && infra_dp_ratelimit == 0)) + return; + slabhash_traverse(a.infra->domain_rates, 0, rate_list, &a); +} + /** tell other processes to execute the command */ static void distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd) @@ -2309,12 +2386,18 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd, } else if(cmdcmp(p, "list_stubs", 10)) { do_list_stubs(ssl, worker); return; + } else if(cmdcmp(p, "list_insecure", 13)) { + do_insecure_list(ssl, worker); + return; } else if(cmdcmp(p, "list_local_zones", 16)) { do_list_local_zones(ssl, worker); return; } else if(cmdcmp(p, "list_local_data", 15)) { do_list_local_data(ssl, worker); return; + } else if(cmdcmp(p, "ratelimit_list", 14)) { + do_ratelimit_list(ssl, worker, p+14); + return; } else if(cmdcmp(p, "stub_add", 8)) { /* must always distribute this cmd */ if(rc) distribute_cmd(rc, ssl, cmd); diff --git a/contrib/unbound/daemon/stats.c b/contrib/unbound/daemon/stats.c index d3f41de037b4..838cf05ae52c 100644 --- a/contrib/unbound/daemon/stats.c +++ b/contrib/unbound/daemon/stats.c @@ -50,12 +50,13 @@ #include "daemon/daemon.h" #include "services/mesh.h" #include "services/outside_network.h" +#include "services/listen_dnsport.h" #include "util/config_file.h" #include "util/tube.h" #include "util/timehist.h" #include "util/net_help.h" #include "validator/validator.h" -#include "ldns/sbuffer.h" +#include "sldns/sbuffer.h" #include "services/cache/rrset.h" #include "services/cache/infra.h" #include "validator/val_kcache.h" @@ -140,6 +141,7 @@ void server_stats_compile(struct worker* worker, struct stats_info* s, int reset) { int i; + struct listen_list* lp; s->svr = worker->stats; s->mesh_num_states = worker->env.mesh->all.count; @@ -174,6 +176,13 @@ server_stats_compile(struct worker* worker, struct stats_info* s, int reset) s->svr.key_cache_count = count_slabhash_entries(worker->env.key_cache->slab); else s->svr.key_cache_count = 0; + /* get tcp accept usage */ + s->svr.tcp_accept_usage = 0; + for(lp = worker->front->cps; lp; lp = lp->next) { + if(lp->com->type == comm_tcp_accept) + s->svr.tcp_accept_usage += lp->com->cur_tcp_count; + } + if(reset && !worker->env.cfg->stat_cumulative) { worker_stats_clear(worker); } @@ -247,6 +256,7 @@ void server_stats_add(struct stats_info* total, struct stats_info* a) total->svr.rrset_bogus += a->svr.rrset_bogus; total->svr.unwanted_replies += a->svr.unwanted_replies; total->svr.unwanted_queries += a->svr.unwanted_queries; + total->svr.tcp_accept_usage += a->svr.tcp_accept_usage; for(i=0; i<STATS_QTYPE_NUM; i++) total->svr.qtype[i] += a->svr.qtype[i]; for(i=0; i<STATS_QCLASS_NUM; i++) diff --git a/contrib/unbound/daemon/stats.h b/contrib/unbound/daemon/stats.h index 5ea00a0da5b7..6985446ce299 100644 --- a/contrib/unbound/daemon/stats.h +++ b/contrib/unbound/daemon/stats.h @@ -129,6 +129,8 @@ struct server_stats { size_t unwanted_replies; /** unwanted traffic received on client-facing ports */ size_t unwanted_queries; + /** usage of tcp accept list */ + size_t tcp_accept_usage; /** histogram data exported to array * if the array is the same size, no data is lost, and diff --git a/contrib/unbound/daemon/worker.c b/contrib/unbound/daemon/worker.c index 5edc21dd46e7..79aec4d3a4b2 100644 --- a/contrib/unbound/daemon/worker.c +++ b/contrib/unbound/daemon/worker.c @@ -71,7 +71,7 @@ #include "validator/val_anchor.h" #include "libunbound/context.h" #include "libunbound/libworker.h" -#include "ldns/sbuffer.h" +#include "sldns/sbuffer.h" #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> @@ -86,6 +86,8 @@ /** Size of an UDP datagram */ #define NORMAL_UDP_SIZE 512 /* bytes */ +/** ratelimit for error responses */ +#define ERROR_RATELIMIT 100 /* qps */ /** * seconds to add to prefetch leeway. This is a TTL that expires old rrsets @@ -291,6 +293,26 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error, return 0; } +/** ratelimit error replies + * @param worker: the worker struct with ratelimit counter + * @param err: error code that would be wanted. + * @return value of err if okay, or -1 if it should be discarded instead. + */ +static int +worker_err_ratelimit(struct worker* worker, int err) +{ + if(worker->err_limit_time == *worker->env.now) { + /* see if limit is exceeded for this second */ + if(worker->err_limit_count++ > ERROR_RATELIMIT) + return -1; + } else { + /* new second, new limits */ + worker->err_limit_time = *worker->env.now; + worker->err_limit_count = 1; + } + return err; +} + /** check request sanity. * @param pkt: the wire packet to examine for sanity. * @param worker: parameters for checking. @@ -315,32 +337,32 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker) if(LDNS_TC_WIRE(sldns_buffer_begin(pkt))) { LDNS_TC_CLR(sldns_buffer_begin(pkt)); verbose(VERB_QUERY, "request bad, has TC bit on"); - return LDNS_RCODE_FORMERR; + return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR); } if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY) { verbose(VERB_QUERY, "request unknown opcode %d", LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt))); - return LDNS_RCODE_NOTIMPL; + return worker_err_ratelimit(worker, LDNS_RCODE_NOTIMPL); } if(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) != 1) { verbose(VERB_QUERY, "request wrong nr qd=%d", LDNS_QDCOUNT(sldns_buffer_begin(pkt))); - return LDNS_RCODE_FORMERR; + return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR); } if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0) { verbose(VERB_QUERY, "request wrong nr an=%d", LDNS_ANCOUNT(sldns_buffer_begin(pkt))); - return LDNS_RCODE_FORMERR; + return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR); } if(LDNS_NSCOUNT(sldns_buffer_begin(pkt)) != 0) { verbose(VERB_QUERY, "request wrong nr ns=%d", LDNS_NSCOUNT(sldns_buffer_begin(pkt))); - return LDNS_RCODE_FORMERR; + return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR); } if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) > 1) { verbose(VERB_QUERY, "request wrong nr ar=%d", LDNS_ARCOUNT(sldns_buffer_begin(pkt))); - return LDNS_RCODE_FORMERR; + return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR); } return 0; } @@ -546,7 +568,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type == htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type == htons(LDNS_RR_TYPE_DNAME))) { - if(!reply_check_cname_chain(rep)) { + if(!reply_check_cname_chain(qinfo, rep)) { /* cname chain invalid, redo iterator steps */ verbose(VERB_ALGO, "Cache reply: cname chain broken"); bail_out: @@ -813,6 +835,10 @@ worker_handle_request(struct comm_point* c, void* arg, int error, if(!query_info_parse(&qinfo, c->buffer)) { verbose(VERB_ALGO, "worker parse request: formerror."); log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); + if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) { + comm_point_drop_reply(repinfo); + return 0; + } sldns_buffer_rewind(c->buffer); LDNS_QR_SET(sldns_buffer_begin(c->buffer)); LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), diff --git a/contrib/unbound/daemon/worker.h b/contrib/unbound/daemon/worker.h index ff69bc1acfd4..63613430b054 100644 --- a/contrib/unbound/daemon/worker.h +++ b/contrib/unbound/daemon/worker.h @@ -103,6 +103,10 @@ struct worker { struct comm_point* cmd_com; /** timer for statistics */ struct comm_timer* stat_timer; + /** ratelimit for errors, time value */ + time_t err_limit_time; + /** ratelimit for errors, packet count */ + unsigned int err_limit_count; /** random() table for this worker. */ struct ub_randstate* rndstate; |