feat(06-04): implement private/reserved IP classification table
- Port PHP PRIVATE_V4_CIDRS and PRIVATE_V6_PREFIXES onto netip.Prefix - Fail closed on invalid addresses; Unmap remains the caller's job
This commit is contained in:
45
fetchguard/ip.go
Normal file
45
fetchguard/ip.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package fetchguard
|
||||
|
||||
import "net/netip"
|
||||
|
||||
// privateV4 is a literal port of ManualCoverUrlFetcher.php PRIVATE_V4_CIDRS.
|
||||
var privateV4 = []netip.Prefix{
|
||||
netip.MustParsePrefix("127.0.0.0/8"),
|
||||
netip.MustParsePrefix("10.0.0.0/8"),
|
||||
netip.MustParsePrefix("172.16.0.0/12"),
|
||||
netip.MustParsePrefix("192.168.0.0/16"),
|
||||
netip.MustParsePrefix("169.254.0.0/16"),
|
||||
netip.MustParsePrefix("100.64.0.0/10"),
|
||||
netip.MustParsePrefix("0.0.0.0/8"),
|
||||
}
|
||||
|
||||
// privateV6 is a literal port of PRIVATE_V6_PREFIXES. PHP lists bare "::1"
|
||||
// as a prefix-less loopback literal; it is expressed here as ::1/128 so
|
||||
// Prefix.Contains works uniformly with the CIDR entries.
|
||||
var privateV6 = []netip.Prefix{
|
||||
netip.MustParsePrefix("::1/128"),
|
||||
netip.MustParsePrefix("fe80::/10"),
|
||||
netip.MustParsePrefix("fc00::/7"),
|
||||
}
|
||||
|
||||
// isReservedOrPrivate classifies addr against the PHP private/loopback/
|
||||
// reserved/CGNAT table. The caller must pass an already-Unmap()-ed address
|
||||
// (fetch.go's dial hook); this function does not Unmap.
|
||||
func isReservedOrPrivate(addr netip.Addr) bool {
|
||||
if !addr.IsValid() {
|
||||
return true
|
||||
}
|
||||
if addr.IsMulticast() || addr.IsUnspecified() {
|
||||
return true
|
||||
}
|
||||
table := privateV4
|
||||
if !addr.Is4() {
|
||||
table = privateV6
|
||||
}
|
||||
for _, prefix := range table {
|
||||
if prefix.Contains(addr) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user