Skip to content

enhance: add IP aggregation option for blocklists#122

Merged
LaurenceJJones merged 10 commits into
mainfrom
feature/ip-aggregation
Jan 27, 2026
Merged

enhance: add IP aggregation option for blocklists#122
LaurenceJJones merged 10 commits into
mainfrom
feature/ip-aggregation

Conversation

@LaurenceJJones

@LaurenceJJones LaurenceJJones commented Jan 19, 2026

Copy link
Copy Markdown
Contributor

Add aggregate: true configuration option that merges individual IP decisions into minimal CIDR blocks, reducing blocklist size.

Feature:

  • New aggregate field in blocklist config works with any format
  • Adjacent IPs are merged into larger CIDR ranges (e.g., .0 + .1 → /31)
  • Overlapping prefixes are deduplicated (larger block absorbs smaller)
  • Supports both IPv4 and IPv6 with optimized bit operations

Performance:

  • Aggregation is pre-computed when decisions are added/deleted from LAPI
  • HTTP requests read from cached aggregated view (no per-request cost)
  • Only enabled if at least one blocklist has aggregate: true
  • Uses RWMutex for concurrent read access during updates

Example config:

  blocklists:
    - format: plain_text
      endpoint: /security/blocklist
      aggregate: true

Files:

  • pkg/aggregate/aggregate.go: sort-and-merge algorithm
  • pkg/aggregate/aggregate_test.go: comprehensive tests
  • pkg/registry/registry.go: stores pre-computed aggregated view
  • pkg/cfg/config.go: Aggregate bool field
  • pkg/server/server.go: passes aggregate flag to registry
  • cmd/root.go: enables aggregation before LAPI connection

Add `aggregate: true` configuration option that merges individual IP
decisions into minimal CIDR blocks, reducing blocklist size.

Feature:
- New `aggregate` field in blocklist config works with any format
- Adjacent IPs are merged into larger CIDR ranges (e.g., .0 + .1 → /31)
- Overlapping prefixes are deduplicated (larger block absorbs smaller)
- Supports both IPv4 and IPv6 with optimized bit operations

Performance:
- Aggregation is pre-computed when decisions are added/deleted from LAPI
- HTTP requests read from cached aggregated view (no per-request cost)
- Only enabled if at least one blocklist has aggregate: true
- Uses RWMutex for concurrent read access during updates

Filter behavior:
- ipv4only/ipv6only: work normally on aggregated results
- origin/supported_decisions_types: skipped for aggregated results
  (aggregated ranges may contain IPs from multiple origins/types)

Example config:
  blocklists:
    - format: plain_text
      endpoint: /security/blocklist
      aggregate: true

Files:
- pkg/aggregate/aggregate.go: sort-and-merge algorithm
- pkg/aggregate/aggregate_test.go: comprehensive tests
- pkg/registry/registry.go: stores pre-computed aggregated view
- pkg/cfg/config.go: Aggregate bool field
- pkg/server/server.go: passes aggregate flag to registry
- cmd/root.go: enables aggregation before LAPI connection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds an IP aggregation feature that merges individual IP decisions into minimal CIDR blocks to reduce blocklist sizes. Aggregation is configured per-blocklist via an aggregate: true option and pre-computed when decisions are added/deleted to avoid per-request overhead.

Changes:

  • New aggregate package implementing sort-and-merge algorithm for IPv4/IPv6 CIDR optimization
  • Registry modifications to store pre-computed aggregated decisions with RWMutex for concurrent access
  • Per-blocklist aggregate configuration flag passed through middleware chain

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
pkg/aggregate/aggregate.go Core aggregation algorithm with CIDR merging and deduplication logic
pkg/aggregate/aggregate_test.go Comprehensive unit tests for aggregation functionality
pkg/registry/registry.go Added aggregation storage, locking, and dual decision views (aggregated/non-aggregated)
pkg/server/server.go Modified middleware to accept and pass aggregate flag per blocklist
pkg/cfg/config.go Added Aggregate boolean field to BlockListConfig
cmd/root.go Enables aggregation on registry if any blocklist requires it
.golangci.yml Increased complexity thresholds to accommodate new code
go.mod Added testify dependency for testing

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/registry/registry.go Outdated
Comment thread pkg/registry/registry.go Outdated
Comment thread pkg/registry/registry.go
Comment thread pkg/aggregate/aggregate.go
Comment thread pkg/registry/registry.go
Comment thread cmd/root.go
LaurenceJJones and others added 2 commits January 20, 2026 10:39
Prevent potential panic if a decision has nil Value pointer.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ProcessDecisions method that handles both additions and deletions
with a single lock and only recomputes aggregation once, instead of
potentially twice when both new and deleted decisions arrive together.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

- Always output CIDR notation (e.g., 10.0.0.1/32) with 'range' scope
  for all aggregated decisions, preventing formatter issues
- Add placeholder values for Scenario ('aggregated') and Duration ('24h')
  to prevent panics in formatters that require these fields
- Add defensive nil check for Scenario in F5 formatter
- Performance optimizations: pre-allocate slices, reuse string constants,
  use IndexByte instead of Contains for CIDR detection
- Replace custom stringPtr with ptr.Of() from go-cs-lib/ptr

Fixes issues where:
- F5 formatter would panic on nil Scenario
- Juniper formatter would generate invalid output like 10.0.0.1/32/32
- Mikrotik templates would show <nil> for Scenario/Duration
Comment thread pkg/aggregate/aggregate.go Outdated
Comment thread pkg/aggregate/aggregate_test.go
Comment thread pkg/aggregate/aggregate.go Outdated
@LaurenceJJones LaurenceJJones requested a review from blotus January 27, 2026 14:59
@LaurenceJJones LaurenceJJones merged commit b1fecec into main Jan 27, 2026
4 checks passed
@LaurenceJJones LaurenceJJones deleted the feature/ip-aggregation branch January 27, 2026 15:26
LaurenceJJones added a commit to crowdsecurity/crowdsec-docs that referenced this pull request Jan 27, 2026
* feat: clean up bl-mirror docs and add aggregate option

See crowdsecurity/cs-blocklist-mirror#122

* enhance: add other 0.0.6 option
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants