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
+11 -10
View File
@@ -65,12 +65,9 @@ var reservedIPNets = sync.OnceValue(func() []*net.IPNet {
return nets 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. // range (see reservedIPNets) that must not be considered a public/external destination.
func isPrivateIP(ip net.IP) bool { func isReservedIP(ip net.IP) bool {
if ip.IsPrivate() {
return true
}
for _, ipNet := range reservedIPNets() { for _, ipNet := range reservedIPNets() {
if ipNet.Contains(ip) { if ipNet.Contains(ip) {
return true return true
@@ -153,18 +150,22 @@ func (hl *HostMatchList) checkPattern(host string) bool {
return false 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, "*") { if slices.Contains(hl.patterns, "*") {
return true return true
} }
for _, builtin := range hl.builtins { for _, builtin := range hl.builtins {
switch builtin { switch builtin {
case MatchBuiltinExternal: 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 return true
} }
case MatchBuiltinPrivate: 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 return true
} }
case MatchBuiltinLoopback: case MatchBuiltinLoopback:
@@ -195,7 +196,7 @@ func (hl *HostMatchList) MatchHostName(host string) bool {
return true return true
} }
if ip := net.ParseIP(hostname); ip != nil { if ip := net.ParseIP(hostname); ip != nil {
return hl.checkIP(ip) return hl.matchesIP(ip)
} }
return false return false
} }
@@ -206,7 +207,7 @@ func (hl *HostMatchList) MatchIPAddr(ip net.IP) bool {
return false return false
} }
host := ip.String() // nil-safe, we will get "<nil>" if ip is nil 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 // MatchHostOrIP checks if the host or IP matches an allow/deny(block) list
+3 -1
View File
@@ -202,15 +202,17 @@ func TestReservedRanges(t *testing.T) {
"198.18.0.1", // benchmarking "198.18.0.1", // benchmarking
"198.51.100.1", // TEST-NET-2 "198.51.100.1", // TEST-NET-2
"203.0.113.1", // TEST-NET-3 "203.0.113.1", // TEST-NET-3
"169.254.169.254", // Cloud metadata
"192.88.99.1", // 6to4 relay anycast "192.88.99.1", // 6to4 relay anycast
"64:ff9b::1", // NAT64 "64:ff9b::1", // NAT64
"64:ff9b::a9fe:a9fe", // NAT64 embedding 169.254.169.254 "64:ff9b::a9fe:a9fe", // NAT64 embedding 169.254.169.254
"2001::1", // Teredo "2001::1", // Teredo
"2002::1", // 6to4 "2002::1", // 6to4
"2001:db8::1", // documentation "2001:db8::1", // documentation
"fe80::1", // link local address
} { } {
addr := net.ParseIP(ip) addr := net.ParseIP(ip)
assert.Falsef(t, external.MatchIPAddr(addr), "reserved ip %s must not be external", 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)
} }
} }