mirror of https://github.com/getdnsapi/getdns.git
- Add a new mode where for TLS (and infact TCP too) the upstream selection simply cycles over all the upstreams rather than treating them as an ordered list and always using the first open one.
- Make IP field in debug output fixed width - Collect all the one line config options at the top of the stubby.conf file to make it easier to read
This commit is contained in:
parent
5f3de12644
commit
f0f3c43552
|
@ -73,6 +73,7 @@ static struct const_info consts_info[] = {
|
|||
{ 619, "GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE", GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE_TEXT },
|
||||
{ 620, "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT },
|
||||
{ 621, "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT },
|
||||
{ 622, "GETDNS_CONTEXT_CODE_TLS_USE_ALL_UPSTREAMS", GETDNS_CONTEXT_CODE_TLS_USE_ALL_UPSTREAMS_TEXT },
|
||||
{ 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT },
|
||||
{ 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT },
|
||||
{ 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT },
|
||||
|
@ -161,6 +162,7 @@ static struct const_name_info consts_name_info[] = {
|
|||
{ "GETDNS_CONTEXT_CODE_TIMEOUT", 616 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION", 618 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_USE_ALL_UPSTREAMS", 622 },
|
||||
{ "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", 603 },
|
||||
{ "GETDNS_DNSSEC_BOGUS", 401 },
|
||||
{ "GETDNS_DNSSEC_INDETERMINATE", 402 },
|
||||
|
|
|
@ -647,6 +647,7 @@ upstreams_create(getdns_context *context, size_t size)
|
|||
r->referenced = 1;
|
||||
r->count = 0;
|
||||
r->current_udp = 0;
|
||||
r->current_stateful = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -721,17 +722,17 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
|
|||
if (upstream->tls_auth_state > upstream->best_tls_auth_state)
|
||||
upstream->best_tls_auth_state = upstream->tls_auth_state;
|
||||
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
|
||||
DEBUG_DAEMON("%s %s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n",
|
||||
DEBUG_DAEMON("%s %-40s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n",
|
||||
STUB_DEBUG_DAEMON, upstream->addr_str,
|
||||
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
|
||||
(int)upstream->responses_received, (int)upstream->responses_timeouts,
|
||||
_getdns_auth_str(upstream->tls_auth_state), (int)upstream->keepalive_timeout);
|
||||
DEBUG_DAEMON("%s %s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\n",
|
||||
DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\n",
|
||||
STUB_DEBUG_DAEMON, upstream->addr_str,
|
||||
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
|
||||
(int)upstream->total_responses, (int)upstream->total_timeouts,
|
||||
_getdns_auth_str(upstream->best_tls_auth_state));
|
||||
DEBUG_DAEMON("%s %s : Upstream stats: Transport=%s - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n",
|
||||
DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=%s - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n",
|
||||
STUB_DEBUG_DAEMON, upstream->addr_str,
|
||||
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
|
||||
(int)upstream->conn_completed, (int)upstream->conn_setup_failed,
|
||||
|
@ -760,7 +761,7 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
|
|||
upstream->conn_shutdowns = 0;
|
||||
upstream->conn_backoffs++;
|
||||
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
|
||||
DEBUG_DAEMON("%s %s : !Backing off this upstream - Will retry as new upstream at %s",
|
||||
DEBUG_DAEMON("%s %-40s : !Backing off this upstream - Will retry as new upstream at %s",
|
||||
STUB_DEBUG_DAEMON, upstream->addr_str,
|
||||
asctime(gmtime(&upstream->conn_retry_time)));
|
||||
#endif
|
||||
|
@ -1428,6 +1429,7 @@ getdns_context_create_with_extended_memory_functions(
|
|||
goto error;
|
||||
result->tls_auth = GETDNS_AUTHENTICATION_NONE;
|
||||
result->tls_auth_min = GETDNS_AUTHENTICATION_NONE;
|
||||
result->tls_use_all_upstreams = 0;
|
||||
result->limit_outstanding_queries = 0;
|
||||
|
||||
/* unbound context is initialized here */
|
||||
|
@ -2031,6 +2033,27 @@ getdns_context_set_tls_authentication(getdns_context *context,
|
|||
return GETDNS_RETURN_GOOD;
|
||||
} /* getdns_context_set_tls_authentication_list */
|
||||
|
||||
/*
|
||||
* getdns_context_set_tls_use_all_upstreams
|
||||
*
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_set_tls_use_all_upstreams(getdns_context *context, uint8_t value)
|
||||
{
|
||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
/* only allow 0 or 1 */
|
||||
if (value != 0 && value != 1) {
|
||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||
}
|
||||
|
||||
context->tls_use_all_upstreams = value;
|
||||
|
||||
dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_USE_ALL_UPSTREAMS);
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
} /* getdns_context_set_tls_use_all_upstreams */
|
||||
|
||||
|
||||
#ifdef HAVE_LIBUNBOUND
|
||||
static void
|
||||
set_ub_limit_outstanding_queries(getdns_context* context, uint16_t value) {
|
||||
|
@ -3467,7 +3490,9 @@ _get_context_settings(getdns_context* context)
|
|||
|| getdns_dict_set_int(result, "append_name",
|
||||
context->append_name)
|
||||
|| getdns_dict_set_int(result, "tls_authentication",
|
||||
context->tls_auth))
|
||||
context->tls_auth)
|
||||
|| getdns_dict_set_int(result, "tls_use_all_upstreams",
|
||||
context->tls_use_all_upstreams))
|
||||
goto error;
|
||||
|
||||
/* list fields */
|
||||
|
@ -3763,6 +3788,15 @@ getdns_context_get_tls_authentication(getdns_context *context,
|
|||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_use_all_upstreams(getdns_context *context,
|
||||
uint8_t* value) {
|
||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
*value = context->tls_use_all_upstreams;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_context_get_limit_outstanding_queries(getdns_context *context,
|
||||
uint16_t* value) {
|
||||
|
@ -4158,6 +4192,7 @@ _getdns_context_config_setting(getdns_context *context,
|
|||
|
||||
CONTEXT_SETTING_INT(edns_client_subnet_private)
|
||||
CONTEXT_SETTING_INT(tls_authentication)
|
||||
CONTEXT_SETTING_INT(tls_use_all_upstreams)
|
||||
CONTEXT_SETTING_INT(tls_query_padding_blocksize)
|
||||
|
||||
/**************************************/
|
||||
|
|
|
@ -217,6 +217,7 @@ typedef struct getdns_upstreams {
|
|||
size_t referenced;
|
||||
size_t count;
|
||||
size_t current_udp;
|
||||
size_t current_stateful;
|
||||
getdns_upstream upstreams[];
|
||||
} getdns_upstreams;
|
||||
|
||||
|
@ -248,6 +249,7 @@ struct getdns_context {
|
|||
uint32_t dnssec_allowed_skew;
|
||||
getdns_tls_authentication_t tls_auth; /* What user requested for TLS*/
|
||||
getdns_tls_authentication_t tls_auth_min; /* Derived minimum auth allowed*/
|
||||
uint8_t tls_use_all_upstreams;
|
||||
|
||||
getdns_transport_list_t *dns_transports;
|
||||
size_t dns_transport_count;
|
||||
|
|
|
@ -76,6 +76,8 @@ extern "C" {
|
|||
#define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT "Change related to getdns_context_set_tls_query_padding_blocksize"
|
||||
#define GETDNS_CONTEXT_CODE_PUBKEY_PINSET 621
|
||||
#define GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT "Change related to getdns_context_set_pubkey_pinset"
|
||||
#define GETDNS_CONTEXT_CODE_TLS_USE_ALL_UPSTREAMS 622
|
||||
#define GETDNS_CONTEXT_CODE_TLS_USE_ALL_UPSTREAMS_TEXT "Change related to getdns_context_set_pubkey_pinset"
|
||||
/** @}
|
||||
*/
|
||||
|
||||
|
@ -265,6 +267,9 @@ getdns_return_t
|
|||
getdns_context_set_tls_authentication(
|
||||
getdns_context *context, getdns_tls_authentication_t value);
|
||||
|
||||
getdns_return_t
|
||||
getdns_context_set_tls_use_all_upstreams(getdns_context *context, uint8_t value);
|
||||
|
||||
getdns_return_t
|
||||
getdns_context_set_edns_client_subnet_private(getdns_context *context, uint8_t value);
|
||||
|
||||
|
@ -356,6 +361,10 @@ getdns_return_t
|
|||
getdns_context_get_tls_authentication(getdns_context *context,
|
||||
getdns_tls_authentication_t* value);
|
||||
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_use_all_upstreams(getdns_context *context,
|
||||
uint8_t* value);
|
||||
|
||||
/**
|
||||
* Get the currently registered callback function and user defined argument
|
||||
* for context changes.
|
||||
|
|
|
@ -30,6 +30,7 @@ getdns_context_get_suffix
|
|||
getdns_context_get_timeout
|
||||
getdns_context_get_tls_authentication
|
||||
getdns_context_get_tls_query_padding_blocksize
|
||||
getdns_context_get_tls_use_all_upstreams
|
||||
getdns_context_get_update_callback
|
||||
getdns_context_get_upstream_recursive_servers
|
||||
getdns_context_process_async
|
||||
|
@ -60,6 +61,7 @@ getdns_context_set_suffix
|
|||
getdns_context_set_timeout
|
||||
getdns_context_set_tls_authentication
|
||||
getdns_context_set_tls_query_padding_blocksize
|
||||
getdns_context_get_tls_use_all_upstreams
|
||||
getdns_context_set_update_callback
|
||||
getdns_context_set_upstream_recursive_servers
|
||||
getdns_context_set_use_threads
|
||||
|
|
75
src/stub.c
75
src/stub.c
|
@ -591,7 +591,7 @@ stub_timeout_cb(void *userarg)
|
|||
netreq->upstream->udp_timeouts++;
|
||||
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
|
||||
if (netreq->upstream->udp_timeouts % 100 == 0)
|
||||
DEBUG_DAEMON("%s %s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
|
||||
DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
|
||||
STUB_DEBUG_DAEMON, netreq->upstream->addr_str,
|
||||
(int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts);
|
||||
#endif
|
||||
|
@ -907,7 +907,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
|||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd);
|
||||
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
|
||||
else
|
||||
DEBUG_DAEMON("%s %s : Conn failed : Transport=TLS - *Failure* - Pinset validation failure\n",
|
||||
DEBUG_DAEMON("%s %-40s : Conn failed : Transport=TLS - *Failure* - Pinset validation failure\n",
|
||||
STUB_DEBUG_DAEMON, upstream->addr_str);
|
||||
#endif
|
||||
} else {
|
||||
|
@ -1373,7 +1373,7 @@ stub_udp_read_cb(void *userarg)
|
|||
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
|
||||
if (upstream->udp_responses == 1 ||
|
||||
upstream->udp_responses % 100 == 0)
|
||||
DEBUG_DAEMON("%s %s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
|
||||
DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
|
||||
STUB_DEBUG_DAEMON, upstream->addr_str,
|
||||
(int)upstream->udp_responses, (int)upstream->udp_timeouts);
|
||||
#endif
|
||||
|
@ -1608,7 +1608,7 @@ upstream_write_cb(void *userarg)
|
|||
/* Cleaning up after connection or auth check failure. Need to fallback. */
|
||||
stub_cleanup(netreq);
|
||||
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
|
||||
DEBUG_DAEMON("%s %s : Conn closed : Transport=%s - *Failure*\n",
|
||||
DEBUG_DAEMON("%s %-40s : Conn closed : Transport=%s - *Failure*\n",
|
||||
STUB_DEBUG_DAEMON, upstream->addr_str,
|
||||
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"));
|
||||
#endif
|
||||
|
@ -1672,6 +1672,17 @@ upstream_active(getdns_upstream *upstream)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
upstream_usable(getdns_upstream *upstream)
|
||||
{
|
||||
if ((upstream->conn_state == GETDNS_CONN_CLOSED ||
|
||||
upstream->conn_state == GETDNS_CONN_SETUP ||
|
||||
upstream->conn_state == GETDNS_CONN_OPEN) &&
|
||||
upstream->keepalive_shutdown == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
upstream_auth_status_ok(getdns_upstream *upstream, getdns_network_req *netreq) {
|
||||
if (netreq->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED)
|
||||
|
@ -1692,10 +1703,16 @@ upstream_valid(getdns_upstream *upstream,
|
|||
getdns_transport_list_t transport,
|
||||
getdns_network_req *netreq)
|
||||
{
|
||||
if (upstream->transport != transport || upstream->conn_state != GETDNS_CONN_CLOSED)
|
||||
if (upstream->transport != transport && upstream_usable(upstream))
|
||||
return 0;
|
||||
if (transport == GETDNS_TRANSPORT_TCP)
|
||||
return 1;
|
||||
if (upstream->conn_state == GETDNS_CONN_OPEN) {
|
||||
if (!upstream_auth_status_ok(upstream, netreq))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
/* We need to check past authentication history to see if this is usable for TLS.*/
|
||||
if (netreq->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED)
|
||||
return 1;
|
||||
|
@ -1728,7 +1745,7 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
|
|||
getdns_upstreams *upstreams = netreq->owner->upstreams;
|
||||
size_t i;
|
||||
time_t now = time(NULL);
|
||||
|
||||
|
||||
if (!upstreams->count)
|
||||
return NULL;
|
||||
|
||||
|
@ -1738,37 +1755,55 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
|
|||
upstreams->upstreams[i].conn_retry_time < now) {
|
||||
upstreams->upstreams[i].conn_state = GETDNS_CONN_CLOSED;
|
||||
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
|
||||
DEBUG_DAEMON("%s %s : Re-instating upstream\n",
|
||||
DEBUG_DAEMON("%s %-40s : Re-instating upstream\n",
|
||||
STUB_DEBUG_DAEMON, upstreams->upstreams[i].addr_str);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* First find if an open upstream has the correct properties and use that*/
|
||||
for (i = 0; i < upstreams->count; i++) {
|
||||
if (upstream_valid_and_open(&upstreams->upstreams[i], transport, netreq))
|
||||
return &upstreams->upstreams[i];
|
||||
if (netreq->owner->context->tls_use_all_upstreams == 0) {
|
||||
/* First find if an open upstream has the correct properties and use that*/
|
||||
for (i = 0; i < upstreams->count; i++) {
|
||||
if (upstream_valid_and_open(&upstreams->upstreams[i], transport, netreq))
|
||||
return &upstreams->upstreams[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* OK - we will have to open one. Choose the first one that has the best stats
|
||||
and the right properties, but because we completely back off failed
|
||||
/* OK - Find the next one to use. First check we have at least one valid
|
||||
upstream because we completely back off failed
|
||||
upstreams we may have no valid upstream at all (in contrast to UDP). This
|
||||
will be better communicated to the user when we have better error codes*/
|
||||
for (i = 0; i < upstreams->count; i++) {
|
||||
i = upstreams->current_stateful;
|
||||
do {
|
||||
DEBUG_STUB("%s %-35s: Testing upstreams %d %d\n", STUB_DEBUG_SETUP,
|
||||
__FUNC__, (int)i, (int)upstreams->upstreams[i].conn_state);
|
||||
if (upstream_valid(&upstreams->upstreams[i], transport, netreq)) {
|
||||
upstream = &upstreams->upstreams[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
if (i >= upstreams->count)
|
||||
i = 0;
|
||||
} while (i != upstreams->current_stateful);
|
||||
if (!upstream)
|
||||
return NULL;
|
||||
for (i++; i < upstreams->count; i++) {
|
||||
if (upstream_valid(&upstreams->upstreams[i], transport, netreq) &&
|
||||
upstream_stats(&upstreams->upstreams[i]) > upstream_stats(upstream))
|
||||
upstream = &upstreams->upstreams[i];
|
||||
|
||||
/* Now select the specific upstream */
|
||||
if (netreq->owner->context->tls_use_all_upstreams == 0) {
|
||||
/* Base the decision on the stats, noting we will have started from 0*/
|
||||
for (i++; i < upstreams->count; i++) {
|
||||
if (upstream_valid(&upstreams->upstreams[i], transport, netreq) &&
|
||||
upstream_stats(&upstreams->upstreams[i]) > upstream_stats(upstream))
|
||||
upstream = &upstreams->upstreams[i];
|
||||
}
|
||||
} else {
|
||||
/* Simplistic, but always just pick the first one, incrementing the current.
|
||||
Note we are not distinguishing TCP/TLS here....*/
|
||||
upstreams->current_stateful+=GETDNS_UPSTREAM_TRANSPORTS;
|
||||
if (upstreams->current_stateful >= upstreams->count)
|
||||
upstreams->current_stateful = 0;
|
||||
}
|
||||
|
||||
return upstream;
|
||||
}
|
||||
|
||||
|
@ -1853,7 +1888,7 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
|
|||
}
|
||||
upstream->conn_state = GETDNS_CONN_SETUP;
|
||||
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
|
||||
DEBUG_DAEMON("%s %s : Conn init : Transport=%s - Profile=%s\n", STUB_DEBUG_DAEMON,
|
||||
DEBUG_DAEMON("%s %-40s : Conn init : Transport=%s - Profile=%s\n", STUB_DEBUG_DAEMON,
|
||||
upstream->addr_str, transport == GETDNS_TRANSPORT_TLS ? "TLS":"TCP",
|
||||
dnsreq->context->tls_auth_min == GETDNS_AUTHENTICATION_NONE ? "Opportunistic":"Strict");
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
{ resolution_type: GETDNS_RESOLUTION_STUB
|
||||
, dns_transport_list: [ GETDNS_TRANSPORT_TLS ]
|
||||
, tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
|
||||
, tls_query_padding_blocksize: 256
|
||||
, edns_client_subnet_private : 1
|
||||
, listen_addresses: [ 127.0.0.1, 0::1 ]
|
||||
, idle_timeout: 10000
|
||||
, tls_use_all_upstreams: 1
|
||||
, upstream_recursive_servers:
|
||||
[ { address_data: 145.100.185.15
|
||||
, tls_auth_name: "dnsovertls.sinodun.com"
|
||||
|
@ -56,9 +62,4 @@
|
|||
} ]
|
||||
}
|
||||
]
|
||||
, tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
|
||||
, tls_query_padding_blocksize: 256
|
||||
, edns_client_subnet_private : 1
|
||||
, listen_addresses: [ 127.0.0.1, 0::1 ]
|
||||
, idle_timeout: 10000
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue