Check if IP address is in private network space

That should be easier to do with Go 1.17 (Q4 2021, 5 years later), as reported by Go 101:

See commit c73fccc and CL 272668:

net: add IP.IsPrivate()

Add IsPrivate() helper to check if an IP is private according to RFC 1918 & RFC 4193

That fixes golang issue 29146 raised by Aaran McGuire:

The net package seems to have many helpers to report what an IP is. e.g:

  • IsLoopback()
  • IsMulticast()
  • IsInterfaceLocalMulticast()

However there are no helpers to report if a IP address is in the private ranges (RFC 1918 & RFC 4193).


You might also want to include checks for loopback (IPv4 or IPv6) and/or IPv6 link-local or unique-local addresses. Here is an example with a list of RFC1918 address plus these others and a simple check against them as isPrivateIP(ip net.IP):

var privateIPBlocks []*net.IPNet

func init() {
    for _, cidr := range []string{
        "127.0.0.0/8",    // IPv4 loopback
        "10.0.0.0/8",     // RFC1918
        "172.16.0.0/12",  // RFC1918
        "192.168.0.0/16", // RFC1918
        "169.254.0.0/16", // RFC3927 link-local
        "::1/128",        // IPv6 loopback
        "fe80::/10",      // IPv6 link-local
        "fc00::/7",       // IPv6 unique local addr
    } {
        _, block, err := net.ParseCIDR(cidr)
        if err != nil {
            panic(fmt.Errorf("parse error on %q: %v", cidr, err))
        }
        privateIPBlocks = append(privateIPBlocks, block)
    }
}

func isPrivateIP(ip net.IP) bool {
    if ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() {
        return true
    }

    for _, block := range privateIPBlocks {
        if block.Contains(ip) {
            return true
        }
    }
    return false
  }