internetstandards / Internet.nl

Internet standards compliance test suite
https://internet.nl
171 stars 35 forks source link

Issue DNSSEC and Google Public DNS #1484

Open yanainic opened 4 weeks ago

yanainic commented 4 weeks ago

Hi guys,

While we were doing somes "Connection test" here, we faced a peculiar situation where no name is showed in "tech details":

image

(source: https://internet.nl/connection/0230c3ab26de41b3a9d8ffc084f5554f/results )

This issue happens when the user enables the Secure DNS option in the Chrome browser and selects Google Public DNS.

image

The site internet.nl indicates that the DNS is secure but doesn't show the resolver name, this happens both in https://internet.nl and https://test.nic.br (Brazilian version), we tested on following browsers:

Ubuntu 22.04 Chrome Version 127.0.6533.72 Mac Os Chrome Versão 127.0.6533.100 (Versão oficial) (arm64) Windows 10 Chrome Version 127.0.6533.19

Debugging with tcpdump, we noticed that NO QUERIES are being made about the resolver to Team Cymru via the DNS protocol on port 53 when the Google Public DNS. However when we use another DNS (200.160.5.13) using the port 53 like the example below made in our test.nic.br (BR Version) we have answers from Team Cymru ....

11:03:04.094950 IP 200.160.7.231.11981 > 216.31.12.17.53: 50062% [1au] TXT? AS22548.asn.cymru.com. (50) 11:03:04.163024 IP 216.31.12.15.53 > 200.160.7.231.19235: 36822*- 1/3/2 TXT "22548 | BR | lacnic | 2001-10-16 | Nucleo de Inf. e Coord. do Ponto BR - NIC., BR" (219)

Is it an issue with Google or due to the query being made via HTTPS? Any ideas?

baknu commented 3 weeks ago

Thanks for your feedback!

Do you see this behaviour only with Google Public DNS or also with other DNS providers (like Quad9, DNS0.EU or Cloudflare) that support DNS-over-HTTPS (DoH)?

Still I believe this can't be DoH, because AFAIK DoH is only used between the client (browser) and the resolver (Google Public DNS) and not between the resolver and the authoritative nameserver (in this case the internet.nl nameservers).

And even if DoH (or DNS-over-TLS; DoT) was used for the latter, Internet.nl would still be able to see the IP of the resolver (given that we support DoH or DoT on our authoritative DNS which I don't believe is the case).

So for some reason, it seems something goes wrong on our side in the following functionality with the Chrome setting you mentioned:

@mxsasha Can you look into this further? Thanks.

yanainic commented 3 weeks ago

Hi Baknu ! Thanks for your answer !

This happens only on Chrome Browser in the option showed it before (Google Public DNS), when I choose a different DNSSEC on Chrome Cloudfare for example:

image

The behavior is what was expected:

image

(Expected behavior)

When I leave the option in Chrome for the choice to be handled by MacOS and it has 'iCloud Private Relay' enabled" the MacOS chooses a DNS Non SEC for me from one of their partners (Akamai,Cloudfare,etc.) but not necessarily is a DNSSEC IP ... perhaps if someone in this git is reading this and works at Apple and could report it to the team in charge ... I appreciate it !

(iCloud Private Relay)

image

(Chrome SO Standard option)

image

(https://support.apple.com/guide/mac-help/use-icloud-private-relay-mchlecadabe0/mac)

About the item that you recommend about the test-query-handling as soon as possible I will ask to our team check it !

Thanks in advance Flavio

mxsasha commented 3 weeks ago

I took out tcpdump, and the reason is that google's resolver, for some reason, intentionally seems to mix the case of the hostnames, e.g. 31b20C3fE0fA42889F52161FB77b1eE0.A.Conn.teSt-Ns-signEd.DeV-DOCkEr.InTeRNEt.NL. That is the most likely cause.

Perhaps the test in https://github.com/internetstandards/unbound/blob/b78aef78049721196f46e6c34ff63c15d436338c/internetnl/internetnl.c#L428-L435 is case sensitive. I can't easily read this code well enough to be sure.

baknu commented 3 weeks ago

@mxsasha Thanks for checking.

I took out tcpdump, and the reason is that google's resolver, for some reason, intentionally seems to mix the case of the hostnames, e.g. 31b20C3fE0fA42889F52161FB77b1eE0.A.Conn.teSt-Ns-signEd.DeV-DOCkEr.InTeRNEt.NL. That is the most likely cause.

Good find. This seems to be the background: https://www.theregister.com/2023/01/19/google_dns_queries/

Perhaps the test in https://github.com/internetstandards/unbound/blob/b78aef78049721196f46e6c34ff63c15d436338c/internetnl/internetnl.c#L428-L435 is case sensitive. I can't easily read this code well enough to be sure.

@gthess Could you have a look and perhaps fix this? Thanks.

bwbroersma commented 3 weeks ago

Official Google Announcement of the case randomization of DNS query names: https://groups.google.com/g/public-dns-discuss/c/KxIDPOydA5M I indeed saw the same using 8.8.8.8 (not specific for DOH).

Some old note about reproducing it by using curl and the Google DNS servers:

DNS='--dns-servers';SERVER='8.8.8.8';
# DNS='--doh-url';SERVER='https://dns.google/dns-query';
# DNS='--doh-url';SERVER='https://cloudflare-dns.com/dns-query';
TEST_ID=$(curl -sSfA '' 'http://conn.internet.nl/connection/gettestid/' | jq .test_id -r);
curl $DNS $SERVER -sSA '' \
    "http://$TEST_ID.{bogus,aaaa,a}.conn.test-ns-signed.internet.nl/?callback=jQuery1_2" \
    "http://$TEST_ID.a-aaaa.conn.test-ns6-signed.internet.nl/?callback=jQuery1_2" \
    "http://[2a00:d00:ff:162:62:204:66:10]/connection/addr-test/$TEST_ID/?callback=jQuery1_2" \
    "http://conn.internet.nl/connection/finished/$TEST_ID" -w '\n' \
| sed -r 's/jQuery1_2\((.*)\)/\1/g' \
| jq;
echo "https://internet.nl/connection/$TEST_ID/results";
{
...
  "connresolver": {
    "done": true,
    "name": "connresolver",
    "title": "test connresolver title",
    "details_set": [
      [
        "",
        "",
        {
          "validation": {
            "label": "detail conn dnssec validation label",
            "status": 1,
            "verdict": "detail conn dnssec validation verdict good",
            "exp": "detail conn dnssec validation exp",
            "tech_type": "table",
            "tech_string": "detail conn dnssec validation tech table",
            "tech_data": [
              []
            ]
          }
        }
      ]
    ],
    "totalscore": 100,
    "maxscore": 100,
    "verdict": "passed",
    "icon": "passed",
    "summary": "Domain signatures validated (DNSSEC)",
    "description": "Well done! Domain signatures (<a href=\"/faqs/dnssec/\">DNSSEC</a>) are validated for you. Therefore you are \nprotected against false translation from signed domain names into rogue IP \naddresses."
  }
}
gthess commented 1 week ago

Perhaps the test in https://github.com/internetstandards/unbound/blob/b78aef78049721196f46e6c34ff63c15d436338c/internetnl/internetnl.c#L428-L435 is case sensitive. I can't easily read this code well enough to be sure.

@gthess Could you have a look and perhaps fix this? Thanks.

The checks there are case insensitive (they explicitly compare lower case). But maybe Unbound writes the received case as is in redis and then the python side looks up the value with case sensitivity (which is different than the one stored). If that is the case I can patch Unbound to always store with a preferred case. But I don't have time to look further into what is actually happening :)