Don't fall through port restrictions to gateway resources with 0.0.0.0/0

This commit is contained in:
Owen
2026-09-23 15:23:59 -04:00
parent f6a4be0137
commit 7e0f83aeae
2 changed files with 163 additions and 1 deletions
+19 -1
View File
@@ -175,13 +175,27 @@ func (sl *SubnetLookup) Match(srcIP, dstIP netip.Addr, port uint16, proto tcpip.
continue
}
// Supernets() yields longest-prefix-match first, then progressively
// less specific. Once a more specific, non-catch-all destination
// rule has been seen and rejected (wrong port/protocol), a
// 0.0.0.0/0 (or ::/0) exit-node rule must not be allowed to rescue
// it - "whole subnet" routing only applies when no more specific
// resource covers this destination at all. Fallthrough between two
// specific (non-catch-all) rules is intentional and unaffected.
sawRejectedSpecificDest := false
// Step 2: Find all destination prefixes that contain dstIP
// This is also O(log n) for each matching source prefix
for _, rules := range destTriePtr.trie.Supernets(dstPrefix) {
for destPrefix, rules := range destTriePtr.trie.Supernets(dstPrefix) {
if rules == nil {
continue
}
isCatchAll := destPrefix.Bits() == 0
if isCatchAll && sawRejectedSpecificDest {
return nil
}
// Step 3: Check each rule for ICMP and port restrictions
for _, rule := range rules {
// Handle ICMP before port range check — ICMP has no ports
@@ -216,6 +230,10 @@ func (sl *SubnetLookup) Match(srcIP, dstIP netip.Addr, port uint16, proto tcpip.
}
}
}
if !isCatchAll {
sawRejectedSpecificDest = true
}
}
}