util/cloudenv: detect Hetzner Cloud
Detect Hetzner via /sys/class/dmi/id/sys_vendor == "Hetzner" and wire up Hetzner's public recursive DNS resolvers (185.12.64.1, 185.12.64.2) for use as a cloud host resolver. Fixes #20217 Change-Id: I24a4c51956adfdd5731f62c937e3c7a4a733ffc7 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
1d69894084
commit
d22bf51e57
@@ -47,6 +47,7 @@ const (
|
|||||||
Azure = Cloud("azure") // Microsoft Azure
|
Azure = Cloud("azure") // Microsoft Azure
|
||||||
GCP = Cloud("gcp") // Google Cloud
|
GCP = Cloud("gcp") // Google Cloud
|
||||||
DigitalOcean = Cloud("digitalocean") // DigitalOcean
|
DigitalOcean = Cloud("digitalocean") // DigitalOcean
|
||||||
|
Hetzner = Cloud("hetzner") // Hetzner Cloud
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResolverIP returns the cloud host's recursive DNS server or the
|
// ResolverIP returns the cloud host's recursive DNS server or the
|
||||||
@@ -64,6 +65,8 @@ func (c Cloud) ResolverIP() string {
|
|||||||
return AzureResolverIP
|
return AzureResolverIP
|
||||||
case DigitalOcean:
|
case DigitalOcean:
|
||||||
return getDigitalOceanResolver()
|
return getDigitalOceanResolver()
|
||||||
|
case Hetzner:
|
||||||
|
return getHetznerResolver()
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -82,6 +85,21 @@ func getDigitalOceanResolver() string {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// https://docs.hetzner.com/robot/dedicated-server/general-information/recursive-name-servers/
|
||||||
|
// IPv6 resolvers also exist: 2a01:4ff:ff00::add:1, 2a01:4ff:ff00::add:2.
|
||||||
|
hetznerResolvers = []string{"185.12.64.1", "185.12.64.2"}
|
||||||
|
hetznerResolver lazy.SyncValue[string]
|
||||||
|
)
|
||||||
|
|
||||||
|
func getHetznerResolver() string {
|
||||||
|
// Randomly select one of the available resolvers so we don't overload
|
||||||
|
// one of them by sending all traffic there.
|
||||||
|
return hetznerResolver.Get(func() string {
|
||||||
|
return hetznerResolvers[rand.IntN(len(hetznerResolvers))]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// HasInternalTLD reports whether c is a cloud environment
|
// HasInternalTLD reports whether c is a cloud environment
|
||||||
// whose ResolverIP serves *.internal records.
|
// whose ResolverIP serves *.internal records.
|
||||||
func (c Cloud) HasInternalTLD() bool {
|
func (c Cloud) HasInternalTLD() bool {
|
||||||
@@ -128,6 +146,9 @@ func getCloud() Cloud {
|
|||||||
if sysVendor == "DigitalOcean" {
|
if sysVendor == "DigitalOcean" {
|
||||||
return DigitalOcean
|
return DigitalOcean
|
||||||
}
|
}
|
||||||
|
if sysVendor == "Hetzner" {
|
||||||
|
return Hetzner
|
||||||
|
}
|
||||||
// TODO(andrew): "Vultr" is also valid if we need it
|
// TODO(andrew): "Vultr" is also valid if we need it
|
||||||
|
|
||||||
prod := readFileTrimmed("/sys/class/dmi/id/product_name")
|
prod := readFileTrimmed("/sys/class/dmi/id/product_name")
|
||||||
|
|||||||
Reference in New Issue
Block a user