The dig is a tool on linux to make dns query, and dnspython is a python packet to make dns query. I want to make DOH query and I have tried these two ways. When I use dig, I succeed, but when I use dnspython, I fail.
1. Environment initialization
I use Dockerfile to describe my environment:
FROM ubuntu:22.04
WORKDIR /home
RUN apt-get update \
&& apt-get install -y python3 python3-pip dnsutils \
&& pip install httpx dnspython -i https://pypi.tuna.tsinghua.edu.cn/simple/
2. Query "www.google.com" to Open NIC.
Open NIC is a famous dns recursive server(https://wiki.opennic.org/user/olde16).
I use the recursive "dns2.dns-ga.de", whose DOH path is "https://secure-dns.dns-ga.de/dns-query".
dig succeeds:
root@bf73bd1fde6f:/home# dig www.google.com @secure-dns.dns-ga.de +https
; <<>> DiG 9.18.12-0ubuntu0.22.04.2-Ubuntu <<>> www.google.com @secure-dns.dns-ga.de +https
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44949
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: c76afa9b3cb7e2d80100000064bf560f900d0d5140b8bcdd (good)
;; QUESTION SECTION:
;www.google.com. IN A
;; ANSWER SECTION:
www.google.com. 138 IN A 142.250.179.100
;; Query time: 248 msec
;; SERVER: 217.160.166.161#443(secure-dns.dns-ga.de) (HTTPS)
;; WHEN: Tue Jul 25 04:56:47 UTC 2023
;; MSG SIZE rcvd: 87
dnspython fails:
root@bf73bd1fde6f:/home# python3
Python 3.10.6 (main, May 29 2023, 11:10:38) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dns.query
>>> import dns.message
>>> query_message = dns.message.make_query("www.google.com", "A", "IN")
>>> result = dns.query.https(query_message, "https://secure-dns.dns-ga.de/dns-query", timeout=5)
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/httpcore/_exceptions.py", line 10, in map_exceptions
yield
File "/usr/local/lib/python3.10/dist-packages/httpcore/_backends/sync.py", line 62, in start_tls
raise exc
File "/usr/local/lib/python3.10/dist-packages/httpcore/_backends/sync.py", line 57, in start_tls
sock = ssl_context.wrap_socket(
File "/usr/lib/python3.10/ssl.py", line 513, in wrap_socket
return self.sslsocket_class._create(
File "/usr/lib/python3.10/ssl.py", line 1071, in _create
self.do_handshake()
File "/usr/lib/python3.10/ssl.py", line 1342, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'secure-dns.dns-ga.de'. (_ssl.c:997)
3. Query "www.google.com" to Yandex.DNS.
Yandex.DNS is also a famous DNS recursive server(https://dns.yandex.com/ ).
According to its website, the IP to query DOH is "77.88.8.8".
dig succeeds
root@bf73bd1fde6f:/home# dig www.google.com @77.88.8.8 +https
; <<>> DiG 9.18.12-0ubuntu0.22.04.2-Ubuntu <<>> www.google.com @77.88.8.8 +https
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44504
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.google.com. IN A
;; ANSWER SECTION:
www.google.com. 225 IN A 142.251.1.104
www.google.com. 225 IN A 142.251.1.105
www.google.com. 225 IN A 142.251.1.147
www.google.com. 225 IN A 142.251.1.106
www.google.com. 225 IN A 142.251.1.103
www.google.com. 225 IN A 142.251.1.99
;; Query time: 228 msec
;; SERVER: 77.88.8.8#443(77.88.8.8) (HTTPS)
;; WHEN: Tue Jul 25 04:59:43 UTC 2023
;; MSG SIZE rcvd: 139
dnspython fails with a different error
root@bf73bd1fde6f:/home# python3
Python 3.10.6 (main, May 29 2023, 11:10:38) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dns.query
>>> import dns.message
>>> query_message = dns.message.make_query("www.google.com", "A", "IN")
>>> result = dns.query.https(query_message, "77.88.8.8", timeout=5)
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/httpcore/_exceptions.py", line 10, in map_exceptions
yield
File "/usr/local/lib/python3.10/dist-packages/httpcore/_sync/http11.py", line 197, in _receive_event
event = self._h11_state.next_event()
File "/usr/local/lib/python3.10/dist-packages/h11/_connection.py", line 487, in next_event
exc._reraise_as_remote_protocol_error()
File "/usr/local/lib/python3.10/dist-packages/h11/_util.py", line 77, in _reraise_as_remote_protocol_error
raise self
File "/usr/local/lib/python3.10/dist-packages/h11/_connection.py", line 469, in next_event
event = self._extract_next_receive_event()
File "/usr/local/lib/python3.10/dist-packages/h11/_connection.py", line 411, in _extract_next_receive_event
event = self._reader(self._receive_buffer)
File "/usr/local/lib/python3.10/dist-packages/h11/_readers.py", line 100, in maybe_read_from_SEND_RESPONSE_server
raise LocalProtocolError("illegal request line")
h11._util.RemoteProtocolError: illegal request line