JohnStarich / go

This is a collection of my Go modules in one easy-to-import place
Apache License 2.0
54 stars 13 forks source link

Does the DNS package support domain scoped resolvers? #20

Closed tristanmorgan closed 1 year ago

tristanmorgan commented 2 years ago

In the macOS resolver configuration you can specify a domain scoped resolver by creating a file in the /etc/resolver directory. it allows you to resolve domains not available publicly.

See man 5 resolver and scutil.

$ cat /etc/resolver/dc1.consul 
nameserver 10.10.10.115
port 8600
timeout 5

$ ./dns-test minio.service.dc1.consul
Looking up minio.service.dc1.consul
{"level":"info","msg":"Reading macOS DNS config from 'scutil'..."}
{"level":"info","msg":"Finished reading macOS DNS config from 'scutil'"}
{"level":"debug","msg":"Dialing all nameservers"}
{"level":"debug","msg":"Dialing all nameservers"}
{"level":"debug","msg":"Dialing all nameservers"}
{"level":"debug","msg":"Dialing all nameservers"}
panic: lookup minio.service.dc1.consul on 127.0.0.1:53: no such host

goroutine 1 [running]:
main.main()
    github.com/johnstarich/go/dns/internal/cmd/dns-test/main.go:26 +0x1d8

$ curl -vvI http://minio.service.dc1.consul:8500
*   Trying 10.10.10.115:8500...
* Connected to minio.service.dc1.consul (10.10.10.115) port 8500 (#0)
> HEAD / HTTP/1.1
> Host: minio.service.dc1.consul:8500
> User-Agent: curl/7.79.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
HTTP/1.1 301 Moved Permanently
< Content-Type: text/html; charset=utf-8
Content-Type: text/html; charset=utf-8
< Location: /ui/
Location: /ui/
< Date: Fri, 10 Jun 2022 00:08:56 GMT
Date: Fri, 10 Jun 2022 00:08:56 GMT

< 
* Connection #0 to host minio.service.dc1.consul left intact
JohnStarich commented 2 years ago

Hey @tristanmorgan šŸ‘‹ Thanks for opening

Right now, dns reads all nameservers from the output of scutil --dns and attempts to use all of them. It should return the first successful result or continue iterating through the remainder.

That's odd though. It looks like your test shows curl successfully resolved the address, while dns did not. Would you mind sharing your scutil --dns output and your resolver configuration? (If it's private info, a minimal reproducible example would be helpful!)

tristanmorgan commented 2 years ago

There's a little extra in here but the output is as follows, I'm expecting resolver No. 9 to be what responds.

$ scutil --dns
DNS configuration

resolver #1
  nameserver[0] : 127.0.0.1
  flags    : Request A records, Request AAAA records
  reach    : 0x00030002 (Reachable,Local Address,Directly Reachable Address)

resolver #2
  domain   : local
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 300000

resolver #3
  domain   : 254.169.in-addr.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 300200

resolver #4
  domain   : 8.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 300400

resolver #5
  domain   : 9.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 300600

resolver #6
  domain   : a.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 300800

resolver #7
  domain   : b.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00000000 (Not Reachable)
  order    : 301000

resolver #8
  domain   : 168.192.in-addr.arpa
  nameserver[0] : 127.0.0.1
  port     : 8600
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00030002 (Reachable,Local Address,Directly Reachable Address)

resolver #9
  domain   : dc1.consul
  nameserver[0] : 10.10.10.115
  port     : 8600
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00020002 (Reachable,Directly Reachable Address)

resolver #10
  domain   : 10.in-addr.arpa
  nameserver[0] : 10.10.10.115
  port     : 8600
  timeout  : 5
  flags    : Request A records, Request AAAA records
  reach    : 0x00020002 (Reachable,Directly Reachable Address)

DNS configuration (for scoped queries)

resolver #1
  nameserver[0] : 127.0.0.1
  if_index : 11 (en0)
  flags    : Scoped, Request A records, Request AAAA records
  reach    : 0x00000002 (Reachable)

P.S. 127.0.0.1:53 is a DoH resolver for general web.

tristanmorgan commented 2 years ago

@JohnStarich I think the difference is the system library looks for the longest domain suffix match first then makes the requests from that pool. This is also useful for creating a file in /etc/reolver to blackhole a domain....

JohnStarich commented 2 years ago

I think you're right, I've come to the same conclusion while looking through. I think dns can be updated to handle the domain in longest matching suffix order, followed by the non-domain-specific resolvers. You may need to tune your delay between resolvers though, to be certain the first match has time to complete.

Also, there's a weird part in the .in-addr.arpa style IP suffixes, which may require special handling.

You're welcome to open a PR to prioritize domain-specific resolvers šŸ‘ (If not, I may have time to look at this soon.)

JohnStarich commented 1 year ago

Looks like Go 1.20 will get a new libc based DNS resolver for macOS šŸŽ‰

https://github.com/golang/go/issues/12524#issuecomment-1302466054 https://github.com/golang/go/commit/a3559f3301b54468c14d4997af0d617db60f4915

That should fix any DNS inconsistencies completely šŸ™

tristanmorgan commented 1 year ago

Agreed, the usage of libc calls to allow cross compiling without CGO is the best resolution for this issue.