PowerDNS / pdns

PowerDNS Authoritative, PowerDNS Recursor, dnsdist
https://www.powerdns.com/
GNU General Public License v2.0
3.48k stars 888 forks source link

Mixed case propagating to other RRs (causing unstable AXFR output) #4690

Open wdoekes opened 7 years ago

wdoekes commented 7 years ago

Short description

When doing an AXFR (or any other) query, the case of previous results influences the next results.

Using this bind config:

            MX  10 mx1.OSSO.NL.
            MX  20 mx2.osso.nl.

$ORIGIN osso.network.
www         CNAME   Website.Osso.Nl.

I get this AXFR output:

$ dig AXFR osso.network. @127.0.0.1  | grep -E 'MX|CNAME'
osso.network.       259200  IN  MX  10 mx1.OSSO.NL.
osso.network.       259200  IN  MX  20 mx2.OSSO.NL.
www.osso.network.   259200  IN  CNAME   Website.OSSO.NL.

If I just query the CNAME, I get this:

$ dig CNAME www.osso.network. @127.0.0.1  | grep -E 'CNAME'
; <<>> DiG 9.10.3-P4-Ubuntu <<>> CNAME www.osso.network. @127.0.0.1
;www.osso.network.      IN  CNAME
www.osso.network.   259200  IN  CNAME   Website.Osso.Nl.

As you can see, the Website.OSSO.NL. results differs from Website.Osso.Nl..

This example above was fetched with pdns (master branch) and the bind backend (*):

$ pdns_server --version
Nov 16 14:11:19 PowerDNS Authoritative Server 0.0.g16e88d1 (C) 2001-2016 PowerDNS.COM BV

(*) The backend is irrelevant, as this behaviour was first observed with the MySQL backend on pdns 3.4.1 and pdns-4.0.0-alpha2.

Steps to reproduce

  1. compile latest pdns
  2. /usr/local/etc/pdns.conf
    launch = bind
    bind-config=/usr/local/etc/pdns-named.conf
  3. /usr/local/etc/pdns-named.conf
    zone "osso.network" {
    type master;
    file "/usr/local/etc/pdns-zone-osso.network";
    };
  4. /usr/local/etc/pdns-zone-osso.network
    
    $ORIGIN .
    $TTL 259200 ; 3 days
    osso.network    IN SOA  ns1.osso.network. info.osso.nl. (
                2016110801 ; serial
                10800      ; refresh (3 hours)
                3600       ; retry (1 hour)
                604800     ; expire (1 week)
                3600       ; minimum (1 hour)
                )
            NS  ns1.osso.network.
            NS  ns2.osso.network.
            MX  10 mx1.OSSO.NL.
            MX  20 mx2.osso.nl.

$ORIGIN osso.network. www CNAME Website.Osso.Nl.

5. do AXFR, CNAME and MX queries and watch the domains have different case:

$ dig AXFR osso.network @127.0.0.1 | grep -E 'MX|CNAME' $ dig MX osso.network @127.0.0.1 | grep -E 'MX|CNAME' $ dig CNAME www.osso.network @127.0.0.1 | grep -E 'MX|CNAME'


**Depending on which "osso.nl" is first in the config file, the output changes. For the MX records, pdns randomizes them on startup (it appears), so the MX query will get either "osso.nl." or "OSSO.NL." but never both.**

### Expected behaviour
I'd expect the case to be as input (or lowercase, but not randomcase):

$ dig AXFR osso.network @127.0.0.1 | grep -E 'MX|CNAME' osso.network. 259200 IN MX 10 mx1.OSSO.NL. osso.network. 259200 IN MX 20 mx2.osso.nl. www.osso.network. 259200 IN CNAME Website.Osso.Nl.


### Actual behaviour
See above, the case is copied/kept from previous records.

Interestingly, this appears to be some kind of DNS protocol feature:

