feat(security): auto-block repeat offenders via CrowdSec community reputation
Gitea Actions Runner Test / test-job (push) Successful in 0s
CI / check (push) Failing after 17s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
Gitea Actions Runner Test / test-job (push) Successful in 0s
CI / check (push) Failing after 17s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
- new crowdsec-api lib: CTI lookup (GET /smoke/{ip}, freemium x-api-key), verdict parser with false-positive veto, 1h Redis + in-memory verdict cache, NX lock dedupe, 403/429 backoff; writes only the shared antiddos:block:{ip} key (value "crowdsec") and never touches Cloudflare
- gate fires it fire-and-forget for IPs that already tripped a rate bucket, so known-bad IPs are hard-blocked before the local maxViolations threshold
- runtime config: crowdsecAutoBlock toggle, score threshold (0-5, default 4), block TTL (default 24h); boot defaults CROWDSEC_AUTO_BLOCK_ENABLED / CROWDSEC_BLOCK_SCORE / CROWDSEC_BLOCK_TTL_SECONDS
- admin panel: CrowdSec stat card, verify-connection action, score/TTL settings, CrowdSec source badge in the blocked-IPs list
- credentials live in env only (CROWDSEC_API_KEY); block is enforced per-request via proxy on the resolved X-Forwarded-For / CF-Connecting-IP
- tests: crowdsec-api unit suite + ddos-guard integration suite (early-block, threshold, cache dedupe, backoff)
This commit is contained in:
1 parent
64edb81ab7
commit
f32a6dadd0
9 files changed
+1414
-5
No files matched your search
+29
@@ -148,6 +148,35 @@ const schema = z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((value) => value !== "false" && value !== "0"),
|
||||
// CrowdSec API — optional. When the CTI API key is set, the anti-DDoS
|
||||
// gate consults the community reputation of repeat offenders (CTI
|
||||
// GET /smoke/{ip}) and hard-blocks known-bad IPs immediately. Like the
|
||||
// Cloudflare token, the key lives in env only and is never written into
|
||||
// the admin-visible config. Free/community key: app.crowdsec.net →
|
||||
// Settings → CTI API Keys.
|
||||
CROWDSEC_API_KEY: z.string().optional(),
|
||||
// Reputation lookup (CTI) endpoint; overridden for tests/staging.
|
||||
CROWDSEC_CTI_BASE_URL: z
|
||||
.string()
|
||||
.url()
|
||||
.default("https://cti.api.crowdsec.net/v2"),
|
||||
// Boot default for the runtime "auto-block from CrowdSec reputation"
|
||||
// toggle (overridable via the admin panel / antiddos:config).
|
||||
CROWDSEC_AUTO_BLOCK_ENABLED: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((value) => value !== "false" && value !== "0"),
|
||||
// Minimum malevolence score (CrowdSec scores are 0-5; 4-5 maps to
|
||||
// "malicious") an IP must reach before the gate treats it as known-bad.
|
||||
// An IP the community already labels "malicious" is always blocked,
|
||||
// unless it carries false-positive classification tags.
|
||||
CROWDSEC_BLOCK_SCORE: z.coerce.number().int().min(0).max(5).default(4),
|
||||
// How long a CrowdSec-confirmed bad IP stays blocked by the gate.
|
||||
CROWDSEC_BLOCK_TTL_SECONDS: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.positive()
|
||||
.default(86_400),
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
if (data.NODE_ENV !== "production") return;
|
||||
|
||||
Reference in new issue
Block a user