fix(hostmacher): patch incorrect private list (#38170) (#38173)

Backport #38170 by @TheFox0x7

regression from #38039

Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
This commit is contained in:
Giteabot
2026-06-19 14:50:01 -07:00
committed by GitHub
parent 42eb7945d1
commit b0eaf6c75b
2 changed files with 14 additions and 11 deletions

View File

@@ -65,12 +65,9 @@ var reservedIPNets = sync.OnceValue(func() []*net.IPNet {
return nets
})
// isPrivateIP reports whether ip falls in a private (net.IP.IsPrivate) or reserved special-purpose
// isReservedIP reports whether ip falls in reserved special-purpose
// range (see reservedIPNets) that must not be considered a public/external destination.
func isPrivateIP(ip net.IP) bool {
if ip.IsPrivate() {
return true
}
func isReservedIP(ip net.IP) bool {
for _, ipNet := range reservedIPNets() {
if ipNet.Contains(ip) {
return true
@@ -153,18 +150,22 @@ func (hl *HostMatchList) checkPattern(host string) bool {
return false
}
func (hl *HostMatchList) checkIP(ip net.IP) bool {
// matchesIP determines if the given IP matches any of the configured rules
func (hl *HostMatchList) matchesIP(ip net.IP) bool {
if slices.Contains(hl.patterns, "*") {
return true
}
for _, builtin := range hl.builtins {
switch builtin {
case MatchBuiltinExternal:
if ip.IsGlobalUnicast() && !isPrivateIP(ip) {
// External address must be a global unicast, must not be in reserved range and must not be in private range
if ip.IsGlobalUnicast() && !isReservedIP(ip) && !ip.IsPrivate() {
return true
}
case MatchBuiltinPrivate:
if isPrivateIP(ip) {
// Private address must be global unicast, must not be in range we explicitly exclude for security reasons
// and must be in private range
if ip.IsGlobalUnicast() && !isReservedIP(ip) && ip.IsPrivate() {
return true
}
case MatchBuiltinLoopback:
@@ -195,7 +196,7 @@ func (hl *HostMatchList) MatchHostName(host string) bool {
return true
}
if ip := net.ParseIP(hostname); ip != nil {
return hl.checkIP(ip)
return hl.matchesIP(ip)
}
return false
}
@@ -206,7 +207,7 @@ func (hl *HostMatchList) MatchIPAddr(ip net.IP) bool {
return false
}
host := ip.String() // nil-safe, we will get "<nil>" if ip is nil
return hl.checkPattern(host) || hl.checkIP(ip)
return hl.checkPattern(host) || hl.matchesIP(ip)
}
// MatchHostOrIP checks if the host or IP matches an allow/deny(block) list

View File

@@ -202,15 +202,17 @@ func TestReservedRanges(t *testing.T) {
"198.18.0.1", // benchmarking
"198.51.100.1", // TEST-NET-2
"203.0.113.1", // TEST-NET-3
"169.254.169.254", // Cloud metadata
"192.88.99.1", // 6to4 relay anycast
"64:ff9b::1", // NAT64
"64:ff9b::a9fe:a9fe", // NAT64 embedding 169.254.169.254
"2001::1", // Teredo
"2002::1", // 6to4
"2001:db8::1", // documentation
"fe80::1", // link local address
} {
addr := net.ParseIP(ip)
assert.Falsef(t, external.MatchIPAddr(addr), "reserved ip %s must not be external", ip)
assert.Truef(t, private.MatchIPAddr(addr), "reserved ip %s should match private block-list", ip)
assert.Falsef(t, private.MatchIPAddr(addr), "reserved ip %s should match private block-list", ip)
}
}