Open azadi opened 3 years ago
I believe this has been considered on the recursor side so far, re: #10002 and #8918
I believe this has been considered on the recursor side so far, re: #10002 and #8918
Ah indeed, thank you for referencing these tickets. I had not considered them on the recursor side as my understanding was that given dnsdist terminates TLS, that it should deal with this and pad as required. I will leave this open for the time being and perhaps wait for input from the developers.
dnsdist does terminate TLS, but it does not generate the answer. So adding the padding in dnsdist would mean more work parsing the answer sent by the client to get the EDNS UDP Payload Size, parsing the response sent by the backend to know where to insert padding (adding an EDNS option unfortunately involves editing the OPT record's rdlength
), making sure that the response does not already contain padding, then finally adding the padding.
On the other hand the backend does generate the answer already, so I'm currently much more inclined to let the backend know that the query was received over an encrypted channel, by routing these queries to a specific backend, specific port of a backend, or by using the proxy protocol to pass that information. Then the backend can handle the padding when generating the response, which is much more efficient.
I really should clarify that if someone wants EDNS padding to happen in dnsdist strongly enough to write the code, we would gladly accept that pull request :)
dnsdist does terminate TLS, but it does not generate the answer. So adding the padding in dnsdist would mean more work parsing the answer sent by the client to get the EDNS UDP Payload Size, parsing the response sent by the backend to know where to insert padding (adding an EDNS option unfortunately involves editing the OPT record's
rdlength
), making sure that the response does not already contain padding, then finally adding the padding. On the other hand the backend does generate the answer already, so I'm currently much more inclined to let the backend know that the query was received over an encrypted channel, by routing these queries to a specific backend, specific port of a backend, or by using the proxy protocol to pass that information. Then the backend can handle the padding when generating the response, which is much more efficient.
Hi and thanks for the response!
I see... I had not anticipated that it would be more work on the recursor side as I assumed that given dnsdist terminates TLS and that encryption protocols have been implemented in dnsdist and not the recursor, that it would be a better fit there and in my (imaginary) implementation I could pad the responses on their way out but I clearly underestimated the complexity of doing it within dnsdist. But now reading your response, I see why it makes sense to do this on the recursor and just forward requests from dnsdist.
I really should clarify that if someone wants EDNS padding to happen in dnsdist strongly enough to write the code, we would gladly accept that pull request :)
I trust you to know more about this than I do so I will wait for support to be added on the rec side :) Nevertheless, I look forward to this feature and I will try to be helpful with the existing tickets instead.
Please feel free to close this feature request if you think it is redundant. Thanks!
I'm currently much more inclined to let the backend know that the query was received over an encrypted channel
Sounds fine to me, but based on our observation this does not happen in PROXYv2 coming from dnsdist, contrary to e.g. haproxy.
That is, unless we're to "guess" that if proxy accepted the query on port 853 or 443, it's a sign of encryption. The protocol does have TLV_TYPE_SSL
... well, you can read on our details around https://gitlab.nic.cz/knot/knot-resolver/-/merge_requests/1238#note_243819
On a related note, I'm a little sad that Quad9 does not pad, even though I don't consider it a significant privacy leak. But I consider this leak cheap to eliminate, and most of good public resolvers have been padding encrypted answers for a long time.
Sounds fine to me, but based on our observation this does not happen in PROXYv2 coming from dnsdist, contrary to e.g. haproxy.
That is, unless we're to "guess" that if proxy accepted the query on port 853 or 443, it's a sign of encryption. The protocol does have
TLV_TYPE_SSL
... well, you can read on our details around https://gitlab.nic.cz/knot/knot-resolver/-/merge_requests/1238#note_243819
You are right, dnsdist does not set TLV_TYPE_SSL
, and we should really have an option to do that! It should technically be possible to do it using SetProxyProtocolValuesAction
1, but a simple option on newServer
would make much more sense.
Wouldn't it be good to pass the full protocol information to the backend servers? Currently it seems, that the recursor has no indicator about it and for the protobuf logging in the recursor, just the local L4 protocol (UDP/TCP) is used. What about passing the SocketProtocol
to the backend according to the proto file and apply that information for the logging as well?
enum SocketProtocol {
UDP = 1; // User Datagram Protocol (RFC 768)
TCP = 2; // Transmission Control Protocol (RFC 793)
DOT = 3; // DNS over TLS (RFC 7858)
DOH = 4; // DNS over HTTPS (RFC 8484)
DNSCryptUDP = 5; // DNSCrypt over UDP (https://dnscrypt.info/protocol)
DNSCryptTCP = 6; // DNSCrypt over TCP (https://dnscrypt.info/protocol)
}
https://docs.powerdns.com/recursor/lua-config/protobuf.html#protocol-buffers-definition
Defining a TLV with such information would be possible, but currently I can't see sufficient motivation to do it. Note that proxyv2 design is quite generic and simple, as if the proxies wouldn't touch anything deeper than TLS layer. (IIRC most implementations are around https and don't even do UDP.)
Quad9 may be willing to put some small amount of funds towards this being implemented in dnsdist if there is someone out there who wants to pick up the task. I know that's not the preferred location, but also recall that dnsdist can synthesize answers, which we use extensively, so padding needs to minimally happen as an option inside of dnsdist somehow. If there is going to be the minimal case for completeness, then it may make sense to implement for all queries instead of relying on the backend recursive resolver for this. I would be happy to see dnsdist support both methods - taking padding from backend resolvers, or generating the padding itself if that is not seen from the backend of if local generation is required for synthesized replies.
I'm tentatively moving this FR to the 1.10 milestone so we can re-evaluate, but please be aware that this is not a promise. DNSdist 1.9 is now adding the proxy protocol TLS TLV so it will be much easier to implement the padding in the recursor without having two separate endpoints, but I guess convincing other backends to do so might be a bit harder, and the fact that nothing happened in almost three years is not a great sign.
Thanks for the update @rgacogne and @johnhtodd! I wanted to share an existing bug report as a reminder about the issues with doing padding in pdns-recursor when used with dnsdist and in cases where ECS is enabled (#10884) which results in an incorrect padding, so perhaps doing it in dnsdist might be more helpful. (For cases where ECS is not a consideration, doing it in pdns-recursor itself where it already supports padding is fine of course).
Short description
RFC 7830 describes the EDNS(0) Padding Option that pads DNS queries and responses to prevent size-based correlation of encrypted DNS messages. The policies and their specific details are further described in RFC 8467. Given dnsdist support DNS-over-TLS and DNS-over-HTTPS, it will be good to have support for padding responses to further improve the privacy of DNS responses over an encrypted channel.
Usecase
RFC 8932 details recommendations for DNS privacy operators and recommends enabling padding to mitigate traffic analysis. If dnsdist were to support this feature, recursive resolver operators using dnsdist for their encrypted DNS frontends can enable padding in the DNS response to improve the privacy of communication between the stub resolver and the recursor (or a frontend, such as dnsdist).
dnsdist can have an extra configuration option that allows the user to specify if they want to enable padding or not. To
addDOHLocal
/addTLSLocal
, we can add an additionaloption
calledpadResponses
:If this is enabled and the other requirements for padding are met (client includes the padding option, request over TCP, encrypted frontend, etc.), then dnsdist should pad the responses to multiples of 468 bytes, as specified in RFC 8467.
Description
The RFCs mentioned above cover the topic in detail so I will avoid repeating that here. Instead, I will just focus on the current state of padding in different public resolver services and resolver software.
Among the popular public resolvers, both Cloudflare and Google support padding:
A more exhaustive list can be found at dnsprivacy.org. Given that many of these services are using dnsdist to provide DoH/DoT, they will all benefit from this feature and so will their users.
Among other DNS servers, Knot and BIND support padding responses.
For clients (and given that servers only pad responses when the client indicates support in the query): the EDNS(0) padding website describes the client implementations; the most notable user-facing client in the list being Android and its Private DNS/DoT mode. Firefox does not support it yet but there is an task for it on Bugzilla while Chromium seems to support it already.
Existing Work/Tickets
I have not found existing work or tickets on this topic. The closest I could find was this Open-Xchange link which describes a grant to work on implementing padding; quoting from the above, "We are also developing EDNS(0) padding, both for answers towards the authoritative server as well as for answers back to the client." But I am not aware what the relation to dnsdist/PowerDNS is (if any) and if there has been any public progress on this topic. (I asked on IRC and was told there has been no work on this so far.)
Current dnsdist support
In the current version of dnsdist, there is an EDNSOptionCode,
EDNSOptionCode.PADDING
. So while this can be used to apply rules/filters on queries with padding, there is no support to change the size of the responses through the Lua configuration.Development
Ideally, I would like to follow up on this feature request with a pull request if there is interest. I am trying to assess how much work is involved and when I can get to it but I thought it will be good to document this in the meantime.