14:52:27.866863 IP (tos 0x0, ttl 64, id 4724, offset 0, flags [DF], proto TCP (6), length 204) 127.0.0.1.53 > 127.0.0.1.56972: Flags [P.], cksum 0xfec0 (incorrect -> 0x258d), seq 96:248, ack 44, win 342, options [nop,nop,TS val 432438810 ecr 432438810], length 15262130*- 5/0/1 osso.network. NS ns1.osso.network., osso.network. NS ns2.osso.network., osso.network. MX mx1.OSSO.NL. 10, osso.network. MX mx2.OSSO.NL. 20, www.osso.network. CNAME Website.OSSO.NL. (150) 0x0000: 4500 00cc 1274 4000 4006 29b6 7f00 0001 E....t@.@.)..... 0x0010: 7f00 0001 0035 de8c 5486 6cc7 2c3a 18e2 .....5..T.l.,:.. 0x0020: 8018 0156 fec0 0000 0101 080a 19c6 7e1a ...V..........~. 0x0030: 19c6 7e1a 0096 f2b2 8400 0001 0005 0000 ..~............. 0x0040: 0001 046f 7373 6f07 6e65 7477 6f72 6b00 ...osso.network. 0x0050: 00fc 0001 c00c 0002 0001 0003 f480 0006 ................ 0x0060: 036e 7331 c00c c00c 0002 0001 0003 f480 .ns1............ 0x0070: 0006 036e 7332 c00c c00c 000f 0001 0003 ...ns2.......... 0x0080: f480 000f 000a 036d 7831 044f 5353 4f02 .......mx1.OSSO. 0x0090: 4e4c 00c0 0c00 0f00 0100 03f4 8000 0800 NL.............. 0x00a0: 1403 6d78 32c0 5403 7777 77c0 0c00 0500 ..mx2.T.www..... 0x00b0: 0100 03f4 8000 0a07 5765 6273 6974 65c0 ........Website. 0x00c0: 5400 0029 0690 0000 0000 0000 T..)........


As the tcpdump output shows, only "OSSO.NL" is passed once, saving (valuable?) bytes.

That would lead me to believe that this is not a bug but a "feature". But I'd rather have send more consistent bytes than fewer bytes that randomly change.

### Usecase
I was creating AXFR dumps to do history keeping of our DNS records, but the records "randomly" changed. The mysql backend doesn't order the records, so sometimes "Osso.Nl" shows up first, and other times one of the other ones does.

Even though I sorted the AXFR dumps manually (see feature request #2694), the sorted AXFR records kept updating even though nothing of relevance had changed.

In our case, some people had set MX records to `ALT1.ASPMX.L.GOOGLE.COM.` but also CNAMEs of subdomains to `ghs.google.com.`. The MX records would randomly turn into to `ALT1.ASPMX.L.google.com` and the CNAMEs into `ghs.GOOGLE.COM`.

The fix here was to lowercase all content fields of our records, but it was not at all apparent why this was needed.
sndrsmnk commented 7 years ago

I've seen the same with a setup that has @ IN MX 10 ASPMX1.GOOGLEMAIL.COM causing the later _dmarc IN CNAME lowercase.example.com to appear as _dmarc IN CNAME lowercase.example.COM in the AXFR'ed results.

Note that repeatedly AXFR'ing gives varying results. Probably due to the order in which records are processed?

(#dns.nl, 24 jan 2017)

Habbie commented 6 years ago

For your history keeping, ldns-read-zone -z might be useful.

stbuehler commented 6 years ago

AFAICT, the observed behavior is allowed and expected according to RFC 4343 section 4.1: compression should use case insensitive comparison to find common suffixes.

And RFC 1035 section 2.3.3 already said:

Systems administrators who enter data into the domain database should take care to represent the data they supply to the domain system in a case-consistent manner if their system is case-sensitive. The data distribution system in the domain system will ensure that consistent representations are preserved.

In short: if your monitoring (or any other use case) is case-sensitive, supply the data in a case-consistent manner.

Habbie commented 6 years ago

The behavior definitely is correct. I consider this a feature request for stability between runs, nothing more.

Habbie commented 3 years ago

For auth 5.0, I think we should lowercase all the things all the time. It's simpler all around and also avoids the problem in this ticket.