Datagram Guard Options¶
DatagramGuardOptions configures the bounded source-window tracking used by the UDP
listener's DatagramGuard. The guard limits per-source packet rate through
ConnectionLimitOptions.MaxPacketPerSecond, while this options type controls how
many IPv4/IPv6 source windows can be tracked and how stale windows are cleaned up.
Source Mapping¶
src/Nalix.Network/Options/DatagramGuardOptions.cssrc/Nalix.Network/RateLimiting/Datagram.Guard.cssrc/Nalix.Network/Listeners/UdpListener/UdpListener.Core.cs
UDP Listener Wiring¶
UdpListenerBase loads and validates these options in its static constructor:
s_datagramGuardOptions = ConfigurationManager.Instance.Get<DatagramGuardOptions>();
s_datagramGuardOptions.Validate();
Each listener instance then constructs a DatagramGuard with:
ConnectionLimitOptions.MaxPacketPerSecondDatagramGuardOptions.IPv4WindowsDatagramGuardOptions.IPv6WindowsDatagramGuardOptions.CleanupIntervalDatagramGuardOptions.IdleTimeoutDatagramGuardOptions.IPv4CapacityDatagramGuardOptions.IPv6Capacity
flowchart LR
A["UdpListenerBase"] --> B["ConnectionLimitOptions.MaxPacketPerSecond"]
A --> C["DatagramGuardOptions"]
B --> D["DatagramGuard"]
C --> D
D --> E["TryAccept(IPEndPoint)"]
E --> F["IPv4/IPv6 source window"]
F --> G["CAS packet count per second"]
Defaults and Validation¶
| Property | Default | Valid range | Source behavior |
|---|---|---|---|
IPv4Windows |
65_536 |
1..10_000_000 |
Maximum number of IPv4 source windows tracked at once. |
IPv6Windows |
16_384 |
1..10_000_000 |
Maximum number of IPv6 source windows tracked at once. |
IPv4Capacity |
1024 |
1..10_000_000 |
Initial capacity hint for the IPv4 source map. |
IPv6Capacity |
64 |
1..10_000_000 |
Initial capacity hint for the IPv6 source map. |
CleanupInterval |
00:01:00 |
00:00:01..01:00:00 |
Delay between stale-window eviction passes. |
IdleTimeout |
00:00:10 |
00:00:01..01:00:00 |
Inactive source-window retention before eviction. |
FailOpenWhenFull |
false |
Boolean | When true, allows packets through when the tracking map is full, preventing legitimate-user lockout during spoofed-source floods. When false (default), the guard rejects incoming packets when the map is full (fail-closed). |
Validate() uses manual range checks and throws ArgumentOutOfRangeException when constraints are violated.
Runtime Behavior¶
DatagramGuard.TryAccept(IPEndPoint) returns false when:
- the guard has been disposed;
- the endpoint is
null; - the IPv4 or IPv6 source-window map has reached its configured limit;
- the source has already reached
MaxPacketPerSecondin the current second.
The guard stores each source in a WindowSlot with a single packed long:
| Packed field | Meaning |
|---|---|
| high 32 bits | current second token from Environment.TickCount64 / 1000 |
| low 32 bits | packet count in that second |
Updates use Interlocked.CompareExchange, so the hot path avoids locks while still
preserving a precise one-second packet counter per source.
IPv4 and IPv6 Tracking¶
| Address family | Key type | Source note |
|---|---|---|
| IPv4 | uint from IPAddress.Address |
Chosen to avoid IPAddress key allocations and hashing overhead. |
| IPv6 | string from IPAddress.ToString() |
Used as the less-common fallback path for UDP DDoS scenarios. |
Cleanup and Disposal¶
The constructor starts CleanupLoopAsync immediately. The loop waits for
CleanupInterval, then evicts windows whose last-seen second is older than
IdleTimeout.
Dispose() marks the guard disposed, cancels and disposes the cleanup token source,
and clears both IPv4 and IPv6 maps.
Operational Guidance¶
- Increase
IPv4Windows/IPv6Windowsonly when legitimate source cardinality is high enough to require it. - Keep
IdleTimeoutshort for public UDP endpoints under spoofed-source pressure. - Tune
ConnectionLimitOptions.MaxPacketPerSecondseparately; it is the per-source packet-rate limit consumed byDatagramGuard.