mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 15:26:40 +00:00
Revert "Add trusted_cidrs field to bypass all restriction layers"
This reverts commit 9c1eb0d288.
This commit is contained in:
@@ -50,11 +50,9 @@ const (
|
||||
CrowdSecObserve CrowdSecMode = "observe"
|
||||
)
|
||||
|
||||
// Filter evaluates IP restrictions. Trusted CIDRs are checked first and
|
||||
// bypass all other layers. Then CIDR checks (cheap), country lookups
|
||||
// (more expensive), and finally CrowdSec reputation checks.
|
||||
// Filter evaluates IP restrictions. CIDR checks are performed first
|
||||
// (cheap), followed by country lookups (more expensive) only when needed.
|
||||
type Filter struct {
|
||||
TrustedCIDRs []netip.Prefix
|
||||
AllowedCIDRs []netip.Prefix
|
||||
BlockedCIDRs []netip.Prefix
|
||||
AllowedCountries []string
|
||||
@@ -65,7 +63,6 @@ type Filter struct {
|
||||
|
||||
// FilterConfig holds the raw configuration for building a Filter.
|
||||
type FilterConfig struct {
|
||||
TrustedCIDRs []string
|
||||
AllowedCIDRs []string
|
||||
BlockedCIDRs []string
|
||||
AllowedCountries []string
|
||||
@@ -76,8 +73,7 @@ type FilterConfig struct {
|
||||
}
|
||||
|
||||
// ParseFilter builds a Filter from the config. Returns nil if no restrictions
|
||||
// are configured. Trusted CIDRs alone don't constitute restrictions: they only
|
||||
// bypass other layers, so without deny rules the filter is a no-op.
|
||||
// are configured.
|
||||
func ParseFilter(cfg FilterConfig) *Filter {
|
||||
hasCS := cfg.CrowdSecMode == CrowdSecEnforce || cfg.CrowdSecMode == CrowdSecObserve
|
||||
if len(cfg.AllowedCIDRs) == 0 && len(cfg.BlockedCIDRs) == 0 &&
|
||||
@@ -98,14 +94,6 @@ func ParseFilter(cfg FilterConfig) *Filter {
|
||||
f.CrowdSec = cfg.CrowdSec
|
||||
f.CrowdSecMode = cfg.CrowdSecMode
|
||||
}
|
||||
for _, cidr := range cfg.TrustedCIDRs {
|
||||
prefix, err := netip.ParsePrefix(cidr)
|
||||
if err != nil {
|
||||
logger.Warnf("skip invalid trusted CIDR %q: %v", cidr, err)
|
||||
continue
|
||||
}
|
||||
f.TrustedCIDRs = append(f.TrustedCIDRs, prefix.Masked())
|
||||
}
|
||||
for _, cidr := range cfg.AllowedCIDRs {
|
||||
prefix, err := netip.ParsePrefix(cidr)
|
||||
if err != nil {
|
||||
@@ -203,9 +191,10 @@ func (f *Filter) IsObserveOnly(v Verdict) bool {
|
||||
return v.IsCrowdSec() && f.CrowdSecMode == CrowdSecObserve
|
||||
}
|
||||
|
||||
// Check evaluates whether addr is permitted. Trusted CIDRs are checked
|
||||
// first and bypass all other layers. Then CIDR rules (O(n) prefix
|
||||
// comparisons), country rules (require geo lookup), and finally CrowdSec.
|
||||
// Check evaluates whether addr is permitted. CIDR rules are evaluated
|
||||
// first because they are O(n) prefix comparisons. Country rules run
|
||||
// only when CIDR checks pass and require a geo lookup. CrowdSec checks
|
||||
// run last.
|
||||
func (f *Filter) Check(addr netip.Addr, geo GeoResolver) Verdict {
|
||||
if f == nil {
|
||||
return Allow
|
||||
@@ -215,12 +204,6 @@ func (f *Filter) Check(addr netip.Addr, geo GeoResolver) Verdict {
|
||||
// IPv4 CIDR rules match regardless of how the address was received.
|
||||
addr = addr.Unmap()
|
||||
|
||||
for _, prefix := range f.TrustedCIDRs {
|
||||
if prefix.Contains(addr) {
|
||||
return Allow
|
||||
}
|
||||
}
|
||||
|
||||
if v := f.checkCIDR(addr); v != Allow {
|
||||
return v
|
||||
}
|
||||
|
||||
@@ -168,10 +168,6 @@ func TestFilter_HasRestrictions(t *testing.T) {
|
||||
assert.False(t, (&Filter{}).HasRestrictions())
|
||||
assert.True(t, ParseFilter(FilterConfig{AllowedCIDRs: []string{"10.0.0.0/8"}}).HasRestrictions())
|
||||
assert.True(t, ParseFilter(FilterConfig{AllowedCountries: []string{"US"}}).HasRestrictions())
|
||||
|
||||
// Trusted CIDRs alone don't constitute restrictions: they only bypass
|
||||
// other layers, so without deny rules the filter is nil (no-op).
|
||||
assert.Nil(t, ParseFilter(FilterConfig{TrustedCIDRs: []string{"10.0.0.0/8"}}))
|
||||
}
|
||||
|
||||
func TestFilter_Check_IPv6CIDR(t *testing.T) {
|
||||
@@ -374,14 +370,12 @@ func TestFilter_IsObserveOnly(t *testing.T) {
|
||||
assert.False(t, f2.IsObserveOnly(DenyCrowdSecBan))
|
||||
}
|
||||
|
||||
// TestFilter_LayerInteraction exercises the evaluation order across all
|
||||
// restriction layers: Trusted -> CIDR -> Country -> CrowdSec.
|
||||
// Trusted CIDRs bypass everything. Each subsequent layer can only further
|
||||
// TestFilter_LayerInteraction exercises the evaluation order across all three
|
||||
// restriction layers: CIDR -> Country -> CrowdSec. Each layer can only further
|
||||
// restrict; no layer can relax a denial from an earlier layer.
|
||||
//
|
||||
// Layer order | Behavior
|
||||
// ---------------|-------------------------------------------------------
|
||||
// 0. Trusted | Bypass all restrictions. Immediate allow.
|
||||
// 1. CIDR | Allowlist narrows to specific ranges, blocklist removes
|
||||
// | specific ranges. Deny here → stop, CrowdSec never runs.
|
||||
// 2. Country | Allowlist/blocklist by geo. Deny here → stop.
|
||||
@@ -487,44 +481,6 @@ func TestFilter_LayerInteraction(t *testing.T) {
|
||||
addr: bannedIP,
|
||||
want: DenyCrowdSecBan, // verdict is ban, caller checks IsObserveOnly
|
||||
},
|
||||
|
||||
// Trusted CIDRs bypass all layers
|
||||
{
|
||||
name: "trusted CIDR bypasses CIDR deny",
|
||||
config: FilterConfig{TrustedCIDRs: []string{"192.168.0.0/16"}, AllowedCIDRs: []string{"10.0.0.0/8"}},
|
||||
addr: outsideIP, // 192.168.x not in CIDR allowlist, but trusted
|
||||
want: Allow,
|
||||
},
|
||||
{
|
||||
name: "trusted CIDR bypasses country deny",
|
||||
config: FilterConfig{TrustedCIDRs: []string{"192.168.0.0/16"}, AllowedCountries: []string{"US"}},
|
||||
addr: outsideIP, // CN country, but trusted
|
||||
want: Allow,
|
||||
},
|
||||
{
|
||||
name: "trusted CIDR bypasses CrowdSec ban",
|
||||
config: FilterConfig{TrustedCIDRs: []string{"10.0.0.0/8"}, CrowdSec: cs, CrowdSecMode: CrowdSecEnforce},
|
||||
addr: bannedIP, // banned by CrowdSec, but trusted
|
||||
want: Allow,
|
||||
},
|
||||
{
|
||||
name: "trusted CIDR bypasses all layers combined",
|
||||
config: FilterConfig{
|
||||
TrustedCIDRs: []string{"10.0.0.0/8"},
|
||||
AllowedCIDRs: []string{"172.16.0.0/12"},
|
||||
AllowedCountries: []string{"FR"},
|
||||
CrowdSec: cs,
|
||||
CrowdSecMode: CrowdSecEnforce,
|
||||
},
|
||||
addr: bannedIP, // not in allowed CIDR, wrong country, banned, but trusted
|
||||
want: Allow,
|
||||
},
|
||||
{
|
||||
name: "non-trusted IP still checked normally",
|
||||
config: FilterConfig{TrustedCIDRs: []string{"172.16.0.0/12"}, CrowdSec: cs, CrowdSecMode: CrowdSecEnforce},
|
||||
addr: bannedIP, // not in trusted range, banned
|
||||
want: DenyCrowdSecBan,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
|
||||
@@ -1325,7 +1325,6 @@ func (s *Server) parseRestrictions(mapping *proto.ProxyMapping) *restrict.Filter
|
||||
}
|
||||
|
||||
return restrict.ParseFilter(restrict.FilterConfig{
|
||||
TrustedCIDRs: r.GetTrustedCidrs(),
|
||||
AllowedCIDRs: r.GetAllowedCidrs(),
|
||||
BlockedCIDRs: r.GetBlockedCidrs(),
|
||||
AllowedCountries: r.GetAllowedCountries(),
|
||||
|
||||
Reference in New Issue
Block a user