Subject: [Doh] Clarification for a newbie DoH implementor

From: "Mark Delany" <[email-masked]>
Date: 18 Apr 2019 07:12:38 +0000

I'm working on a proxy/server DoH implementation designed to install on CPE
and a private DoH server respectively. The development is strictly based on
the RFCs without reference to any existing implementations and there are a
few areas that seem ambiguous or undefined. I'm hoping to get clarity from
this list.

The model is: port 53 -> CPE proxy -> HTTPS -> private server -> localResolver

For those familiar with CPE think of a dnsmasq replacement.

The questions:

## TTL reduction due to HTTP "Age" header

RFC8484 Section 5.1 advises that clients MUST account for the HTTP "Age"
header by reducing TTLs. Unfortunately the RFC is silent on what to do if
that reduction causes the TTL to be reduced to zero or below. Should the RR
be removed which could result in an empty/odd response? Should the TTL be set
to zero and let the client deal with it? This seems a risky choice as client
behaviour with zero TTL is well-know to be quite unpredictable.

Current behaviour is to never set the TTL lower than 1s and leave
every RR in place.

## ECS Performance

I've had conversations around this topic in other forums and consensus seems
hard to find. Should a DoH server - when appropriately configured or
signalled - add an ECS option based on the HTTPS client source IP? That seems
like it would really help ECS-aware auths give much better answers than they
otherwise would. Particularly as DoH servers are likely to be topologically
distant from DoH clients resulting in otherwise very sub-optimal ECS answers.

As best I can tell, ECS is perfectly suit to DoH but the RFC is silent on the
matter. So what's the general thinking?

## ECS Privacy

The converse view is that ECS is antithetical to DoH and should be avoided
with extreme prejudice. If so, should a DoH implementation remove any
pre-existing ECS option to protect a naive client? I know it's not
particuarly likely as ECS is mostly generated by resolvers/caches rather than
stubs or clients, nonetheless having a DoH implementation let a
privacy-exposing option leak out seems at odds with the central tenant of
DoH.

** RFC8467 DNS Padding for DoH client

RFC8484 Section 9 recommends adding padding to the DNS query sent between
client and server. What should a client do if the query already contains
padding? Should it assume the initiator has a specific purpose in mind and
not do anything or should it replace the padding to comply with RFC8484?
Again unlikely, but not impossible.

** RFC8467 DNS Padding for DoH server

RFC8484 is not clear about whether a DoH server should forward queries with
any existing padding remaining in place or whether the padding should be
removed. Arguably from a "layering" perspective if the DoH client has "pushed
padding onto the stack" then the DoH server should "pop it off the
stack". But the DoH server has no idea whether the padding was added by the
DoH client or whether it was in the original query given to the client. The
other thing to consider is that passing on padding may disclose that the
query probably travelled via DoH. Is that a concern given we're trying not to
disclose anything about the client?

** RFC8484 DNS Padding for GET requests

My first thought is that DNS padding should apply to both GET and POST
methods, but 4.1.1 says "Finally, a GET-based query ... and that padding is
omitted". Is "padding omitted" referring to DNS padding or base64url padding?
I presume base64url padding, but it's ambiguous.

For now the implementation doesn't add DNS padding for GET requests. Should I
change that?

** RFC8467 padding ambiguity with "closest multiples" and "a multiple"

I've sent this to dprive but maybe it's more appropriate here. This is a
truly minor nit about the precision of the text in 4.1. Nonetheless...

For clients the text says pad to the "closest multiple" but for servers the
text says pad to "a multiple". A literal interpretation is that servers can
use a padding value which may *not* be the closest multiple, but maybe 2 or 3
or 100 multiples?

My interpretation is that the intent is the same for both client and server,
namely that the padding should increase the size to the next multiple up as I
don't see anything else in the text that explains why larger multiples are of
value.

But it may be that a server is given latitude for some security or traffic
analysis reason I don't understand. Is that latitude in the text on purpose
and if so on what basis should a server exercise that latitude?

