feat(security): give back to CrowdSec and harden the CTI budget
Gitea Actions Runner Test / test-job (push) Successful in 0s
CI / check (push) Successful in 29s
CI / tests-integration (push) Successful in 1m34s
CI / tests-unit (push) Successful in 1m36s
CI / tests-ui (push) Successful in 2m22s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 1m53s
Gitea Actions Runner Test / test-job (push) Successful in 0s
CI / check (push) Successful in 29s
CI / tests-integration (push) Successful in 1m34s
CI / tests-unit (push) Successful in 1m36s
CI / tests-ui (push) Successful in 2m22s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 1m53s
- Bound the in-process verdict cache (FIFO eviction at 2000 entries) so a
flood of distinct bucket-tripping IPs cannot grow it without limit.
- Record block metadata (reputation, score, behaviors, category, TTL) in
antiddos:block:meta:{ip}, surfaced as the reason in the admin block list;
unban now also clears the metadata and report locks.
- Track daily CTI enrichment usage in Redis (crowdsec:usage:{date}); warn
once at 80% and pause lookups until tomorrow at CROWDSEC_CTI_DAILY_QUOTA
(default 10000, 0 = unlimited) so a via-spread DDoS cannot burn the plan.
- Add opt-in signal push to the CrowdSec community (CAPI watcher): stable
auto-generated 48-char machine_id/password pair persisted in Redis (or via
env), one-time registration, cached JWT login, optional Console enrollment,
and POST /v3/signals with a ban decision, deduped per IP. Never throws and
reports last status to the admin panel with a verify action.
- Admin page: quota usage bar, reporting status/verify channel, and CrowdSec
block reasons in the active-blocks list.
This commit is contained in:
1 parent
ee25545b7f
commit
5e4fc9ab59
8 files changed
+1323
-37
No files matched your search
@@ -19,6 +19,10 @@ import {
|
||||
setLastCrowdsecVerify,
|
||||
verifyCrowdsecConnection,
|
||||
} from "@/lib/crowdsec-api";
|
||||
import {
|
||||
setLastCrowdsecReport,
|
||||
verifyCrowdsecReporting,
|
||||
} from "@/lib/crowdsec-report";
|
||||
import { db, WebsiteSetting } from "@/lib/db";
|
||||
import { logger } from "@/lib/logger";
|
||||
import { PERMS } from "@/lib/permissions";
|
||||
@@ -223,6 +227,8 @@ export async function unbanAntiddosIp(formData: FormData): Promise<void> {
|
||||
if (redis) {
|
||||
await Promise.all([
|
||||
redis.del(`antiddos:block:${ip}`),
|
||||
redis.del(`antiddos:block:meta:${ip}`),
|
||||
redis.del(`crowdsec:report:${ip}`),
|
||||
redis.del(`antiddos:v:${ip}`),
|
||||
]);
|
||||
}
|
||||
@@ -272,6 +278,19 @@ export async function verifyCrowdsecConfiguration(): Promise<void> {
|
||||
revalidatePath("/admin/devops/antiddos");
|
||||
}
|
||||
|
||||
/** Test the CrowdSec signal-push (CAPI watcher) channel. */
|
||||
export async function verifyCrowdsecReportingConfiguration(): Promise<void> {
|
||||
const staff = await requirePermission(PERMS.SETTINGS_VIEW);
|
||||
const status = await verifyCrowdsecReporting();
|
||||
await setLastCrowdsecReport(status);
|
||||
logger.info("CrowdSec reporting configuration verified", {
|
||||
staff: staff.username,
|
||||
ok: status.ok,
|
||||
message: status.message,
|
||||
});
|
||||
revalidatePath("/admin/devops/antiddos");
|
||||
}
|
||||
|
||||
/** Test the configured Cloudflare API credentials against the zone. */
|
||||
export async function verifyCloudflareConfiguration(): Promise<void> {
|
||||
const staff = await requirePermission(PERMS.SETTINGS_VIEW);
|
||||
|
||||
Reference in new issue
Block a user