From 8f6dfc03d988f1257c086593255b8689811e1c31 Mon Sep 17 00:00:00 2001 From: Sefinek Date: Mon, 10 Mar 2025 20:31:56 +0100 Subject: [PATCH] REPORT_SCHEDULE --- config.default.js | 6 +-- index.js | 115 +++++++++++++++++++++++----------------------- package-lock.json | 29 ++++++++++++ package.json | 1 + 4 files changed, 91 insertions(+), 60 deletions(-) diff --git a/config.default.js b/config.default.js index 3fc62c7..437cdd3 100644 --- a/config.default.js +++ b/config.default.js @@ -7,8 +7,8 @@ exports.CONFIG = { }, CYCLES: { - // Main interval (in minutes) of each cycle - CYCLE_INTERVAL: 120 * 60 * 1000, + // Schedule for running cron jobs for reporting to AbuseIPDB. + REPORT_SCHEDULE: '0 */2 * * *', // The minimum time (in hours) that must pass after reporting an IP address before it can be reported again. // The required time is >= 15 minutes, according to AbuseIPDB API limits. @@ -19,7 +19,7 @@ exports.CONFIG = { MAX_URL_LENGTH: 780, // Additional delay (in milliseconds) after each successful IP report to avoid overloading the AbuseIPDB API. - SUCCESS_COOLDOWN: 30, + SUCCESS_COOLDOWN: 20, // Interval for refreshing your IP address (in minutes). // This ensures that WAF violations originating from your IP address are not reported to AbuseIPDB. diff --git a/index.js b/index.js index caf40a5..939b1d0 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,4 @@ +const { CronJob } = require('cron'); const axios = require('./services/axios.js'); const { CONFIG, GENERATE_COMMENT } = require('./config.js'); const PAYLOAD = require('./services/payload.js'); @@ -100,6 +101,61 @@ const reportIP = async (event, uri, country, hostname, endpoint, cycleErrorCount } }; +let cycleId = 1; + +const cron = async () => { + const whitelist = await getFilters(); + + log(0, `===================== Reporting Cycle No. ${cycleId} =====================`); + + const blockedIPEvents = await fetchBlockedIPs(whitelist); + if (!blockedIPEvents) return log(1, 'No events fetched, skipping cycle...'); + + const serverIP = fetchServerIP(); + if (!serverIP) log(1, `Server IP address is missing! Received: ${serverIP}`); + + let cycleProcessedCount = 0, cycleReportedCount = 0, cycleSkippedCount = 0; + const cycleErrorCounts = { blocked: 0, otherErrors: 0 }; + + for (const event of blockedIPEvents) { + cycleProcessedCount++; + const ip = event.clientIP; + if (ip === serverIP) { + log(0, `The IP address ${ip} belongs to this machine. Ignoring...`); + cycleSkippedCount++; + continue; + } + + if (whitelist.endpoints.includes(event.clientRequestPath)) { + log(0, `Skipping ${event.clientRequestPath}...`); + continue; + } + + const reportedIPs = readReportedIPs(); + const { recentlyReported } = isIPReportedRecently(event.rayName, ip, reportedIPs); + if (recentlyReported) { + cycleSkippedCount++; + continue; + } + + const wasReported = await reportIP(event, `${event.clientRequestHTTPHost}${event.clientRequestPath}`, event.clientCountryName, event.clientRequestHTTPHost, event.clientRequestPath, cycleErrorCounts); + if (wasReported) { + cycleReportedCount++; + await new Promise(resolve => setTimeout(resolve, CONFIG.CYCLES.SUCCESS_COOLDOWN)); + } + } + + log(0, `- Reported IPs: ${cycleReportedCount}`); + log(0, `- Total IPs processed: ${cycleProcessedCount}`); + log(0, `- Skipped IPs: ${cycleSkippedCount}`); + log(0, `- Rate-limits: ${cycleErrorCounts.blocked}`); + log(0, `- Other errors: ${cycleErrorCounts.otherErrors}`); + log(0, '===================== End of Reporting Cycle ====================='); + + cycleId++; + await new Promise(resolve => setTimeout(resolve)); +}; + (async () => { log(0, 'Loading data, please wait...'); @@ -113,61 +169,6 @@ const reportIP = async (event, uri, country, hostname, endpoint, cycleErrorCount process.send && process.send('ready'); // AbuseIPDB - let cycleId = 1; - while (true) { - const whitelist = await getFilters(); - - log(0, `===================== Reporting Cycle No. ${cycleId} =====================`); - - const blockedIPEvents = await fetchBlockedIPs(whitelist); - if (!blockedIPEvents) { - log(1, 'No events fetched, skipping cycle...'); - continue; - } - - const serverIP = fetchServerIP(); - if (!serverIP) log(1, `Server IP address is missing! Received: ${serverIP}`); - - let cycleProcessedCount = 0, cycleReportedCount = 0, cycleSkippedCount = 0; - const cycleErrorCounts = { blocked: 0, otherErrors: 0 }; - - for (const event of blockedIPEvents) { - cycleProcessedCount++; - const ip = event.clientIP; - if (ip === serverIP) { - log(0, `The IP address ${ip} belongs to this machine. Ignoring...`); - cycleSkippedCount++; - continue; - } - - if (whitelist.endpoints.includes(event.clientRequestPath)) { - log(0, `Skipping ${event.clientRequestPath}...`); - continue; - } - - const reportedIPs = readReportedIPs(); - const { recentlyReported } = isIPReportedRecently(event.rayName, ip, reportedIPs); - if (recentlyReported) { - cycleSkippedCount++; - continue; - } - - const wasReported = await reportIP(event, `${event.clientRequestHTTPHost}${event.clientRequestPath}`, event.clientCountryName, event.clientRequestHTTPHost, event.clientRequestPath, cycleErrorCounts); - if (wasReported) { - cycleReportedCount++; - await new Promise(resolve => setTimeout(resolve, CONFIG.CYCLES.SUCCESS_COOLDOWN)); - } - } - - log(0, `- Reported IPs: ${cycleReportedCount}`); - log(0, `- Total IPs processed: ${cycleProcessedCount}`); - log(0, `- Skipped IPs: ${cycleSkippedCount}`); - log(0, `- Rate-limits: ${cycleErrorCounts.blocked}`); - log(0, `- Other errors: ${cycleErrorCounts.otherErrors}`); - log(0, '===================== End of Reporting Cycle ====================='); - - log(0, `Waiting ${formatDelay(CONFIG.CYCLES.CYCLE_INTERVAL)} (${CONFIG.CYCLES.CYCLE_INTERVAL} ms)...`); - cycleId++; - await new Promise(resolve => setTimeout(resolve, CONFIG.CYCLES.CYCLE_INTERVAL)); - } + new CronJob(CONFIG.CYCLES.REPORT_SCHEDULE, cron, null, true, 'UTC'); + await cron(); })(); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9e4ec88..a30a599 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "axios": "^1.8.2", + "cron": "^4.1.0", "ipaddr.js": "^2.2.0" }, "devDependencies": { @@ -27,6 +28,12 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@types/luxon": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.2.tgz", + "integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==", + "license": "MIT" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -69,6 +76,19 @@ "node": ">= 0.8" } }, + "node_modules/cron": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cron/-/cron-4.1.0.tgz", + "integrity": "sha512-wmcuXr2qP0UZStYgwruG6jC2AYSO9n5VMm2t93hmcEXEjWY3S2bsXe3sfGUrTs/uQ1AvRCrZ0Pp9Q032L/V9tw==", + "license": "MIT", + "dependencies": { + "@types/luxon": "~3.4.0", + "luxon": "~3.5.0" + }, + "engines": { + "node": ">=18.x" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -291,6 +311,15 @@ "node": ">= 10" } }, + "node_modules/luxon": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", diff --git a/package.json b/package.json index 4b768ea..4c3c0a9 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ }, "dependencies": { "axios": "^1.8.2", + "cron": "^4.1.0", "ipaddr.js": "^2.2.0" }, "devDependencies": {