**

A naive answer to most of these questions is that the DoH channel is merely a
secure tunnel transporting a DNS blob. Leastwise I think the primordial DoH
implementations worked that way. But that genie was let out of the bottle
with the "Age" header modifications and DNS padding and possibly ECS. In
short DoH implementations are now expected to peer into the message and mess
with it.

I'm new to DoH so any and all clarification and corrections appreciated.

Mark.

---

From: Vladimír Čunát <[email-masked]>
Date: Thu, 18 Apr 2019 14:20:33 +0200

Hello!
Reactions to particular parts inline.  I omitted those where I can't say
too much.

On 4/18/19 9:12 AM, Mark Delany wrote:
> [...]

I believe the HTTP "Age" makes sense as the minimum of all TTLs in the
packet, or optionally smaller but never larger.  Therefore it should not
happen, but in case it does, I can't think of anything better than
resetting the underflowed TTLs to 1s.

The RFC only bounds to minimum TTL *in answer section*, but I believe
that's a mistake as you can't just ignore authority section at least. 
There may be records vital for DNSSEC validation of negative answers,
for example.

> ## ECS Performance, Privacy, etc.

I can't see how using a different transport makes ECS issues different. 
If you use UDP forwarding to some public resolver, you are in pretty
same situation, except that you're more likely to be intercepted, etc.

> ** RFC8467 DNS Padding for DoH client

I'm not so sure about this, but my point of view is, shortly, that
padding is a per-hop thing.  It depends on the particular transport -
for unencrypted ones it doesn't even make any sense, so I can't see why
padding should matter between your proxy and its clients.  I believe
this point of view is consistent with the RFC, too.

> For now the implementation doesn't add DNS padding for GET requests. Should I

That's certainly about base64url padding.  It could get clarified in the
RFC, but I suspect most people don't get to reading errata or
"corrected" RFC versions.

--Vladimir (Knot Resolver)

---

From: "Mark Delany" <[email-masked]>
Date: 19 Apr 2019 00:25:30 +0000

On 18Apr19, Vladim??r ??un??t allegedly wrote:
> Hello!
> Reactions to particular parts inline.?? I omitted those where I can't say
> too much.

Thanks.

> that's a mistake as you can't just ignore authority section at least.??

I agree, particularly as an "Age" response might come from a caching
HTTP server which is oblivious to the payload. Since "Age" is saying
the whole payload has aged thus it should logically apply to all TTLs
inside.

> padding is a per-hop thing.?? It depends on the particular transport

Yeah. I guess the thing is that a DNS message didn't typically
traverse multiple hops until DoH came along so the question never
arose. As you well know, most often a message triggers new messages
rather than being forwarding directly. But I agree that padding seems
like a per-hop/per-transport value.

As it turns out I don't think a DoH proxy has to care about
pre-existing padding as it should be able to arbitrarily add a second
padding to the message to meet the modulo size requirements. Is there
anything that says two paddings options in one message are illegal? It
might be more efficient to replace the existing padding, but RFC7830
is silent on the matter of multiple occurrences.

  (It's also interesting that padding has been placed inside the DNS
  message as opposed to something appended to the HTTP payload. Both
  work just as well to mitigate the traffic analysis risk. However
  this in-message approach forces a proxy implementation to
  disassemble and reassemble the message and thus have a fairly full
  understanding of the DNS message structure rather than just append a
  blob of zeros to a blob of HTTP payload. That's a lot of extra
  complexity to add a few zero bytes. Oh well, that ship has well and
  truly sailed!)

> That's certainly about base64url padding.?? It could get clarified in the

Or the original RFCs for that matter :-)

In retrospect I think GET should have padding as it mitigates the same
risks as POST but it also might reduce cacheability if some proxys pad
and others don't... And the RFC authors did worried a bit about HTTP
cacheability as witness by the zero ID for GET rule. All in all tho,
since GET is discouraged it's unlikely to be a big deal.

Thanks again for your responses.

Mark.