Skip to content

Instantly share code, notes, and snippets.

@grantpullen
Forked from andres-erbsen/addr.go
Created August 8, 2018 06:59
Show Gist options
  • Save grantpullen/4659ef9afd537d3c167db80ea0856bbc to your computer and use it in GitHub Desktop.
Save grantpullen/4659ef9afd537d3c167db80ea0856bbc to your computer and use it in GitHub Desktop.
Get public IP address in Go #golang
package main
import (
"net"
"sort"
"strconv"
"strings"
)
func rfc1918private(ip net.IP) bool {
for _, cidr := range []string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"} {
_, subnet, err := net.ParseCIDR(cidr)
if err != nil {
panic("failed to parse hardcoded rfc1918 cidr: " + err.Error())
}
if subnet.Contains(ip) {
return true
}
}
return false
}
func rfc4193private(ip net.IP) bool {
_, subnet, err := net.ParseCIDR("fd00::/8")
if err != nil {
panic("failed to parse hardcoded rfc4193 cidr: " + err.Error())
}
return subnet.Contains(ip)
}
func isLoopback(ip net.IP) bool {
for _, cidr := range []string{"127.0.0.0/8", "::1/128"} {
_, subnet, err := net.ParseCIDR(cidr)
if err != nil {
panic("failed to parse hardcoded loopback cidr: " + err.Error())
}
if subnet.Contains(ip) {
return true
}
}
return false
}
func mightBePublic(ip net.IP) bool {
return !rfc1918private(ip) && !rfc4193private(ip) && !isLoopback(ip)
}
type name_and_ip struct {
string
net.IP
}
func heuristic(ni name_and_ip) (ret int) {
a := strings.ToLower(ni.string)
ip := ni.IP
if isLoopback(ip) {
ret += 1000
}
if rfc1918private(ip) || rfc4193private(ip) {
ret += 500
}
if strings.Contains(a, "dyn") {
ret += 100
}
if strings.Contains(a, "dhcp") {
ret += 99
}
for i := 0; i < len(ip); i++ {
if strings.Contains(a, strconv.Itoa(int(ip[i]))) {
ret += 5
}
}
return ret
}
type nameAndIPByStabilityHeuristic []name_and_ip
func (nis nameAndIPByStabilityHeuristic) Len() int { return len(nis) }
func (nis nameAndIPByStabilityHeuristic) Swap(i, j int) { nis[i], nis[j] = nis[j], nis[i] }
func (nis nameAndIPByStabilityHeuristic) Less(i, j int) bool { return heuristic(nis[i]) < heuristic(nis[j]) }
func publicAddresses() ([]name_and_ip, error) {
var ret []name_and_ip
addrs, err := net.InterfaceAddrs()
if err != nil {
return nil, err
}
for _, addr := range addrs {
ip, _, err := net.ParseCIDR(addr.String())
if err != nil {
return nil, err
}
// ignore unresolvable addresses
names, err := net.LookupAddr(ip.String())
if err != nil {
continue
}
for _, name := range names {
ret = append(ret, name_and_ip{name, ip})
}
}
sort.Sort(nameAndIPByStabilityHeuristic(ret))
return ret, nil
}
func main() {
if names, err := publicAddresses(); err == nil {
for _, ni := range names {
println(ni.string, ni.IP.String(), heuristic(ni))
}
} else {
panic(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment