mjl- / mox

modern full-featured open source secure mail server for low-maintenance self-hosted email
https://www.xmox.nl
MIT License
3.7k stars 111 forks source link

Mox incorrectly warns that DNS resolvers do not verify DNSSEC #139

Closed triatic closed 8 months ago

triatic commented 8 months ago

Mox is telling me my DNS resolvers do not verify DNSSEC, but this is not the case.

./mox quickstart triatic@example.com
Checking if DNS resolvers are DNSSEC-verifying...

WARNING: It looks like the DNS resolvers configured on your system do not
verify DNSSEC, or aren't trusted (by having loopback IPs or through "options
trust-ad" in /etc/resolv.conf).  Without DNSSEC, outbound delivery with SMTP
used unprotected MX records, and SMTP STARTTLS connections cannot verify the TLS
certificate with DANE (based on a public key in DNS), and will fallback to
either MTA-STS for verification, or use "opportunistic TLS" with no certificate
verification.
mox@mail:~$ delv xmox.nl
; fully validated
xmox.nl.                3597    IN      A       84.22.96.237
xmox.nl.                3597    IN      RRSIG   A 13 2 3600 20240317072505 20240303062638 58294 xmox.nl. 7ikPcMtTgbFgu+3CFT1v0PUOsTlkvrI5DEMx/lAs2PGa4kb99mBvLmBF 1JEY/L7rw14kWXYMgk6g8jRhnSjqyA==
mox@mail:~$ grep -v '^#' /etc/resolv.conf

nameserver 169.254.169.254
search vcn04249209.oraclevcn.com
options edns0 trust-ad
mjl- commented 8 months ago

Hi triatic, thanks for raising this issue.

I don't think delv is a representative check: Delv does its own DNSSEC validation. This is from its manual page:

       delv sends to a specified name server all queries needed to fetch and validate the requested data; this includes the original requested query, subsequent queries to follow CNAME or DNAME chains, queries for DNSKEY, and DS records to establish a chain of trust
       for DNSSEC validation. It does not perform iterative resolution, but simulates the behavior of a name server configured for DNSSEC validating and forwarding.

Could you check a command like this, and make sure the "ad" (authentic data) flag is present in the response? If it is not present, then the recursive resolver did not validate DNSSEC.

$ dig xmox.nl

; <<>> DiG 9.19.21-1-Debian <<>> xmox.nl
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9043
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;xmox.nl.                       IN      A

;; ANSWER SECTION:
xmox.nl.                3462    IN      A       84.22.96.237

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Wed Mar 06 12:37:45 CET 2024
;; MSG SIZE  rcvd: 52

Also see issue #131 for similar debugging.

triatic commented 8 months ago

Thanks for your reply, I didn't know that about delv.

dig is reporting the ad flag.

mox@mail:~$ dig xmox.nl

; <<>> DiG 9.18.18-0ubuntu2.1-Ubuntu <<>> xmox.nl
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50599
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1372
;; QUESTION SECTION:
;xmox.nl.                       IN      A

;; ANSWER SECTION:
xmox.nl.                3600    IN      A       84.22.96.237

;; Query time: 24 msec
;; SERVER: 169.254.169.254#53(169.254.169.254) (UDP)
;; WHEN: Wed Mar 06 11:54:34 UTC 2024
;; MSG SIZE  rcvd: 52
triatic commented 8 months ago

So in the other issue it related to the root trust anchor file, but I am using Oracle Cloud's default DNS resolver.

Am I able to verify its root trust anchor manually?

mjl- commented 8 months ago

Ah interesting. The root trust anchor issue with unbound was the reason that other issue didn't return the "ad" flag. But you are getting the "ad" response, so it is something different.

Could you try separate dns lookups with the "mox dns lookup" subcommand? It will use the same configuration as mox uses during quickstart and later operation:

$ ./mox -loglevel debug dns lookup a xmox.nl
debug: dns lookup result; pkg=dns; type=ip; network=ip4; host=xmox.nl.; resp=[84.22.96.237]; authentic=true; duration="601.836µs"
records (1, with dnssec):
- 84.22.96.237

If that does not have dnssec, and authentic=false, we'll have to dig deeper.

triatic commented 8 months ago
mox@mail:~$ ./mox -loglevel debug dns lookup a xmox.nl
debug: dns lookup result; pkg=dns; type=ip; network=ip4; host=xmox.nl.; resp=[84.22.96.237]; authentic=true; duration=1.80443ms
records (1, with dnssec):
- 84.22.96.237
mjl- commented 8 months ago

It's getting interesting. (:

Can you try looking up NS for the root label (.)? That's what quickstart does for its check for DNSSEC, https://github.com/mjl-/mox/blob/v0.0.9/quickstart.go#L166:

