-
Notifications
You must be signed in to change notification settings - Fork 155
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix custom resolver implementation for Windows (#255)
Pebble accepts a `--dnsserver` flag, that allows to select a custom DNS resolver to use when validating the ACME challenges. This option is critical to make the certbot integration tests work in particular. Current implementation is to set the `net.DefaultResolver` on a new `net.Resolver` instance with a custom `Dial` property to consume the value from `--dnsserver`. This allows to transparently resolve any host using this custom DNS resolver from a pure-Go implementation of the DNS resolution API. Sadly this approach does not work on Windows, and the `--dnsserver` has no effect on how resolution is done, and it is always the OS mechanism that is used. One can reveal this behavior by running the following piece of code on Linux and on Windows: ```go // test.go package main import ( "context" "fmt" "net" ) func main() { resolver := &net.Resolver{ PreferGo: true, Dial: func(ctx context.Context, _, _ string) (net.Conn, error) { d := net.Dialer{} return d.DialContext(ctx, "udp", "4.3.2.1:404") }, } net.DefaultResolver = resolver ctx, cancelfunc := context.WithTimeout(context.Background(), 30) defer cancelfunc() _, err := resolver.LookupTXT(ctx, "stupid.entry.net") fmt.Printf("Error is: %s\n", err) } ``` This piece of code tries to resolve a non-existent domain on a non-existent DNS server as IP `4.3.2.1:404`. On Linux, you will get the following error: ```bash Error is: lookup stupid.entry.net on 127.0.0.53:53: dial udp 4.3.2.1:404: i/o timeout ``` That indicates that the system tried to reach the non-existent DNS server, and get back a timeout exception on it. However on Windows you will get: ```bash Error is: lookup stupid.entry.net: dnsquery: DNS name does not exist. ``` This indicates that the system ignored the dummy DNS server address, contacted the OS DNS resolver, that responded that the DNS name does not exist. One can see also the reason for this behavior on Windows on the `net` godoc, https://godoc.org/net, in particular this line in the module introduction: ``` On Windows, the resolver always uses C library functions, such as GetAddrInfo and DnsQuery. ``` In fact, the pure Go DNS resolver is not applicable on Windows, the OS DNS resolver will be used, ignoring any customization. Several relevant discussions, in particular a proposal (not developed yet) to make the pure Go DNS resolver available on Windows: * golang/go#29621 * golang/go#33097 * golang/go#33086 To fix this, this PR makes Pebble switch to a different logic: * if `-dnsserver` is not set, use the default API to resolve the names * if `-dnsserver` is set, use a dedicated DNS client, to avoid to use the OS one both on Linux and Windows The DNS client is https://github.com/miekg/dns, a highly used and supported DNS library. With these modifications, integrations tests on Certbot are running correctly both on Linux and Windows.
- Loading branch information
Showing
3 changed files
with
130 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters