pdns icon indicating copy to clipboard operation
pdns copied to clipboard

PowerDNS Auth does not forward EDNS Client Subnet for ALIAS records

Open DarkDeviL opened this issue 7 years ago • 9 comments

  • 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

  1. Install (or compile) PowerDNS
  2. In the configuration, set:
edns-subnet-processing=yes
expand-alias=yes
resolver=8.8.8.8
  1. Create zone "example.com" where you ALIAS "example.com" and/or "www.example.com" to "www.google.com"
  2. 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
  1. 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=".

DarkDeviL avatar Jun 27 '17 06:06 DarkDeviL

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.

Habbie avatar Jun 27 '17 07:06 Habbie

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:

  1. 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.
  2. 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.
  3. 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).

M4t7e avatar Jul 09 '18 16:07 M4t7e

Has this been implemented yet?

Daniel15 avatar Apr 25 '20 13:04 Daniel15

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.

jmazzi avatar Apr 13 '22 15:04 jmazzi

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

rgacogne avatar Apr 14 '22 07:04 rgacogne

The non-AXFR case does not currently use stubDoResolve at all (but it should).

Habbie avatar Apr 14 '22 12:04 Habbie

Oh, my bad, I missed the if(r->d_tcp) { condition at the beginning of that block!

rgacogne avatar Apr 14 '22 12:04 rgacogne

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?

klyoungblood avatar Jul 25 '22 14:07 klyoungblood

Hopefully in a month or so

Habbie avatar Jul 29 '22 09:07 Habbie

I saw that 4.7.1 was released, did this change make it into the release?

jmazzi avatar Sep 06 '22 14:09 jmazzi

I think the latest release of the Authoritative server is 4.6.3, PowerDNS Recursor is at 4.7.2.

omoerbeek avatar Sep 06 '22 14:09 omoerbeek

Fixed in #13441

Habbie avatar Jan 23 '24 14:01 Habbie