fix https://github.com/fosrl/pangolin/issues/2952 issue by setting the incoming host header to the outgoing one by the reverse proxy, this was the default behaviour when using single proxy but now since we use more features it now rewrites the host header
Preserve optional ResponseWriter interfaces through statusCapture so httputil.ReverseProxy can hijack upgraded websocket connections. Add a regression test covering websocket traffic through the HTTP handler path.
- Fix prefix canonicalization: use Masked() to handle host bits correctly
(e.g., 10.0.0.5/24 and 10.0.0.0/24 are now treated as equal)
- Fix empty trie cleanup: use BART's Size() method to check if trie is empty
instead of relying on rules slice length, preventing stale entries
- Fix go.mod: move BART from indirect to direct dependencies
These fixes ensure proper bookkeeping and prevent memory leaks from
empty tries hanging around after rule removal.
Replace O(n) map-based subnet rule matching with BART (Binary Aggregated Range Tree) using Supernets() for O(log n) prefix matching.
Performance improvements:
- 1.3x faster for large rule sets (1000+ rules)
- 39x faster for no-match cases (critical for firewall/security)
- 1.9x faster for adding rules
- Better scaling characteristics
Trade-offs:
- Small rule sets (10-100): 1.2-1.4x slower for matches (20-30ns overhead)
- Large rule sets (1000+): 1.3x faster
- No-match: 39x faster (original checks all rules, BART uses O(log n) tree lookup)
The no-match performance is particularly important for security/firewall scenarios where many packets are rejected. BART can determine 'no match' in ~7 tree operations vs checking all 100+ rules.
Dependencies:
- Added: github.com/gaissmai/bart v0.26.0
Files:
- netstack2/subnet_lookup.go: New BART-based implementation
- netstack2/proxy.go: Removed old map-based implementation, updated to use BART
Replace O(n) linear search through NAT table with O(1) reverse lookup map
for reply packet NAT translation.
Changes:
- Add reverseConnKey type for reverse NAT lookups
- Add reverseNatTable map to ProxyHandler for O(1) lookups
- Populate both forward and reverse maps when creating NAT entries
- Replace iteration-based reverse lookup with direct map access
Performance:
- O(n) → O(1) complexity for reverse NAT lookups
- Eliminates lock-held iteration on every reply packet
- Removes string comparisons from hot path
- Expected 10-50x improvement for reverse NAT lookups
This addresses Critical #1 from performance analysis where reply path
was walking the entire NAT table to find original mapping.