mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-18 02:48:40 +00:00
util/cloudenv: add support for DigitalOcean
Updates #4984 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: Ib229eb40af36a80e6b0fd1dd0cabb07f0d50a7d1
This commit is contained in:
parent
55b372a79f
commit
c1c50cfcc0
@ -8,6 +8,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -16,6 +17,7 @@ import (
|
||||
"time"
|
||||
|
||||
"tailscale.com/syncs"
|
||||
"tailscale.com/types/lazy"
|
||||
)
|
||||
|
||||
// CommonNonRoutableMetadataIP is the IP address of the metadata server
|
||||
@ -40,9 +42,10 @@ const AzureResolverIP = "168.63.129.16"
|
||||
type Cloud string
|
||||
|
||||
const (
|
||||
AWS = Cloud("aws") // Amazon Web Services (EC2 in particular)
|
||||
Azure = Cloud("azure") // Microsoft Azure
|
||||
GCP = Cloud("gcp") // Google Cloud
|
||||
AWS = Cloud("aws") // Amazon Web Services (EC2 in particular)
|
||||
Azure = Cloud("azure") // Microsoft Azure
|
||||
GCP = Cloud("gcp") // Google Cloud
|
||||
DigitalOcean = Cloud("digitalocean") // DigitalOcean
|
||||
)
|
||||
|
||||
// ResolverIP returns the cloud host's recursive DNS server or the
|
||||
@ -55,10 +58,27 @@ func (c Cloud) ResolverIP() string {
|
||||
return AWSResolverIP
|
||||
case Azure:
|
||||
return AzureResolverIP
|
||||
case DigitalOcean:
|
||||
return getDigitalOceanResolver()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var (
|
||||
// https://docs.digitalocean.com/support/check-your-droplets-network-configuration/
|
||||
digitalOceanResolvers = []string{"67.207.67.2", "67.207.67.3"}
|
||||
digitalOceanResolver lazy.SyncValue[string]
|
||||
)
|
||||
|
||||
func getDigitalOceanResolver() string {
|
||||
// Randomly select one of the available resolvers so we don't overload
|
||||
// one of them by sending all traffic there.
|
||||
return digitalOceanResolver.Get(func() string {
|
||||
rn := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
return digitalOceanResolvers[rn.Intn(len(digitalOceanResolvers))]
|
||||
})
|
||||
}
|
||||
|
||||
// HasInternalTLD reports whether c is a cloud environment
|
||||
// whose ResolverIP serves *.internal records.
|
||||
func (c Cloud) HasInternalTLD() bool {
|
||||
@ -98,6 +118,12 @@ func getCloud() Cloud {
|
||||
return AWS
|
||||
}
|
||||
|
||||
sysVendor := readFileTrimmed("/sys/class/dmi/id/sys_vendor")
|
||||
if sysVendor == "DigitalOcean" {
|
||||
return DigitalOcean
|
||||
}
|
||||
// TODO(andrew): "Vultr" is also valid if we need it
|
||||
|
||||
prod := readFileTrimmed("/sys/class/dmi/id/product_name")
|
||||
if prod == "Google Compute Engine" {
|
||||
return GCP
|
||||
@ -109,6 +135,7 @@ func getCloud() Cloud {
|
||||
// Azure, or maybe all Hyper-V?
|
||||
hitMetadata = true
|
||||
}
|
||||
|
||||
default:
|
||||
// TODO(bradfitz): use Win32_SystemEnclosure from WMI or something on
|
||||
// Windows to see if it's a physical machine and skip the cloud check
|
||||
|
29
util/cloudenv/cloudenv_test.go
Normal file
29
util/cloudenv/cloudenv_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package cloudenv
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"net/netip"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var extNetwork = flag.Bool("use-external-network", false, "use the external network in tests")
|
||||
|
||||
// Informational only since we can run tests in a variety of places.
|
||||
func TestGetCloud(t *testing.T) {
|
||||
if !*extNetwork {
|
||||
t.Skip("skipping test without --use-external-network")
|
||||
}
|
||||
|
||||
cloud := getCloud()
|
||||
t.Logf("Cloud: %q", cloud)
|
||||
t.Logf("Cloud.HasInternalTLD: %v", cloud.HasInternalTLD())
|
||||
t.Logf("Cloud.ResolverIP: %q", cloud.ResolverIP())
|
||||
}
|
||||
|
||||
func TestGetDigitalOceanResolver(t *testing.T) {
|
||||
addr := netip.MustParseAddr(getDigitalOceanResolver())
|
||||
t.Logf("got: %v", addr)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user