$ ./mox -loglevel debug dns lookup ns .
debug: dns lookup result; pkg=dns; type=ns; name=.; resp="[host=f.root-servers.net.;host=g.root-servers.net.;host=h.root-servers.net.;host=i.root-servers.net.;host=j.root-servers.net.;host=k.root-servers.net.;host=l.root-servers.net.;host=m.root-servers.net.;host=a.root-servers.net.;host=b.root-servers.net.;host=c.root-servers.net.;host=d.root-servers.net.;host=e.root-servers.net.]"; authentic=true; duration="577.44µs"
ns records (13, with dnssec):
- &{f.root-servers.net.}
- &{g.root-servers.net.}
- &{h.root-servers.net.}
- &{i.root-servers.net.}
- &{j.root-servers.net.}
- &{k.root-servers.net.}
- &{l.root-servers.net.}
- &{m.root-servers.net.}
- &{a.root-servers.net.}
- &{b.root-servers.net.}
- &{c.root-servers.net.}
- &{d.root-servers.net.}
- &{e.root-servers.net.}

The idea is that trust has to start at the top, so it makes sense to query the root, but I it may be a special case for some dns resolvers. I didn't want to query any specific other domain, though perhaps just requesting .com will be fine too (if ns on dot doesn't return authentic data, could you check if looking up ns on .com does? or see if there is a pattern).

triatic commented 8 months ago

It's getting interesting. (:

I thought I was the only one that finds DNS interesting! :)

The idea is that trust has to start at the top, so it makes sense to query the root, but I it may be a special case for some dns resolvers. I didn't want to query any specific other domain, though perhaps just requesting .com will be fine too (if ns on dot doesn't return authentic data, could you check if looking up ns on .com does? or see if there is a pattern).

Yes, you nailed it.

mox@mail:~$ ./mox -loglevel debug dns lookup ns .
debug: dns lookup result; pkg=dns; type=ns; name=.; resp="[host=h.root-servers.net.;host=i.root-servers.net.;host=j.root-servers.net.;host=k.root-servers.net.;host=l.root-servers.net.;host=m.root-servers.net.;host=a.root-servers.net.;host=b.root-servers.net.;host=c.root-servers.net.;host=d.root-servers.net.;host=e.root-servers.net.;host=f.root-servers.net.;host=g.root-servers.net.]"; authentic=false; duration=1.437821ms
ns records (13, without dnssec):
- &{h.root-servers.net.}
- &{i.root-servers.net.}
- &{j.root-servers.net.}
- &{k.root-servers.net.}
- &{l.root-servers.net.}
- &{m.root-servers.net.}
- &{a.root-servers.net.}
- &{b.root-servers.net.}
- &{c.root-servers.net.}
- &{d.root-servers.net.}
- &{e.root-servers.net.}
- &{f.root-servers.net.}
mox@mail:~$ ./mox -loglevel debug dns lookup ns com.
debug: dns lookup result; pkg=dns; type=ns; name=com.; resp="[host=e.gtld-servers.net.;host=g.gtld-servers.net.;host=c.gtld-servers.net.;host=d.gtld-servers.net.;host=l.gtld-servers.net.;host=b.gtld-servers.net.;host=j.gtld-servers.net.;host=h.gtld-servers.net.;host=i.gtld-servers.net.;host=a.gtld-servers.net.;host=k.gtld-servers.net.;host=f.gtld-servers.net.;host=m.gtld-servers.net.]"; authentic=true; duration=1.100834ms
ns records (13, with dnssec):
- &{e.gtld-servers.net.}
- &{g.gtld-servers.net.}
- &{c.gtld-servers.net.}
- &{d.gtld-servers.net.}
- &{l.gtld-servers.net.}
- &{b.gtld-servers.net.}
- &{j.gtld-servers.net.}
- &{h.gtld-servers.net.}
- &{i.gtld-servers.net.}
- &{a.gtld-servers.net.}
- &{k.gtld-servers.net.}
- &{f.gtld-servers.net.}
- &{m.gtld-servers.net.}
mjl- commented 8 months ago

nice, thanks! will change to looking up .com in the quickstart. i have another commit pending, hopefully later today.

triatic commented 8 months ago

Cheers! And thanks for Mox, I found out about it in my quest for an MTA with native MTA-STS support. Looking forward to trying it out.

mjl- commented 8 months ago

The referenced commit should fix this issue. If you want, you could test with that commit, but I would recommend the latest, a9f11b8fa383bdcbda165143e8db43e44a19eb8e: Run GOBIN=$PWD CGO_ENABLED=0 go install github.com/mjl-/mox@v0.0.10-0.20240307102653-a9f11b8fa383, or download a binary, eg https://beta.gobuilds.org/github.com/mjl-/mox@v0.0.10-0.20240307102653-a9f11b8fa383/linux-amd64-go1.22.1/04xZjo2lllGU9twi7Exfm0lTF0B8/.

For fun, once you have it up and running, you may like to try https://www.email-security-scans.org. It checks various tls/mta-sts/dane behaviours when sending email (the "receiving" part of dane/mta-sts is usually easier to set up/do).

Thanks again, and let me know if you run into anything else!

triatic commented 8 months ago

No problem, glad I could help. :)