From cf88b3057aa2f23d2a189db07800d98b524b5e17 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Mon, 26 Oct 2020 13:44:23 +0000 Subject: [PATCH] DoH: limit total time and max requests Better loop checking, force DoH off for request --- core/java/src/net/i2p/util/DNSOverHTTPS.java | 36 +++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/core/java/src/net/i2p/util/DNSOverHTTPS.java b/core/java/src/net/i2p/util/DNSOverHTTPS.java index 6b02742c3a..3d3167a765 100644 --- a/core/java/src/net/i2p/util/DNSOverHTTPS.java +++ b/core/java/src/net/i2p/util/DNSOverHTTPS.java @@ -43,9 +43,9 @@ public class DNSOverHTTPS implements EepGet.StatusListener { private static final Map<String, Result> v4Cache = new LHMCache<String, Result>(32); private static final Map<String, Result> v6Cache = new LHMCache<String, Result>(32); // v4 URLs to query, ending with '&' - private static final List<String> v4urls = new ArrayList<String>(4); + private static final List<String> v4urls = new ArrayList<String>(8); // v6 URLs to query, ending with '&' - private static final List<String> v6urls = new ArrayList<String>(4); + private static final List<String> v6urls = new ArrayList<String>(8); // consecutive failures private static final ObjectCounter<String> fails = new ObjectCounter<String>(); @@ -64,7 +64,11 @@ public class DNSOverHTTPS implements EepGet.StatusListener { } ); static { - // Warning: All hostnames MUST be in loop check in lookup() below + // Public lists: + // https://dnscrypt.info/public-servers/ + // https://github.com/curl/curl/wiki/DNS-over-HTTPS#publicly-available-servers + // https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Public+Resolvers#DNSPrivacyPublicResolvers-DNS-over-HTTPS(DoH) + // Google // https://developers.google.com/speed/public-dns/docs/doh/ // 8.8.8.8 and 8.8.4.4 now redirect to dns.google, but SSLEepGet doesn't support redirect @@ -89,9 +93,13 @@ public class DNSOverHTTPS implements EepGet.StatusListener { // keep the timeout very short, as we try multiple addresses, // and will be falling back to regular DNS. private static final long TIMEOUT = 3*1000; + // total for v4 + v6 + private static final long OVERALL_TIMEOUT = 10*1000; private static final int MAX_TTL = 24*60*60; // don't use a URL after this many consecutive failures private static final int MAX_FAILS = 3; + // each for v4 and v6 + private static final int MAX_REQUESTS = 4; private static final int V4_CODE = 1; private static final int CNAME_CODE = 5; private static final int V6_CODE = 28; @@ -203,21 +211,22 @@ public class DNSOverHTTPS implements EepGet.StatusListener { private String query(String host, Type type) { List<String> toQuery = new ArrayList<String>((type == Type.V6_ONLY) ? v6urls : v4urls); Collections.shuffle(toQuery); + final long timeout = System.currentTimeMillis() + OVERALL_TIMEOUT; if (type == Type.V4_ONLY || type == Type.V4_PREFERRED) { // v4 query - String rv = query(host, false, toQuery); + String rv = query(host, false, toQuery, timeout); if (rv != null) return rv; } if (type != Type.V4_ONLY) { // v6 query - String rv = query(host, true, toQuery); + String rv = query(host, true, toQuery, timeout); if (rv != null) return rv; } if (type == Type.V6_PREFERRED) { // v4 query after v6 query - String rv = query(host, false, toQuery); + String rv = query(host, false, toQuery, timeout); if (rv != null) return rv; } @@ -227,8 +236,16 @@ public class DNSOverHTTPS implements EepGet.StatusListener { /** * @return null if not found */ - private String query(String host, boolean isv6, List<String> toQuery) { + private String query(String host, boolean isv6, List<String> toQuery, long timeout) { + int requests = 0; + final String loopcheck = "https://" + host + '/'; for (String url : toQuery) { + if (requests >= MAX_REQUESTS) + break; + if (System.currentTimeMillis() >= timeout) + break; + if (url.startsWith(loopcheck)) + continue; if (fails.count(url) > MAX_FAILS) continue; int tcode = isv6 ? V6_CODE : V4_CODE; @@ -236,6 +253,7 @@ public class DNSOverHTTPS implements EepGet.StatusListener { log("Fetching " + furl); baos.reset(); SSLEepGet eepget = new SSLEepGet(ctx, baos, furl, state); + eepget.forceDNSOverHTTPS(false); if (ctx.isRouterContext()) eepget.addStatusListener(this); else @@ -248,9 +266,11 @@ public class DNSOverHTTPS implements EepGet.StatusListener { if (state == null) state = eepget.getSSLState(); // we treat all fails the same, whether server responded or not + requests++; fails.increment(url); log("No result from " + furl); } + log("No result after " + requests + " attempts"); return null; } @@ -343,7 +363,7 @@ public class DNSOverHTTPS implements EepGet.StatusListener { } log("Bad response:\n" + new String(b)); } else { - log("Fail fetching"); + log("Fail fetching, rc: " + eepget.getStatusCode()); } return null; } -- GitLab