From 443495d54bc15f7fbf36b6cc174170b303f949c8 Mon Sep 17 00:00:00 2001 From: Sefinek Date: Thu, 13 Feb 2025 02:57:23 +0100 Subject: [PATCH] 1.4.0: Added filters --- index.js | 48 ++++++++++++++++++++---------------------- package-lock.json | 20 +++++++++--------- package.json | 15 +++---------- services/getFilters.js | 11 ++++++++++ utils/whitelist.js | 29 ------------------------- 5 files changed, 47 insertions(+), 76 deletions(-) create mode 100644 services/getFilters.js delete mode 100644 utils/whitelist.js diff --git a/index.js b/index.js index f7f6dd9..8e0e406 100644 --- a/index.js +++ b/index.js @@ -6,29 +6,32 @@ const headers = require('./utils/headers.js'); const { logToCSV, readReportedIPs } = require('./services/csv.js'); const formatDelay = require('./utils/formatDelay.js'); const fetchServerIP = require('./services/fetchServerIP.js'); -const whitelist = require('./utils/whitelist.js'); +const getFilters = require('./services/getFilters.js'); const log = require('./utils/log.js'); -const fetchBlockedIPs = async () => { +const fetchBlockedIPs = async whitelist => { try { const { data, status } = await axios.post('https://api.cloudflare.com/client/v4/graphql', PAYLOAD(), { headers: headers.CLOUDFLARE }); - const events = data?.data?.viewer?.zones[0]?.firewallEventsAdaptive; - if (events) { - const filtered = events.filter(x => - x.ip !== fetchServerIP() && - !whitelist.imgExtensions.some(ext => x.clientRequestPath.endsWith(ext)) && - !whitelist.domains.some(subdomain => x.clientRequestHTTPHost?.includes(subdomain)) && - !whitelist.endpoints.some(endpoint => x.clientRequestPath?.includes(endpoint)) - ); + const events = data?.data?.viewer?.zones?.[0]?.firewallEventsAdaptive; + if (!events) throw new Error(`Failed to retrieve data from Cloudflare (status ${status}): ${JSON.stringify(data?.errors)}`); - log(0, `Fetched ${events.length} (filtered ${filtered.length}) events from Cloudflare`); - return filtered; - } else { - throw new Error(`Failed to retrieve data from Cloudflare (status ${status}); ${JSON.stringify(data?.errors)}`); - } + const isWhitelisted = event => + event.ip === fetchServerIP() || + whitelist.userAgents.some(ua => event.userAgent.includes(ua)) || + whitelist.imgExtensions.some(ext => event.clientRequestPath.endsWith(ext)) || + whitelist.domains.some(domain => event.clientRequestHTTPHost?.includes(domain)) || + whitelist.endpoints.some(endpoint => event.clientRequestPath?.includes(endpoint)); + + const filtered = events.filter(event => !isWhitelisted(event)); + + log(0, `Fetched ${events.length} events (filtered ${filtered.length}) from Cloudflare`); + return filtered; } catch (err) { - log(2, err.response?.data ? `${err.response.status} HTTP ERROR Cloudflare API: ${JSON.stringify(err.response.data, null, 2)}` : `Unknown error with Cloudflare API: ${err.message}`); - return null; + log(2, err.response?.data + ? `${err.response.status} HTTP ERROR Cloudflare API: ${JSON.stringify(err.response.data, null, 2)}` + : `Unknown error with Cloudflare API: ${err.message}` + ); + return []; } }; @@ -108,9 +111,11 @@ const reportIP = async (event, uri, country, hostname, endpoint, cycleErrorCount // AbuseIPDB let cycleId = 1; while (true) { + const whitelist = await getFilters(); + log(0, `===================== Reporting Cycle No. ${cycleId} =====================`); - const blockedIPEvents = await fetchBlockedIPs(); + const blockedIPEvents = await fetchBlockedIPs(whitelist); if (!blockedIPEvents) { log(1, 'No events fetched, skipping cycle...'); continue; @@ -136,13 +141,6 @@ const reportIP = async (event, uri, country, hostname, endpoint, cycleErrorCount const reportedIPs = readReportedIPs(); const { recentlyReported } = isIPReportedRecently(event.rayName, ip, reportedIPs); if (recentlyReported) { - // if (MAIN.NODE_ENV === 'development') { - // const hoursAgo = Math.floor(timeDifference / (1000 * 60 * 60)); - // const minutesAgo = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60)); - // const secondsAgo = Math.floor((timeDifference % (1000 * 60)) / 1000); - // log(0, `${ip} was ${reason} ${hoursAgo}h ${minutesAgo}m ${secondsAgo}s ago. Skipping...`); - // } - cycleSkippedCount++; continue; } diff --git a/package-lock.json b/package-lock.json index ca082ca..02a2f62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,26 +1,26 @@ { "name": "cf-waf-to-abuseipdb", - "version": "1.3.1", + "version": "1.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cf-waf-to-abuseipdb", - "version": "1.3.1", + "version": "1.4.0", "license": "MIT", "dependencies": { "axios": "^1.7.9", "ipaddr.js": "^2.2.0" }, "devDependencies": { - "@eslint/js": "^9.19.0", - "globals": "^15.14.0" + "@eslint/js": "^9.20.0", + "globals": "^15.15.0" } }, "node_modules/@eslint/js": { - "version": "9.19.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", - "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", + "version": "9.20.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz", + "integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==", "dev": true, "license": "MIT", "engines": { @@ -100,9 +100,9 @@ } }, "node_modules/globals": { - "version": "15.14.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", - "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index d1844f9..c3f5222 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,7 @@ { "name": "cf-waf-to-abuseipdb", - "version": "1.3.1", + "version": "1.4.0", "description": "Node.js script for automatically reporting incidents to AbuseIPDB using data obtained from Cloudflare WAF.", - "keywords": [ - "abuseipdb", - "cloudflare", - "cloudflare waf", - "waf", - "reporting", - "abuseipdb reporting", - "node abuseipdb" - ], "homepage": "https://github.com/sefinek/Cloudflare-WAF-To-AbuseIPDB", "bugs": { "url": "https://github.com/sefinek/Cloudflare-WAF-To-AbuseIPDB/issues" @@ -32,7 +23,7 @@ "ipaddr.js": "^2.2.0" }, "devDependencies": { - "@eslint/js": "^9.19.0", - "globals": "^15.14.0" + "@eslint/js": "^9.20.0", + "globals": "^15.15.0" } } diff --git a/services/getFilters.js b/services/getFilters.js new file mode 100644 index 0000000..78c65b5 --- /dev/null +++ b/services/getFilters.js @@ -0,0 +1,11 @@ +const axios = require('./axios.js'); + +module.exports = async () => { + try { + const res = await axios.get('https://api.sefinek.net/api/v2/filter-rules'); + if (!res.data.success) throw new Error('Sefinek API Error'); + return { userAgents: res.data.userAgents, domains: res.data.domains, endpoints: res.data.endpoints, imgExtensions: res.data.imgExtensions }; + } catch (err) { + throw new Error(err); + } +}; \ No newline at end of file diff --git a/utils/whitelist.js b/utils/whitelist.js deleted file mode 100644 index a06bde5..0000000 --- a/utils/whitelist.js +++ /dev/null @@ -1,29 +0,0 @@ -const domains = [ - 'api.', - 'cdn.', - 'static.', - 'assets.', - 'media.', - 'auth.', - 'files.', - 'blocklist.sefinek.net', - 'bucket.sefinek.net', -]; - -const endpoints = [ - 'favicon.ico', - 'favicon.png', - 'sitemap.xml', - 'robots.txt', - 'ads.txt', - 'security.txt', - 'humans.txt', - 'manifest.json', - 'apple-touch-icon.png', - 'crossdomain.xml', - 'site.webmanifest', -]; - -const imgExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.svg', '.webp']; - -module.exports = { domains, endpoints, imgExtensions }; \ No newline at end of file