pdns
pdns copied to clipboard
PowerDNS Auth does not forward EDNS Client Subnet for ALIAS records
- Program: Authoritative
- Issue type: Bug report
Short description
Authoritative PowerDNS server does not forward EDNS Client Subnet to the server specified as "resolver=" when processing ALIAS records, which quite much destroys the performance when using it together with CDN services that rely on the EDNS Client Subnet to route users to the nearest server.
Not forwarding isn't really consistent with the documentation about ALIAS processing either: -> https://github.com/PowerDNS/pdns/blob/master/docs/WIP/alias.md
## EDNS Subnet
Authoritative servers sometimes give out different answers based on the IP
address of the resolver asking. As a further refinement, some resolvers can
pass along (part) of the actual stub-resolver asking the question, and base
its answer on that 'real' address.
For ALIAS processing, implementors are encouraged to pass along or use all
knowledge of the remote client IP address when retrieving A or AAAA records.
Environment
- Operating system: Debian 8
- Software version: master branch (0.0.1728g70bd485-1pdns.jessie)
- Software source: PowerDNS repository
Steps to reproduce
- Install (or compile) PowerDNS
- In the configuration, set:
edns-subnet-processing=yes
expand-alias=yes
resolver=8.8.8.8
- Create zone "example.com" where you ALIAS "example.com" and/or "www.example.com" to "www.google.com"
- Look up either "example.com" or "www.example.com" and compare "www.google.com"
dig @ns1.example.com example.com
dig @ns1.example.com www.example.com
dig @8.8.8.8 www.google.com
- With your server "ns1.example.com" being in the United States, and you being in e.g. United Kingdom where Google has a local cache server within your ISP's network, the first two dig will route you towards Google's nearest instances (e.g. Netherlands), rather than the local ones within your ISP in United Kingdom. With CDN services, the same happens where both "example.com" and "www.example.com" are reaching locations closer to the United States rather than locations close to (or in) United Kingdom.
Expected behaviour
When 192.0.2.123 queries ns1.example.com for "example.com" or "www.example.com" with a EDNS Client Subnet of "198.51.100.0/24", then "198.51.100.0/24" should be forwarded to the resolver 8.8.8.8, as set in "resolver=".
Actual behaviour
When PowerDNS queries for "www.google.com", the query is made to 8.8.8.8 ("resolver=") without any EDNS Client Subnet attached at all, reducing the overall performance of the CDN.
The EDNS Client Subnet is never making its way to the final destination, since it doesn't even make the way to the server set in "resolver=".
Yes, indeed we did not implement ECS here. We will soon start our implementation of https://datatracker.ietf.org/doc/draft-ietf-dnsop-aname/ and it is likely ECS will happen as part of that.
For ECS based ALIAS Records from the pipe backend, it would be great to consider the returned ECS scope bits as well. I can see at least three scenarios for that:
- No scope bits (zero scope bits) from pipe backend in ALIAS Record returned Don't forward ECS in ALIAS target (A/AAAA RR) resolution and set scope bits to zero in the final response.
- Scope bits from pipe backend in ALIAS Record are returned, but no scope bits (or zero) from ALIAS target (A/AAAA RR) resolution are returned Forward the ECS in the A/AAAA RR query with a new source prefix length based on the scope bits from the ALIAS Record. Then keep the scope bits from pipe backend in the final response, because the A/AAAA RR result is not ECS based (no scope bits from ALIAS target resolution) but the name of the ALIAS target was based on the ECS from the initial DNS query.
- Scope bits from pipe backend in ALIAS Record are returned, but also scope bits from ALIAS target (A/AAAA RR) are returned Not sure... Forward the ECS in the A/AAAA RR query with a new source prefix length based on the scope bits from pipe backend and use the scope bits from the A/AAAA RR resolution in the final response?
Btw, I have a use case for the 2nd scenario :sweat_smile: I determine the ALIAS Target name based on the ECS and want to deliver the scope bits from the pipe backend in the final response. The A/AAAA RR query response from the ALIAS resolution will not return scope bits (or zero).
Has this been implemented yet?
One of our upcoming projects needs subnet processing for ALIAS record expansion. I am looking for guidance on how this might be properly implemented. Here is what the research has uncovered so far:
https://github.com/PowerDNS/pdns/blob/master/pdns/packethandler.cc#L1581
https://github.com/PowerDNS/pdns/blob/master/pdns/tcpreceiver.cc#L759
https://github.com/PowerDNS/pdns/blob/master/pdns/stubresolver.cc#L122
https://github.com/PowerDNS/pdns/blob/master/pdns/dnswriter.hh#L73
https://github.com/PowerDNS/pdns/blob/master/pdns/recursordist/test-ednsoptions_cc.cc#L34
packethandler.cc
appears to be the entrance point for handling a request. The highlighted line appears to be where it retrieves the content of the alias record. I as
tcpreceiver.cc
is where I found the AXFR request handler. The highlighted line appears to try to resolve the ALIAS request into an A/AAAA record.
stubresolver.cc
is the resolver that the TCP Receiver uses. At the highlighted line, it prepares a packet to send to the backend, from what I can tell.
dnswriter.hh
highlights the method you have to use to add an EDNS option (client subnet in our case).
test-ednsoptions_cc.cc
highlights an example of how to add an EDNS Subnet option.
packethandler.cc line 1608 calls completePacket()
https://github.com/PowerDNS/pdns/blob/master/pdns/dnsproxy.cc#L92-L101
Is stubDoResolve
the proper place to implement subnet processing? If not, I would appreciate any help anyone can provide.
I am willing to have this be a paid sponsored feature as long as the changes can be merged upstream for all to use.
I don't think that the code in the AXFR request handler, which handles the expansion of ALIAS records when outgoing-axfr-expand-alias
is enabled, can do anything meaningful with ECS, since the ALIAS records are then expanded on a zone transfer, without any idea of where the actual client will come from.
For the "normal", non-XFR case, I think adding an optional Netmask parameter to stubDoResolve
might be the best way to do what you want. We should be careful to set a correct scope on the returned response then:
- likely a /32 scope if there was no scope in the response we received, which will likely happen quite often since I think most resolvers will not pass the scope along
- otherwise we can likely use the same scope
The non-AXFR case does not currently use stubDoResolve
at all (but it should).
Oh, my bad, I missed the if(r->d_tcp) {
condition at the beginning of that block!
I see this issue and the linked pull request have been assigned to the 4.7.0 milestone. Is there an ETA for said milestone?
Hopefully in a month or so
I saw that 4.7.1 was released, did this change make it into the release?
I think the latest release of the Authoritative server is 4.6.3, PowerDNS Recursor is at 4.7.2.
Fixed in #13441