Package rfc6890

import "funnyhaha.technology/rfc/rfc6890"
View the source code

Overview

Package rfc6890 reports whether an IP address is in one of the special-purpose address blocks of RFC 6890 (Special-Purpose IP Address Registries): private-use, loopback, link-local, documentation and the rest.

A server that fetches URLs its clients supply checks the address it's about to connect to, so a URL can't make it reach its own network. The OAuth Client ID Metadata Document draft, for example, says an authorization server "MUST NOT fetch" a document from a special-purpose address. Check the resolved address at dial time, not the host name, or DNS can return a different address after the check:

dialer := net.Dialer{ControlContext: func(_ context.Context, _, address string, _ syscall.RawConn) error {
	ap, err := netip.ParseAddrPort(address)
	if err != nil || rfc6890.IsSpecialPurpose(ap.Addr().Unmap()) {
		return errForbiddenAddress
	}
	return nil
}}

The package covers the blocks RFC 6890 lists. IANA's registries have added blocks since, and RFC 6890 doesn't list multicast, so a caller that means "only public unicast" should also require netip.Addr.IsGlobalUnicast.

The RFC text is in rfc6890.txt in this directory, and the doc comments cite its sections.

Index

Functions

IsSpecialPurpose source

func IsSpecialPurpose(addr netip.Addr) bool

IsSpecialPurpose reports whether addr is in one of the special-purpose address blocks of RFC 6890: the IPv4 table of Section 2.2.2 or the IPv6 table of Section 2.2.3. The invalid Addr is reported as special-purpose, so a caller that fails closed needn't check it separately. An IPv6 zone, as in fe80::1%eth0, is ignored, since a zoned address is never in a netip.Prefix.

IPv4-mapped IPv6 addresses (::ffff:0:0/96) are in the IPv6 table, so they're special-purpose whatever IPv4 address they map. Call netip.Addr.Unmap first to judge the IPv4 address instead.