--- httpd-2.4.29/modules/proxy/mod_proxy.c 2017-10-13 09:30:15.000000000 +0200 +++ httpd-2.4.29/modules/proxy/mod_proxy.c 2017-11-20 16:22:25.199425973 +0100 @@ -129,6 +129,16 @@ return "TTL must be at least one second"; worker->s->ttl = apr_time_from_sec(ival); } + else if (!strcasecmp(key, "dnsttl")) { + /* Time in seconds that will cause a new dns lookup + * for the connection + */ + ival = atoi(val); + if (ival < 1) { + return "DNSTTL must be at least one second"; + } + worker->s->dns_ttl = apr_time_from_sec(ival); + } else if (!strcasecmp(key, "min")) { /* Initial number of connections to remote */ --- httpd-2.4.29/modules/proxy/mod_proxy.h 2017-08-18 10:49:42.000000000 +0200 +++ httpd-2.4.29/modules/proxy/mod_proxy.h 2017-11-20 16:23:02.511427302 +0100 @@ -285,6 +285,7 @@ /* Connection pool */ struct proxy_conn_pool { + apr_time_t updated; /* timestamp of last update */ apr_pool_t *pool; /* The pool used in constructor and destructor calls */ apr_sockaddr_t *addr; /* Preparsed remote address info */ apr_reslist_t *res; /* Connection resource list */ @@ -414,6 +415,7 @@ apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */ apr_interval_time_t ping_timeout; apr_interval_time_t conn_timeout; + apr_interval_time_t dns_ttl; /* TTL for a stored DNS ip address to be looked up again */ apr_size_t recv_buffer_size; apr_size_t io_buffer_size; apr_size_t elected; /* Number of times the worker was elected */ --- httpd-2.4.29/modules/proxy/proxy_util.c 2017-09-19 12:17:40.000000000 +0200 +++ httpd-2.4.29/modules/proxy/proxy_util.c 2017-11-20 16:35:45.607454477 +0100 @@ -2337,13 +2337,30 @@ conn->hostname, APR_UNSPEC, conn->port, 0, worker->cp->pool); + worker->cp->updated = apr_time_now(); conn->addr = worker->cp->addr; if ((uerr = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, uerr, r, APLOGNO(00946) "unlock"); } } else { - conn->addr = worker->cp->addr; + /* cp pool has been created once + dns_ttl is set + dns ttl expired */ + if ( worker->cp->updated && worker->s->dns_ttl && \ + ( worker->s->dns_ttl < ( apr_time_now() - worker->cp->updated ) ) ) { + worker->cp->updated = apr_time_now(); + /* work in current conn directly */ + err = apr_sockaddr_info_get(&(conn->addr), + conn->hostname, APR_UNSPEC, + conn->port, 0, + conn->pool); + /* save in cp if different */ + if (! apr_sockaddr_equal(worker->cp->addr, conn->addr) ) { + apr_sockaddr_info_copy(&(worker->cp->addr), conn->addr, worker->cp->pool); + } + } + else { + conn->addr = worker->cp->addr; + } } } }