diff --git a/docs/_includes/matrix.html b/docs/_includes/matrix.html index 0e21808c1..a2a965dd0 100644 --- a/docs/_includes/matrix.html +++ b/docs/_includes/matrix.html @@ -15,6 +15,7 @@
DESEC
DIGITALOCEAN
DNSIMPLE
+
DNSOVERHTTPS
EXOSCALE
GANDI_V5
GCLOUD
@@ -72,6 +73,9 @@ + + + @@ -153,6 +157,9 @@ + + + @@ -240,6 +247,9 @@ + + + @@ -321,6 +331,7 @@ + @@ -387,6 +398,7 @@ + @@ -439,6 +451,7 @@ + @@ -510,6 +523,7 @@ + @@ -582,6 +596,7 @@ + @@ -632,6 +647,7 @@ + @@ -710,6 +726,7 @@ + @@ -768,6 +785,7 @@ + @@ -826,6 +844,7 @@ + @@ -878,6 +897,7 @@ + @@ -917,6 +937,7 @@ + @@ -955,6 +976,7 @@ + @@ -1003,6 +1025,7 @@ + @@ -1081,6 +1104,9 @@ + + + @@ -1168,6 +1194,9 @@ + + + @@ -1252,6 +1281,7 @@ + diff --git a/docs/_providers/doh.md b/docs/_providers/doh.md new file mode 100644 index 000000000..010f35382 --- /dev/null +++ b/docs/_providers/doh.md @@ -0,0 +1,37 @@ +--- +name: DNS-over-HTTPS +title: DNS-over-HTTPS Provider +layout: default +jsId: DNSOVERHTTPS +--- +# DNS-over-HTTPS Provider + +This is a read-only/monitoring "registrar". It does a DNS NS lookup to confirm the nameserver servers are correct. This "registrar" is unable to update the NS servers but will alert you if they are incorrect. A common use of this provider is when the domain is with a registrar that does not have an API. + +## Configuration +The DNS-over-HTTPS provider does not require anything in `creds.json`. By default, it uses Google Public DNS however you may configure an alternative RFC 8484 DoH provider. + +{% highlight json %} +{ + "DNS-over-HTTPS": { + "host": "cloudflare-dns.com" + } +} +{% endhighlight %} + +Some common DoH providers are `cloudflare-dns.com` [Cloudflare](https://developers.cloudflare.com/1.1.1.1/dns-over-https), `9.9.9.9` [Quad9](https://www.quad9.net/about/), and `dns.google` [Google Public DNS](https://developers.google.com/speed/public-dns/docs/doh) + +## Metadata +This provider does not recognize any special metadata fields unique to Internet.bs. + +## Usage +Example Javascript: + +{% highlight js %} +var REG_MONITOR = NewRegistrar('DNS-over-HTTPS', 'DNSOVERHTTPS'); + +D("example.com", REG_MONITOR, + NNAMESERVER("ns1.example.com."), + NNAMESERVER("ns2.example.com."), +); +{% endhighlight %} diff --git a/go.mod b/go.mod index 339fa3927..267f9b35e 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 github.com/andybalholm/cascadia v1.2.0 // indirect github.com/aws/aws-sdk-go v1.34.13 + github.com/babolivier/go-doh-client v0.0.0-20200723140836-2f86c709ac4a github.com/billputer/go-namecheap v0.0.0-20170915210158-0c7adb0710f8 github.com/cenkalti/backoff v2.1.1+incompatible // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect diff --git a/go.sum b/go.sum index 1f855b4aa..fc338f8d0 100644 --- a/go.sum +++ b/go.sum @@ -80,6 +80,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.34.13 h1:wwNWSUh4FGJxXVOVVNj2lWI8wTe5hK8sGWlK7ziEcgg= github.com/aws/aws-sdk-go v1.34.13/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/babolivier/go-doh-client v0.0.0-20200723140836-2f86c709ac4a h1:ecIUxgsssZnvVeNNsreMlWe6Y7RCfcoayiO7xI0+bC0= +github.com/babolivier/go-doh-client v0.0.0-20200723140836-2f86c709ac4a/go.mod h1:WorCk0sF6w5RjJorPxPL80q35XcMAPew90L8WSZxobY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/billputer/go-namecheap v0.0.0-20170915210158-0c7adb0710f8 h1:sIv3xbwhhAG94a62Q/rrSBtrWcXiYgldNOeqifyKSgo= github.com/billputer/go-namecheap v0.0.0-20170915210158-0c7adb0710f8/go.mod h1:bqqNsI2akL+lLWyApkYY0cxquWPKwEBU0Wd3chi3TEg= diff --git a/providers/_all/all.go b/providers/_all/all.go index e7aa7cde7..8a9800a4a 100644 --- a/providers/_all/all.go +++ b/providers/_all/all.go @@ -12,6 +12,7 @@ import ( _ "github.com/StackExchange/dnscontrol/v3/providers/desec" _ "github.com/StackExchange/dnscontrol/v3/providers/digitalocean" _ "github.com/StackExchange/dnscontrol/v3/providers/dnsimple" + _ "github.com/StackExchange/dnscontrol/v3/providers/doh" _ "github.com/StackExchange/dnscontrol/v3/providers/exoscale" _ "github.com/StackExchange/dnscontrol/v3/providers/gandi_v5" _ "github.com/StackExchange/dnscontrol/v3/providers/gcloud" diff --git a/providers/doh/api.go b/providers/doh/api.go new file mode 100644 index 000000000..98602c7e9 --- /dev/null +++ b/providers/doh/api.go @@ -0,0 +1,36 @@ +package doh + +import ( + "fmt" + "sort" + + "github.com/babolivier/go-doh-client" +) + +type api struct { + host string +} + +func (c *api) getNameservers(domain string) ([]string, error) { + resolver := doh.Resolver{ + Host: c.host, + Class: doh.IN, + } + + // Perform a NS lookup + nss, _, err := resolver.LookupNS(domain) + if err != nil { + return nil, fmt.Errorf("failed fetching nameservers list (DNS-over-HTTPS): %s", err) + } + + ns := []string{} + for _, res := range nss { + ns = append(ns, res.Host) + } + sort.Strings(ns) + return ns, nil +} + +func (c *api) updateNameservers(ns []string, domain string) error { + return fmt.Errorf("DNS-over-HTTPS 'Registrar' is read only, changes must be applied to %s manually", domain) +} diff --git a/providers/doh/dohProvider.go b/providers/doh/dohProvider.go new file mode 100644 index 000000000..357eccf71 --- /dev/null +++ b/providers/doh/dohProvider.go @@ -0,0 +1,61 @@ +package doh + +import ( + "fmt" + "sort" + "strings" + + "github.com/StackExchange/dnscontrol/v3/models" + "github.com/StackExchange/dnscontrol/v3/providers" +) + +/* + +DNS over HTTPS 'Registrar': + +Info required in `creds.json`: + - host DNS over HTTPS host (eg 9.9.9.9) +*/ + +func init() { + providers.RegisterRegistrarType("DNSOVERHTTPS", newDNSOverHTTPS) +} + +func newDNSOverHTTPS(m map[string]string) (providers.Registrar, error) { + api := &api{ + host: m["host"], + } + if api.host == "" { + api.host = "dns.google" + } + return api, nil +} + +// GetRegistrarCorrections gathers corrections that would being n to match dc. +func (c *api) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) { + nss, err := c.getNameservers(dc.Name) + if err != nil { + return nil, err + } + foundNameservers := strings.Join(nss, ",") + + expected := []string{} + for _, ns := range dc.Nameservers { + expected = append(expected, ns.Name) + } + sort.Strings(expected) + expectedNameservers := strings.Join(expected, ",") + + if foundNameservers == expectedNameservers { + return nil, nil + } + + return []*models.Correction{ + { + Msg: fmt.Sprintf("Update nameservers %s -> %s", foundNameservers, expectedNameservers), + F: func() error { + return c.updateNameservers(expected, dc.Name) + }, + }, + }, nil +}