Block 6to4/Teredo/NAT64-local/site-local/benchmarking/reserved ranges from the IANA registries (families, not decoded embeds). Guard.DenyPrefixes / -deny-prefix covers hairpin WAN /32s; home addresses stay on-box, not in git. Control is tcp/tcp4/tcp6 only.
64 lines
2.3 KiB
Go
64 lines
2.3 KiB
Go
package guard
|
|
|
|
import "net/netip"
|
|
|
|
// IANA special-purpose registries (IPv4 and IPv6). Families that can embed
|
|
// IPv4 (6to4, Teredo, well-known NAT64, local-use NAT64) are blocked outright
|
|
// rather than decoded. IsGlobalUnicast remains a final gate in CheckAddr.
|
|
//
|
|
// Sources:
|
|
// https://www.iana.org/assignments/iana-ipv4-special-registry
|
|
// https://www.iana.org/assignments/iana-ipv6-special-registry
|
|
var ianaDeny = []struct {
|
|
prefix netip.Prefix
|
|
reason string
|
|
}{
|
|
// IPv4
|
|
{p("0.0.0.0/8"), "unspecified address"},
|
|
{p("10.0.0.0/8"), "private address"},
|
|
{p("100.64.0.0/10"), "tailnet address"},
|
|
{p("127.0.0.0/8"), "loopback address"},
|
|
{p("169.254.0.0/16"), "link-local address"},
|
|
{p("172.16.0.0/12"), "private address"},
|
|
{p("192.0.0.0/24"), "special-purpose address"},
|
|
{p("192.0.2.0/24"), "special-purpose address"},
|
|
{p("192.31.196.0/24"), "special-purpose address"},
|
|
{p("192.52.193.0/24"), "special-purpose address"},
|
|
{p("192.88.99.0/24"), "special-purpose address"},
|
|
{p("192.168.0.0/16"), "private address"},
|
|
{p("192.175.48.0/24"), "special-purpose address"},
|
|
{p("198.18.0.0/15"), "special-purpose address"},
|
|
{p("198.51.100.0/24"), "special-purpose address"},
|
|
{p("203.0.113.0/24"), "special-purpose address"},
|
|
{p("224.0.0.0/4"), "multicast address"},
|
|
{p("240.0.0.0/4"), "special-purpose address"},
|
|
{p("255.255.255.255/32"), "special-purpose address"},
|
|
|
|
// IPv6
|
|
{p("::/128"), "unspecified address"},
|
|
{p("::1/128"), "loopback address"},
|
|
{p("64:ff9b::/96"), "NAT64 prefix"},
|
|
{p("64:ff9b:1::/48"), "NAT64 prefix"},
|
|
{p("100::/64"), "special-purpose address"},
|
|
{p("2001::/23"), "special-purpose address"}, // IETF protocol: Teredo, ORCHID, ORCHIDv2, …
|
|
{p("2001:db8::/32"), "special-purpose address"},
|
|
{p("2002::/16"), "special-purpose address"}, // 6to4; do not decode embedded v4
|
|
{p("3fff::/20"), "special-purpose address"}, // documentation (RFC 9637)
|
|
{p("fc00::/7"), "private address"},
|
|
{p("fe80::/10"), "link-local address"},
|
|
{p("fec0::/10"), "special-purpose address"}, // deprecated site-local
|
|
{p("ff00::/8"), "multicast address"},
|
|
{p("fd7a:115c:a1e0::/48"), "tailnet address"},
|
|
}
|
|
|
|
func p(s string) netip.Prefix { return netip.MustParsePrefix(s) }
|
|
|
|
func checkIANA(addr netip.Addr) error {
|
|
for _, e := range ianaDeny {
|
|
if e.prefix.Contains(addr) {
|
|
return blockedAddr(e.reason, addr)
|
|
}
|
|
}
|
|
return nil
|
|
}
|