1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! # Per-IP DDoS scoring and connection-slot accounting
//!
//! Defines three collaborating pieces:
//!
//! - [`DdosScore`] — per-IP score with linear time-decay (drains
//! [`crate::tools::config::SERVER_DDOS_DECAY_PER_SECOND`] points per second). Bad
//! requests add points, good requests don't, and once the score crosses
//! [`crate::tools::config::SERVER_DDOS_SCORE_THRESHOLD`] the IP is banned. Decay is
//! lazy so there's no background timer — every `increment` or `current` call
//! recomputes based on elapsed real time.
//! - [`DdosConnectionGuard`] — an RAII guard returned to the transport for every open
//! connection slot. Its `Drop` decrements the per-IP connection count. Request
//! processing code threads this guard through `IncomingRequest`, so the moment the
//! request is finished the slot is freed, automatically.
//! - [`DdosProtection`] — the overall trait the transport calls into:
//! `try_accept_connection` (returns `None` if over limit), `observe_bad_request`,
//! `ban` (pokes `ipset`/`iptables` via the sibling server crate on native).
//!
//! Two implementations exist:
//! [`crate::transport::ddos::mem_ddos`] for accounting-only deployments and tests, and
//! the native ipset-backed production implementation lives in `hashiverse-server-lib`.
use Arc;
use Instant;
/// Per-IP score with linear time decay.
///
/// Score drains at `decay_per_second` points per second. The decay is applied
/// lazily on each `increment` or `current` call — no background timer needed.
/// RAII guard for a single IP's connection slot.
///
/// Created by `DdosConnectionGuard::try_new`; dropped when the connection ends.
/// While alive it holds a slot in the per-IP connection counter.
/// Exposes `allow_request` and `report_bad_request` so callers never need to
/// pass a raw `Arc<dyn DdosProtection>` through request handling code.
/// The server-side throttle and abuse-mitigation policy for inbound connections.
///
/// Every inbound request is gated through a `DdosProtection` implementation: the server asks
/// `try_acquire_connection` when a new connection lands, `allow_request` before processing
/// each request, and calls `report_bad_request` when a packet fails validation (bad PoW,
/// malformed RPC framing, signature mismatch, …). Implementations accumulate a per-IP score
/// from reported bad requests and refuse further connections above a threshold.
///
/// Pairing with [`DdosConnectionGuard`] means call sites never have to pass a raw
/// `Arc<dyn DdosProtection>` through every layer of the request handler — the guard carries
/// a handle to this trait through `IncomingRequest` and releases its slot automatically
/// on drop. A `NoopDdosProtection` exists for tests that do not want to exercise rate limiting.