Skip to content

Whitelist System

OpenShield's whitelist provides granular per-IP bypass of specific mitigation stages, with Bloom filter acceleration to minimize overhead on the common (non-whitelisted) path.

Whitelist flags

Each whitelisted IP is assigned a 32-bit flags word. Multiple flags can be combined:

FlagValueMnemonicEffect
WL_FULL_BYPASS0x0000Full bypassSkip all checks. Immediate XDP_PASS on whitelist hit.
WL_SKIP_BAN0x0001Skip banSkip single-IP ban + subnet ban lookup
WL_SKIP_RATE0x0002Skip rateSkip rate threshold checks (both threshold scoring and token bucket)
WL_SKIP_VALIDATION0x0004Skip validationSkip L3 validation (private/bogon) + L4 validation (bogus TCP, bounds)

FULL_BYPASS = 0x0000

WL_FULL_BYPASS is 0x0000, which is also the zero value. This means a newly inserted whitelist entry defaults to full bypass. To use granular flags, explicitly set a non-zero flag value. The kernel treats wl_flags == WL_FULL_BYPASS as an immediate XDP_PASS — no further checks are performed.

Whitelist maps

MapTypeKey → ValueMax entriesMemory
whitelist_mapHASHu32(ipv4) → u32(flags)10,000~410 KB
whitelist_map_v6HASHip6_key → u32(flags)10,000~410 KB

HASH, not LRU

Whitelist maps use BPF_MAP_TYPE_HASH (not LRU_HASH). Whitelist entries must never be evicted. They are written by userspace at startup and on config reload, and read by the kernel on every packet.

Bloom filter acceleration

A Bloom filter (3 hash functions, 150K u64 entries = 1.2 MB, ~1% FPR at 1M entries) is checked before the HASH whitelist lookup:

Bloom filter properties

PropertyValue
Hash functionSplitMix64-derived (3 hashes from 1 seed)
Hash count (k)3
Bits per entry64
Total entries150,000
Total memory1.2 MB
False positive rate~1% at 1M IPs
False negativesNone (guaranteed)
Per-check latency~15 ns

If the Bloom filter says "definitely not present", the HASH whitelist lookup is skipped, saving ~60–100ns per packet. If the Bloom filter says "maybe present" (false positive), the HASH lookup is performed — whitelist correctness is preserved. Bloom is purely a fast-path optimization.

IPv6 Bloom support

IPv6 addresses are XOR-folded from 128 bits to 32 bits before Bloom hashing:

c
u32 ip32 = (u32)(key->hi ^ key->lo);
// Then hash ip32 with 3 SplitMix64-derived functions

This is a lossy fold — different IPv6 addresses may collide in the Bloom filter (increasing FPR). In practice this is acceptable because the Bloom is only a fast-path check; the authoritative HASH lookup always follows on a Bloom "maybe".

Empty-map fast path

The whitelist_empty config flag skips all whitelist lookups when the map has 0 entries:

c
if (!cfg->whitelist_empty) {
    // Bloom check + HASH lookup
}

This flag is set by userspace at startup and updated after every config reload. When no whitelist entries exist, the entire whitelist lookup (Bloom + HASH) is skipped — zero overhead.

Flag interaction with pipeline stages

c
// In the XDP entry point:
if (wl_flags == WL_FULL_BYPASS) {
    prof_inc(PROF_WHITELISTED);
    return XDP_PASS;  // Exit immediately
}

// Later stages:
if (!(wl_flags & WL_SKIP_BAN))
    stage_ban_check(...);       // Ban check runs

if (!(wl_flags & WL_SKIP_VALIDATION))
    validate_source_ip(...);     // Validation runs

if (!(wl_flags & WL_SKIP_RATE))
    stage_rate_limit(...);      // Rate limiting runs
StageBlocked by
Ban check (single + subnet)WL_SKIP_BAN
L3 validation (private/bogon)WL_SKIP_VALIDATION
L4 validation (bogus TCP, bounds)WL_SKIP_VALIDATION
UDP amplificationAlways runs (even on whitelist — amp is an inbound attack vector)
L7 signaturesAlways runs
Connection trackingAlways runs
Rate limitingWL_SKIP_RATE

Amplification and L7 checks bypass the bypass

UDP amplification and L7 signature checks are not affected by whitelist flags. A whitelisted IP sending amplified DNS responses will still be dropped. Whitelisting is for protecting legitimate source IPs, not for allowing malicious traffic from those IPs.

Runtime updates

Whitelist entries can be updated at runtime via:

  1. Config reload — edit openshield.yaml, then openshield config reload
  2. CLIopenshield whitelist add 10.0.0.1 --flag full_bypass
  3. API — the userspace gRPC/HTTP server exposes whitelist management endpoints

When entries change, the Bloom filter is rebuilt by userspace (all bits are cleared and re-set from the current whitelist entries). This is a userspace operation — zero kernel overhead for Bloom rebuilds.

Configuration

yaml
whitelist:
  enabled: true
  ips:                                  # Each entry: IP + optional flags
    - ip: "192.168.1.100"
      flags: "full_bypass"             # or: skip_ban, skip_rate, skip_validation

maps:
  whitelist_max: 10000                  # Max IPv4 + IPv6 entries each
  bloom_filter_enabled: true            # Enable Bloom fast path
  bloom_filter_size: 150000             # Number of u64 Bloom words

Ban System · Rate Limiting · Detection Engine