Deal with DoT servers that take long to connect to

(because they might be under attack)
This commit is contained in:
Willem Toorop 2020-02-21 14:17:00 +01:00
parent dadddb0d7b
commit d7099f6e30
3 changed files with 26 additions and 6 deletions

View File

@ -925,6 +925,7 @@ upstream_init(getdns_upstream *upstream,
/* For sharing a socket to this upstream with TCP */
upstream->fd = -1;
upstream->expires = 0;
upstream->tls_obj = NULL;
upstream->tls_session = NULL;
upstream->tls_cipher_list = NULL;

View File

@ -209,7 +209,10 @@ typedef struct getdns_upstream {
_getdns_tls_session* tls_session;
getdns_tls_hs_state_t tls_hs_state;
getdns_auth_state_t tls_auth_state;
uint64_t expires; /* Expire time of waiting netreqs.
* This is how long a handshake may
* take.
*/
/* TLS settings */
char *tls_cipher_list;
char *tls_ciphersuites;

View File

@ -68,7 +68,8 @@
#define STUB_TCP_ERROR -2
/* Don't currently have access to the context whilst doing handshake */
#define TIMEOUT_TLS 2500
#define MIN_TLS_HS_TIMEOUT 2500
#define MAX_TLS_HS_TIMEOUT 7500
/* Arbritray number of message for EDNS keepalive resend*/
#define EDNS_KEEPALIVE_RESEND 5
@ -981,13 +982,23 @@ tls_do_handshake(getdns_upstream *upstream)
int r;
while ((r = _getdns_tls_connection_do_handshake(upstream->tls_obj)) != GETDNS_RETURN_GOOD)
{
uint64_t timeout_tls = _getdns_ms_until_expiry(upstream->expires);
if (timeout_tls < MIN_TLS_HS_TIMEOUT)
timeout_tls = MIN_TLS_HS_TIMEOUT;
else if (timeout_tls > MAX_TLS_HS_TIMEOUT)
timeout_tls = MAX_TLS_HS_TIMEOUT;
DEBUG_STUB("%s %-35s: FD: %d, do_handshake -> %d (timeout: %d)\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, r, (int)timeout_tls);
switch (r) {
case GETDNS_RETURN_TLS_WANT_READ:
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
upstream->event.read_cb = upstream_read_cb;
upstream->event.write_cb = NULL;
GETDNS_SCHEDULE_EVENT(upstream->loop,
upstream->fd, TIMEOUT_TLS, &upstream->event);
upstream->fd, timeout_tls, &upstream->event);
upstream->tls_hs_state = GETDNS_HS_READ;
return STUB_TCP_RETRY;
case GETDNS_RETURN_TLS_WANT_WRITE:
@ -995,7 +1006,7 @@ tls_do_handshake(getdns_upstream *upstream)
upstream->event.read_cb = NULL;
upstream->event.write_cb = upstream_write_cb;
GETDNS_SCHEDULE_EVENT(upstream->loop,
upstream->fd, TIMEOUT_TLS, &upstream->event);
upstream->fd, timeout_tls, &upstream->event);
upstream->tls_hs_state = GETDNS_HS_WRITE;
return STUB_TCP_RETRY;
default:
@ -1199,7 +1210,12 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
_getdns_tls_connection* tls_obj = upstream->tls_obj;
uint16_t padding_sz;
int q = tls_connected(upstream);
int q;
if (netreq->owner->expires > upstream->expires)
upstream->expires = netreq->owner->expires;
q = tls_connected(upstream);
if (q != 0)
return q;
/* This is the case where the upstream is connected but it isn't an authenticated
@ -2226,7 +2242,7 @@ upstream_schedule_netreq(getdns_upstream *upstream, getdns_network_req *netreq)
/* Set a timeout on the upstream so we can catch failed setup*/
upstream->event.timeout_cb = upstream_setup_timeout_cb;
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
_getdns_ms_until_expiry(netreq->owner->expires)/2,
_getdns_ms_until_expiry(netreq->owner->expires)/5*4,
&upstream->event);
#if defined(HAVE_DECL_TCP_FASTOPEN) && HAVE_DECL_TCP_FASTOPEN \
&& !(defined(HAVE_DECL_TCP_FASTOPEN_CONNECT) && HAVE_DECL_TCP_FASTOPEN_CONNECT) \