Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DNS over HTTPS response truncated #503

Closed
astounding opened this issue Jun 22, 2021 · 4 comments
Closed

DNS over HTTPS response truncated #503

astounding opened this issue Jun 22, 2021 · 4 comments

Comments

@astounding
Copy link

Hi,

I've been testing DoH using Unbound 1.13.1 (I installed the prebuilt binary from FreeBSD's port package) on a FreeBSD 12.2 machine, using a Let's Encrypt TLS certificate. Unbound starts and listens on my DoH port, and when I connect to it, the HTTP/2's TLS session is established as expected. I send a simple DNS query and the server sends a response. The response is oddly truncated one byte short such that it is NOT a valid response.

RAW QUERY, 28 BYTES:
58, 102, # Query ID
1, # qr=0 (request), opcode=0, aa=0,
# tc=0, rd=1 (recursion desired)
0, # ra=0, z=0, rcode=0
0, 1, # Number of questions: 1
0, 0, # Number of answers: 0
0, 0, # Authority RRs: 0
0, 0, # Additional RRs: 0
--- QUESTION 1 of 1 ---
6, 103, 111, 111, 103, 108, 101, # label "google"
3, 99, 111, 109, # Label "com"
0, # End of labels
0, 1, # Class "IN" (1)
0, 1 # Resource type "A" (1)

Local Unbound 1.13.1 test server using HTTP/2:
https://unbound.example.org/dns-query?dns=OmYBAAABAAAAAAAABmdvb2dsZQNjb20AAAEAAQ==

HTTP/2 Response Headers:
Content-Type: application/dns-message
Content-Length: 27

RAW REPLY, 27 BYTES:
58, 102, # Query ID (matches question ID)
129, # qr=1 (answer), opcode=0, aa=0,
# rc=0, rd=1 (recursion desired)
1, # ra=0 (recursion NOT available),
# z=0, rcode=1
# rcode=1 (format error) WHAT??
0, 1, # Number of questions: 1
0, 0, # Number of answers: 0
0, 0, # Authority RRs: 0
0, 0, # Additional RRs: 0
--- QUESTION 1 of 1 ---
6, 103, 111, 111, 103, 108, 101,# Label "google"
3, 99, 111, 109, # Label "com"
0, # End of labels
0, 1, # Class "IN" (1)
0, X <<< MISSING BYTE X # Record type MUST BE 2 BYTES not ONE

NOTE the "Content-Length" header indicates the server's response is exactly 27 bytes in length. However, to be valid, it SHOULD have been 28 bytes in length.

(I've posted my questions to the user list regarding why Unbound responded with an error when my query was valid--but that's separate from this bug report that the response with the error is oddly truncated one byte short.)

Thanks!

--Aaron out

@astounding astounding changed the title DNS over HTTPS query truncated DNS over HTTPS response truncated Jun 22, 2021
@wcawijngaards
Copy link
Member

If I trigger a FORMERR response locally, I get a 28 byte response. The different FORMERR code paths are different, though, so it is interesting to know what caused your format error response, perhaps that code path is different somehow.

I triggered it by setting up a DNS over HTTPS service, and using 'dohclient' to query for type TSIG; which is a transaction type; and this gets a format error response. Of 28 bytes. So I cannot reproduce, by making a format error.

That said, I also see nothing wrong with your query, that you post. What caused the format error? Did you send only 27 bytes? That would cause unbound to send this failure response, as it copies the query to the output, with little modification, because it is unparsable. You state it was 28 bytes sent, where did you observe this? There could be an error after that point that loses a byte; perhaps on the query path. That would also explain the format error response from unbound, because the query was one byte short.

@wcawijngaards
Copy link
Member

I can reproduce the problem, your query is malformed. The dohclient program does not produce the trailing '==' padding after it. That is part of normal base64 encoding, but not for dns over https base64 query encoding. The query you have then has no padding.

@wcawijngaards
Copy link
Member

Fixed this by making unbound lenient for it. The spec is however to use a modified version of base64 encoding for DNS queries, for base64 encoding parameters in the URL of a http query. This omits certain characters and does not use padding.

Unbound detects if the wrong character set or padding is used, and then it switches to the ordinary base64 encoding to decode the query. In verbose logs at high verbosity, unbound logs that the wrong encoding was used for this query.

@astounding
Copy link
Author

Somewhere in 1.13.1's error response, something was truncating the 28-byte response to only 27 bytes. Unbound's HTTP/2 response claimed a "Content-Length" of 27 bytes. I was able to reproduce it on the command line easily:

user@group:~$ curl -o reply.bin https://unbound.example.org/dns-query?dns=OmYBAAABAAAAAAAABmdvb2dsZQNjb20AAAEAAQ==
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    27  100    27    0     0   1800      0 --:--:-- --:--:-- --:--:--  1800
user@example:~$ ls -l reply.bin
-rw-r--r--  1 user  group  27 Jun 23 11:04 reply.bin
user@example:~$ 

Thanks for making Unbound more lenient in accepting '=' padding characters at the end of the query.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants