DNS-over-HTTPS) work during the hackathonCode written for the DoH (
All the code here work with HTTP/2 and TLS.
quart-doh.py is a server written in Python with the
Quart framework for HTTP/2. It
uses the dnspython library to send the request to a full resolver. You
can start it with
./quart-doh.py -r YOURESOLVER (
-h for other
-c, you have a checking mode, for interoperability testing.
Work under way for CoreDNS
Firefox has now a DoH client
doh-nghttp.c is a C client, using the
nghttp2 asynchronous HTTP/2 library and the
getdns library to encode and decode DNS
messages. You can compile it with
cc -c doh-nghttp.c and link it
cc -odoh-nghttp doh-nghttp.o getdns-git/src/parseutil.o -lnghttp2 -lhttp_parser -levent -lssl -lcrypto -levent_openssl -lgetdns.
Work is under way for the C library getdns. The development branch for this work is here. It relies on the new upstream server management code. Once finished, this is how DoH upstreams can be configured in a Stubby YAML configuration file:
# Specify the list of upstream recursive name servers to send queries to upstream_recursive_servers: # Manu Bretelle's DNS over HTTPS server: - uri: "https://dns.dnsoverhttps.net/dns-query" # The google DNS over HTTPS server: - uri: "https://dns.google.com/experimental" # The cloudflare DNS over HTTPS server: - uri: "https://dns.cloudflare.com/.well-known/dns-query" # The Stephane Bortzmeyer's DNS over HTTPS server: - uri: "https://dns.bortzmeyer.fr" # The quad9 DNS over TLS server - name: "dns.quad9.net"
Public DoH servers
It is interesting to know that each uses a different code base.
- https://dns.bortzmeyer.fr (ephemeral / temporary)
- https://vm1.dev.dns.cam.ac.uk/doh (v6 only, ephemeral / temporary)
Ideas for interoperability testing
Client side tests are tests that would be run from the client to test the server conformance
Server side tests are errors that would be logged if a client was to send invalid content
- correct MIME type
- return code should be 415 when the content type is invalid
- return code should be 405 when the method is not accepted (check that Allow header is set). What about HEAD? if the server does not accept GET, then HEAD is pointless . doh-proxy fail the HEAD handling: https://github.com/facebookexperimental/doh-proxy/issues/37
- return code should be 406 when the content type is not accepted by the server: does the server returns a list of accepted content type?
- does server supports GET
- does server supports POST
- Invalid certificates should be rejected
- "intelligent" use of the cache-control and expires headers
- send Base64 with padding
- ID set to 0
- if GET, check that ct= and dns= exist and that ct= has a proper value
- check the MIME type
Manu Bretelle's test system. To
pip install -e .[integration_tests]. To run
PYTHONPATH=. python3 ./dohproxy/integration.py --domain dohserver.example.com. See
-h for more options.
This is using the unittest framework and basically will print the result for individual tests and then spit out the exceptions.
test-servers.py (requires dnspython and pycurl) tests several servers:
https://dns.dnsoverhttps.net/dns-query WARNING: Impossible content type requested and accepted https://dns.google.com/experimental ERROR: HTTP error in reply to HEAD 400 WARNING: Impossible content type requested and accepted https://dns.cloudflare.com/.well-known/dns-query INFO: GET not implemented INFO: HEAD not implemented WARNING: Impossible content type requested and accepted https://dns.bortzmeyer.fr WARNING: Impossible content type requested and accepted
Questions/notes about the current draft
Wire format specification should explicitly say that length preambule is not part of the DNS wireformat blob, just to be explicit? No implementor included it (it is useless for HTTP).
Should we use GET, POST or both? (see the Cloudflare test above)
As always during a hackathon, some bugs were discovered in the libraries used, and sometimes fixed even before the end of the hackathon