diff --git a/consul/util.go b/consul/util.go index de94efb632..b1ca085c63 100644 --- a/consul/util.go +++ b/consul/util.go @@ -1,13 +1,45 @@ package consul import ( + "fmt" "github.com/hashicorp/serf/serf" + "net" "os" "path/filepath" "strconv" "strings" ) +/* + * Contains an entry for each private block: + * 10.0.0.0/8 + * 172.16.0.0/12 + * 192.168/16 + */ +var privateBlocks []*net.IPNet + +func init() { + // Add each private block + privateBlocks = make([]*net.IPNet, 3) + _, block, err := net.ParseCIDR("10.0.0.0/8") + if err != nil { + panic(fmt.Sprintf("Bad cidr. Got %v", err)) + } + privateBlocks[0] = block + + _, block, err = net.ParseCIDR("172.16.0.0/12") + if err != nil { + panic(fmt.Sprintf("Bad cidr. Got %v", err)) + } + privateBlocks[1] = block + + _, block, err = net.ParseCIDR("192.168.0.0/16") + if err != nil { + panic(fmt.Sprintf("Bad cidr. Got %v", err)) + } + privateBlocks[2] = block +} + // strContains checks if a list contains a string func strContains(l []string, s string) bool { for _, v := range l { @@ -44,3 +76,39 @@ func isConsulServer(m serf.Member) (bool, string, int) { return true, datacenter, port } + +// Returns if the given IP is in a private block +func isPrivateIP(ip_str string) bool { + ip := net.ParseIP(ip_str) + for _, priv := range privateBlocks { + if priv.Contains(ip) { + return true + } + } + return false +} + +// GetPrivateIP is used to return the first private IP address +// associated with an interface on the machine +func GetPrivateIP() (*net.IPNet, error) { + addresses, err := net.InterfaceAddrs() + if err != nil { + return nil, fmt.Errorf("Failed to get interface addresses: %v", err) + } + + // Find private IPv4 address + for _, addr := range addresses { + ip, ok := addr.(*net.IPNet) + if !ok { + continue + } + if ip.IP.To4() == nil { + continue + } + if !isPrivateIP(ip.IP.String()) { + continue + } + return ip, nil + } + return nil, fmt.Errorf("No private IP address found") +} diff --git a/consul/util_test.go b/consul/util_test.go index 2511ef2116..7a04c57bf5 100644 --- a/consul/util_test.go +++ b/consul/util_test.go @@ -13,3 +13,21 @@ func TestStrContains(t *testing.T) { t.Fatalf("should not contain") } } + +func TestIsPrivateIP(t *testing.T) { + if !isPrivateIP("192.168.1.1") { + t.Fatalf("bad") + } + if !isPrivateIP("172.16.45.100") { + t.Fatalf("bad") + } + if !isPrivateIP("10.1.2.3") { + t.Fatalf("bad") + } + if isPrivateIP("8.8.8.8") { + t.Fatalf("bad") + } + if isPrivateIP("127.0.0.1") { + t.Fatalf("bad") + } +}