package manetimport (ma)// Private4 and Private6 are well-known private networksvarPrivate4, Private6 []*net.IPNetvar privateCIDR4 = []string{// localhost"127.0.0.0/8",// private networks"10.0.0.0/8","100.64.0.0/10","172.16.0.0/12","192.168.0.0/16",// link local"169.254.0.0/16",}var privateCIDR6 = []string{// localhost"::1/128",// ULA reserved"fc00::/7",// link local"fe80::/10",}// Unroutable4 and Unroutable6 are well known unroutable address rangesvarUnroutable4, Unroutable6 []*net.IPNetvar unroutableCIDR4 = []string{"0.0.0.0/8","192.0.0.0/26","192.0.2.0/24","192.88.99.0/24","198.18.0.0/15","198.51.100.0/24","203.0.113.0/24","224.0.0.0/4","240.0.0.0/4","255.255.255.255/32",}var unroutableCIDR6 = []string{"ff00::/8", // multicast"2001:db8::/32", // documentation}var globalUnicast []*net.IPNetvar globalUnicastCIDR6 = []string{"2000::/3",}var nat64CIDRs = []string{"64:ff9b:1::/48", // RFC 8215"64:ff9b::/96", // RFC 6052}var nat64 []*net.IPNet// unResolvableDomains do not resolve to an IP address.// Ref: https://en.wikipedia.org/wiki/Special-use_domain_name#Reserved_domain_namesvar unResolvableDomains = []string{// Reverse DNS Lookup".in-addr.arpa",".ip6.arpa",// RFC 6761: Users MAY assume that queries for "invalid" names will always return NXDOMAIN // responses".invalid",}// privateUseDomains are reserved for private use and have no central authority for consistent// address resolution// Ref: https://en.wikipedia.org/wiki/Special-use_domain_name#Reserved_domain_namesvar privateUseDomains = []string{// RFC 8375: Reserved for home networks".home.arpa",// MDNS".local",// RFC 6761: No central authority for .test names".test",}// RFC 6761: Users may assume that IPv4 and IPv6 address queries for localhost names will// always resolve to the respective IP loopback addressconst localHostDomain = ".localhost"func init() {Private4 = parseCIDR(privateCIDR4)Private6 = parseCIDR(privateCIDR6)Unroutable4 = parseCIDR(unroutableCIDR4)Unroutable6 = parseCIDR(unroutableCIDR6)globalUnicast = parseCIDR(globalUnicastCIDR6)nat64 = parseCIDR(nat64CIDRs)}func parseCIDR( []string) []*net.IPNet { := make([]*net.IPNet, len())for , := range { , , := net.ParseCIDR()if != nil {panic() } [] = }return}// IsPublicAddr returns true if the IP part of the multiaddr is a publicly routable address// or if it's a dns address without a special use domain e.g. .local.func ( ma.Multiaddr) bool { := falsema.ForEach(, func( ma.Component) bool {switch .Protocol().Code {casema.P_IP6ZONE:returntruecasema.P_IP4: := net.IP(.RawValue()) = !inAddrRange(, Private4) && !inAddrRange(, Unroutable4)casema.P_IP6: := net.IP(.RawValue())// IP6 documentation prefix(part of Unroutable6) is a subset of the ip6 // global unicast allocation so we ensure that it's not a documentation // prefix by diffing with Unroutable6 := inAddrRange(, globalUnicast) && !inAddrRange(, Unroutable6)if { = truereturnfalse }// The WellKnown NAT64 prefix(RFC 6052) can only reference a public IPv4 // address. // The Local use NAT64 prefix(RFC 8215) can reference private IPv4 // addresses. But since the translation from Local use NAT64 prefix to IPv4 // address is left to the user we have no way of knowing which IPv4 address // is referenced. We count these as Public addresses because a false // negative for this method here is generally worse than a false positive. = inAddrRange(, nat64)returnfalsecasema.P_DNS, ma.P_DNS4, ma.P_DNS6, ma.P_DNSADDR: := .Value() = trueifisSubdomain(, localHostDomain) { = falsereturnfalse }for , := rangeunResolvableDomains {ifisSubdomain(, ) { = falsereturnfalse } }for , := rangeprivateUseDomains {ifisSubdomain(, ) { = falsebreak } } }returnfalse })return}// isSubdomain checks if child is sub domain of parent. It also returns true if child and parent are// the same domain.// Parent must have a "." prefix.func isSubdomain(, string) bool {returnstrings.HasSuffix(, ) || == [1:]}// IsPrivateAddr returns true if the IP part of the mutiaddr is in a private networkfunc ( ma.Multiaddr) bool { := falsema.ForEach(, func( ma.Component) bool {switch .Protocol().Code {casema.P_IP6ZONE:returntruecasema.P_IP4: = inAddrRange(net.IP(.RawValue()), Private4)casema.P_IP6: = inAddrRange(net.IP(.RawValue()), Private6)casema.P_DNS, ma.P_DNS4, ma.P_DNS6, ma.P_DNSADDR: := .Value()ifisSubdomain(, localHostDomain) { = true }// We don't check for privateUseDomains because private use domains can // resolve to public IP addresses }returnfalse })return}func inAddrRange( net.IP, []*net.IPNet) bool {for , := range {if .Contains() {returntrue } }returnfalse}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.