From 78371e847d2e1aab532290ff93beafef725345b4 Mon Sep 17 00:00:00 2001 From: Juraj Uhlar Date: Thu, 21 Dec 2023 15:01:28 +0100 Subject: [PATCH] chore: refactor and clean up --- .gitignore | 3 +++ src/pages/api/bot-firewall/block-bot-ip.ts | 18 +++++++++++++++--- src/pages/api/bot-firewall/get-blocked-ips.ts | 2 +- src/server/botd-firewall/updateFirewallRule.ts | 8 +++++--- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index b4fa38bf..d24e63aa 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ tsconfig.tsbuildinfo # MacOS Finder .DS_Store + +# Local experiments +.scratchpad/* diff --git a/src/pages/api/bot-firewall/block-bot-ip.ts b/src/pages/api/bot-firewall/block-bot-ip.ts index c252b3e3..2d52858f 100644 --- a/src/pages/api/bot-firewall/block-bot-ip.ts +++ b/src/pages/api/bot-firewall/block-bot-ip.ts @@ -1,6 +1,10 @@ import { NextApiRequest, NextApiResponse } from 'next'; import { deleteBlockedIp, saveBlockedIp } from '../../../server/botd-firewall/saveBlockedIp'; -import { syncCloudflareBotFirewallRule } from '../../../server/botd-firewall/updateFirewallRule'; +import { + buildFirewallRules, + getBlockedIps, + updateFirewallRuleset as updateCloudflareRuleset, +} from '../../../server/botd-firewall/updateFirewallRule'; import { FingerprintJsServerApiClient, isEventError } from '@fingerprintjs/fingerprintjs-pro-server-api'; import { ALLOWED_REQUEST_TIMESTAMP_DIFF_MS, BACKEND_REGION, SERVER_API_KEY } from '../../../server/const'; import { ensurePostRequest } from '../../../server/server'; @@ -27,23 +31,31 @@ export default async function blockIp(req: NextApiRequest, res: NextApiResponse) return; } + // Validate block/unblock request const { ip, blocked, requestId } = req.body as BlockIpPayload; - const { okay, message } = await validateBlockIpRequest(requestId, ip, req); if (!okay) { return res.status(403).json({ result: 'error', message } satisfies BlockIpResponse); } try { + // Save or remove blocked IP from database if (blocked) { await saveBlockedIp(ip); } else { await deleteBlockedIp(ip); } - await syncCloudflareBotFirewallRule(); + + // Construct updated firewall rules from the blocked IP database and apply them to your Cloudflare application + const blockedIps = await getBlockedIps(); + const newRules = await buildFirewallRules(blockedIps); + console.log(JSON.stringify(await updateCloudflareRuleset(newRules), null, 2)); + + // Return success return res.status(200).json({ result: 'success', message: 'OK', ip, blocked } satisfies BlockIpResponse); } catch (error) { console.log(error); + // Catch unexpected errors and return 500 to the client return res.status(500).json({ result: 'error', message: 'Internal server error.' } satisfies BlockIpResponse); } } diff --git a/src/pages/api/bot-firewall/get-blocked-ips.ts b/src/pages/api/bot-firewall/get-blocked-ips.ts index 3c127506..f1f4dbac 100644 --- a/src/pages/api/bot-firewall/get-blocked-ips.ts +++ b/src/pages/api/bot-firewall/get-blocked-ips.ts @@ -1,7 +1,7 @@ import { NextApiRequest, NextApiResponse } from 'next'; import { BlockedIp, BlockedIpDbModel } from '../../../server/botd-firewall/saveBlockedIp'; -export default async function getBlockedIps(req: NextApiRequest, res: NextApiResponse) { +export default async function handler(req: NextApiRequest, res: NextApiResponse) { const blockedIps = await BlockedIpDbModel.findAll(); res.status(200).json(blockedIps); } diff --git a/src/server/botd-firewall/updateFirewallRule.ts b/src/server/botd-firewall/updateFirewallRule.ts index 818b3ade..92bd2e35 100644 --- a/src/server/botd-firewall/updateFirewallRule.ts +++ b/src/server/botd-firewall/updateFirewallRule.ts @@ -16,19 +16,21 @@ const MAX_IPS_PER_RULE = 84; const MAX_RULES = 5; const MAX_IPS = MAX_IPS_PER_RULE * MAX_RULES; // 420 -export const getFirewallRules = async (): Promise => { - // Get the list of blocked IPs from the database +export const getBlockedIps = async (): Promise => { const blockedIps = await BlockedIpDbModel.findAll({ order: [['timestamp', 'DESC']], limit: MAX_IPS, }); + return blockedIps.map((ip) => ip.ip); +}; +export const buildFirewallRules = async (blockedIps: string[]): Promise => { // Split the list of blocked IPs into chunks of MAX_IPS_PER_RULE length const chunks = chunk(blockedIps, MAX_IPS_PER_RULE); // Build the rule expression for each chunk const ruleExpressions = chunks.map((chunk) => { - const ipList = chunk.map((ip) => `"${ip.ip}"`).join(' '); + const ipList = chunk.map((ip) => `"${ip}"`).join(' '); return `http.x_forwarded_for in {${ipList}}`; });