refactor(10.2-01): nest framework packages under modules
- Move remaining beach packages and embedded admin assets\n- Rewrite framework, example, build, and gate paths
This commit is contained in:
82
modules/fetchguard/ip.go
Normal file
82
modules/fetchguard/ip.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package fetchguard
|
||||
|
||||
import "net/netip"
|
||||
|
||||
// privateV4 is the IANA IPv4 special-purpose non-public set. It is a strict
|
||||
// superset of ManualCoverUrlFetcher.php's lists (06-VERIFICATION gap 3).
|
||||
var privateV4 = mustPrefixes(
|
||||
"0.0.0.0/8", "10.0.0.0/8", "100.64.0.0/10", "127.0.0.0/8",
|
||||
"169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.2.0/24",
|
||||
"192.88.99.0/24", "192.168.0.0/16", "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",
|
||||
)
|
||||
|
||||
// privateV6 is the IANA IPv6 special-purpose non-public set. 2002::/16 and
|
||||
// 64:ff9b::/96 are handled by embeddedTransitionIPv4 instead.
|
||||
var privateV6 = mustPrefixes(
|
||||
"::/96", "100::/64", "2001::/23", "2001:db8::/32", "3fff::/20",
|
||||
"5f00::/16", "fc00::/7", "fe80::/10", "fec0::/10", "ff00::/8",
|
||||
)
|
||||
|
||||
func mustPrefixes(cidrs ...string) []netip.Prefix {
|
||||
out := make([]netip.Prefix, len(cidrs))
|
||||
for i, c := range cidrs {
|
||||
out[i] = netip.MustParsePrefix(c)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var (
|
||||
nat64WellKnownPrefix = netip.MustParsePrefix("64:ff9b::/96")
|
||||
nat64LocalUsePrefix = netip.MustParsePrefix("64:ff9b:1::/48")
|
||||
sixToFourPrefix = netip.MustParsePrefix("2002::/16")
|
||||
)
|
||||
|
||||
// isReservedOrPrivate classifies addr against the PHP private/loopback/
|
||||
// reserved/CGNAT table, including IPv4 embedded in supported IPv6 transition
|
||||
// formats.
|
||||
func isReservedOrPrivate(addr netip.Addr) bool {
|
||||
if !addr.IsValid() {
|
||||
return true
|
||||
}
|
||||
addr = addr.WithZone("").Unmap()
|
||||
if addr.IsMulticast() || addr.IsUnspecified() {
|
||||
return true
|
||||
}
|
||||
if embedded, ok := embeddedTransitionIPv4(addr); ok {
|
||||
return isReservedOrPrivate(embedded)
|
||||
}
|
||||
table := privateV4
|
||||
if !addr.Is4() {
|
||||
table = privateV6
|
||||
}
|
||||
for _, prefix := range table {
|
||||
if prefix.Contains(addr) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// embeddedTransitionIPv4 extracts IPv4 from the transition formats supported
|
||||
// by fetchguard. A recognized but malformed RFC 6052 /48 address returns an
|
||||
// invalid address with ok=true so the classifier fails closed.
|
||||
func embeddedTransitionIPv4(addr netip.Addr) (netip.Addr, bool) {
|
||||
if !addr.Is6() {
|
||||
return netip.Addr{}, false
|
||||
}
|
||||
b := addr.As16()
|
||||
switch {
|
||||
case nat64WellKnownPrefix.Contains(addr):
|
||||
return netip.AddrFrom4([4]byte{b[12], b[13], b[14], b[15]}), true
|
||||
case nat64LocalUsePrefix.Contains(addr):
|
||||
if b[8] != 0 {
|
||||
return netip.Addr{}, true
|
||||
}
|
||||
return netip.AddrFrom4([4]byte{b[6], b[7], b[9], b[10]}), true
|
||||
case sixToFourPrefix.Contains(addr):
|
||||
return netip.AddrFrom4([4]byte{b[2], b[3], b[4], b[5]}), true
|
||||
default:
|
||||
return netip.Addr{}, false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user