java.lang.Object
net.i2p.util.DNSOverHTTPS
All Implemented Interfaces:
EepGet.StatusListener

public class DNSOverHTTPSextends Object implements EepGet.StatusListener
Simple implementation of DNS over HTTPS. Also sets the local clock from the received date header.

Warning - not thread-safe. Create new instances as necessary.

As of 0.9.49, this supports the RFC 8484 (DNS) format only. Does NOT support the JSON format (used prior to 0.9.49) or RFC 7858 (DNS over TLS).

https://developers.google.com/speed/public-dns/docs/dns-over-https https://developers.cloudflare.com/1.1.1.1/dns-over-https/json-format/ https://github.com/curl/curl/wiki/DNS-over-HTTPS

  • Field Details

  • Constructor Details

    • DNSOverHTTPS

      public DNSOverHTTPS(I2PAppContext context)
      Create a DNSOverHTTPS instance.
      Parameters:
      context - the I2P app context
    • DNSOverHTTPS

      public DNSOverHTTPS(I2PAppContext context, SSLEepGet.SSLState sslState)
      Create a DNSOverHTTPS instance.
      Parameters:
      context - the I2P app context
      sslState - the SSL state, or null
  • Method Details

    • lookup

      public String lookup(String host)
      V4_ONLY unless we have only IPv6 address, then V6_ONLY.
      Parameters:
      host - the hostname to resolve
      Returns:
      null if not found
    • lookup

      public String lookup(String host, DNSOverHTTPS.Type type)
      Lookup in cache, then query servers.
      Parameters:
      host - the hostname to resolve
      type - the query type
      Returns:
      null if not found
    • lookup

      private String lookup(String host, DNSOverHTTPS.Type type, String url)
      Lookup in cache, then query servers.
      Parameters:
      host - the host name to resolve
      type - the record type to return, A or AAAA
      url - null to query several default servers, or specify single server
      Returns:
      null if not found
    • clearCaches

      public static void clearCaches()
      Clear DNS caches and fail counts.
    • lookup

      private static String lookup(String host, Map<String, DNSOverHTTPS.Result> cache)
      Lookup in cache.
      Parameters:
      host - the host name to look up
      cache - the cache to search, keyed by host name
      Returns:
      null if not found or expired
    • query

      private String query(String host, DNSOverHTTPS.Type type, String url)
      Query servers.
      Parameters:
      host - the host name to resolve
      type - the record type to return, A or AAAA
      url - null to query several default servers, or specify single server
      Returns:
      null if not found
    • query

      private String query(String host, boolean isv6, List<String> toQuery, long timeout)
      Query one host over DNS-over-HTTPS.
      Parameters:
      host - the host name to resolve
      isv6 - true to query AAAA for an IPv6 answer, false for A
      toQuery - the DoH server URLs to try
      timeout - the absolute deadline in ms, servers are tried until it passes
      Returns:
      null if not found
    • fetch

      private String fetch(SSLEepGet eepget, String host, boolean isv6, Question q)
      Fetch one DNS answer over HTTPS.
      Parameters:
      eepget - the fetcher, already set up for the DoH server URL
      host - the host name being resolved, used for the CNAME fallback question
      isv6 - true if the original question was AAAA, used to re-query after a CNAME
      q - the DNS question whose answers are wanted
      Returns:
      null if not found
    • attemptFailed

      public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause)
      Description copied from interface: EepGet.StatusListener
      Attempt failed notification.
      Specified by:
      attemptFailed in interface EepGet.StatusListener
      Parameters:
      url - the address whose fetch attempt failed
      bytesTransferred - bytes received so far, counted across every attempt and including response headers
      bytesRemaining - bytes still owed, or -1 if unknown
      currentAttempt - zero-based index of the attempt that failed
      numRetries - total attempts this fetch is allowed
      cause - the exception that ended the attempt
      See Also:
    • bytesTransferred

      public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url)
      Description copied from interface: EepGet.StatusListener
      Total length should be == alreadyTransferred + currentWrite + bytesRemaining for all calls.
      Specified by:
      bytesTransferred in interface EepGet.StatusListener
      Parameters:
      alreadyTransferred - total of all attempts, not including currentWrite If nonzero on the first call, a partial file of that length was found, _and_ the server supports resume. If zero on a subsequent call after some bytes are transferred (and presumably after an attemptFailed), the server does _not_ support resume and we had to start over. To track _actual_ transfer if the output file could already exist, the listener should keep its own counter, or subtract the initial alreadyTransferred value. And watch out for alreadyTransferred resetting if a resume failed...
      currentWrite - since last call to the listener
      bytesTransferred - includes headers, retries, redirects, discarded partial downloads, ...
      bytesRemaining - on this attempt only, currentWrite already subtracted - or -1 if chunked encoding or server does not return a length
      url - the URL being fetched
    • transferComplete

      public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified)
      Description copied from interface: EepGet.StatusListener
      Transfer complete notification.
      Specified by:
      transferComplete in interface EepGet.StatusListener
      Parameters:
      alreadyTransferred - total bytes transferred
      bytesTransferred - total incl headers
      bytesRemaining - bytes still owed by the server, or -1 if chunked encoding or no Content-Length was returned
      url - the address the transfer was reading
      outputFile - null if unknown (output stream constructor)
      notModified - whether 304
      See Also:
    • transferFailed

      public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt)
      Description copied from interface: EepGet.StatusListener
      Transfer failed notification.
      Specified by:
      transferFailed in interface EepGet.StatusListener
      Parameters:
      url - the address whose transfer failed
      bytesTransferred - bytes received so far, counted across every attempt and including response headers
      bytesRemaining - bytes still owed, or -1 if unknown
      currentAttempt - zero-based index of the attempt that failed
      See Also:
    • attempting

      public void attempting(String url)
      Description copied from interface: EepGet.StatusListener
      Called when a new attempt to fetch the URL is starting.
      Specified by:
      attempting in interface EepGet.StatusListener
      Parameters:
      url - the URL being attempted
    • headerReceived

      public void headerReceived(String url, int attemptNum, String key, String val)
      Use the Date header as a backup time source. Code from Reseeder. We set the stratum to a lower (better) value than in Reseeder, as Cloudflare and Google probably have a better idea than our reseeds.
      Specified by:
      headerReceived in interface EepGet.StatusListener
      Parameters:
      url - the address the header arrived on
      attemptNum - zero-based index of the attempt the header arrived on
      key - header key
      val - header value
    • log

      private void log(String msg)
      Logs a message when debug logging is on.
      Parameters:
      msg - the message to log
    • log

      private void log(String msg, Throwable t)
      Logs a message with an exception when debug logging is on.
      Parameters:
      msg - the message to log
      t - the exception to log
    • loadURLs

      private static void loadURLs()
      Load the DoH server URLs.
    • main

      public static void main(String[] args)
      Main entry point for command line usage.
      Parameters:
      args - command line arguments
    • usage

      private static void usage()
      Prints the command line usage text.
    • decodeStamp

      private static String decodeStamp(String sdns, boolean log)
      Decode sdns:// stamps e.g. sdns://AgMAAAAAAAAADjE2My40Ny4xMTcuMTc2oMwQYNOcgym2K2-8fQ1t-TCYabmB5-Y5LVzY-kCPTYDmIEROvWe7g_iAezkh6TiskXi4gr1QqtsRIx8ETPXwjffOEGFkbC5hZGZpbHRlci5uZXQKL2Rucy1xdWVyeQ Ref: https://dnscrypt.info/stamps-specifications/
      Parameters:
      sdns - the sdns:// stamp to decode
      log - true to print decode errors to standard output
      Returns:
      the URL, or null on error or if not a DoH (type 2) stamp
    • decodeStamps

      private static void decodeStamps(String file) throws IOException
      Decode sdns:// stamps found in file. Stamps that are not DoH (type 2), or fail to decode, are skipped.
      Parameters:
      file - the file to scan line by line for sdns:// stamps
      Throws:
      IOException - if the file cannot be read