1.4.0: Added filters

This commit is contained in:
Sefinek 2025-02-13 02:57:23 +01:00
parent 5e1fb0d823
commit 443495d54b
5 changed files with 47 additions and 76 deletions

View file

@ -6,29 +6,32 @@ const headers = require('./utils/headers.js');
const { logToCSV, readReportedIPs } = require('./services/csv.js'); const { logToCSV, readReportedIPs } = require('./services/csv.js');
const formatDelay = require('./utils/formatDelay.js'); const formatDelay = require('./utils/formatDelay.js');
const fetchServerIP = require('./services/fetchServerIP.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 log = require('./utils/log.js');
const fetchBlockedIPs = async () => { const fetchBlockedIPs = async whitelist => {
try { try {
const { data, status } = await axios.post('https://api.cloudflare.com/client/v4/graphql', PAYLOAD(), { headers: headers.CLOUDFLARE }); 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; const events = data?.data?.viewer?.zones?.[0]?.firewallEventsAdaptive;
if (events) { if (!events) throw new Error(`Failed to retrieve data from Cloudflare (status ${status}): ${JSON.stringify(data?.errors)}`);
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))
);
log(0, `Fetched ${events.length} (filtered ${filtered.length}) events from Cloudflare`); 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; return filtered;
} else {
throw new Error(`Failed to retrieve data from Cloudflare (status ${status}); ${JSON.stringify(data?.errors)}`);
}
} catch (err) { } 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}`); log(2, err.response?.data
return null; ? `${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 // AbuseIPDB
let cycleId = 1; let cycleId = 1;
while (true) { while (true) {
const whitelist = await getFilters();
log(0, `===================== Reporting Cycle No. ${cycleId} =====================`); log(0, `===================== Reporting Cycle No. ${cycleId} =====================`);
const blockedIPEvents = await fetchBlockedIPs(); const blockedIPEvents = await fetchBlockedIPs(whitelist);
if (!blockedIPEvents) { if (!blockedIPEvents) {
log(1, 'No events fetched, skipping cycle...'); log(1, 'No events fetched, skipping cycle...');
continue; continue;
@ -136,13 +141,6 @@ const reportIP = async (event, uri, country, hostname, endpoint, cycleErrorCount
const reportedIPs = readReportedIPs(); const reportedIPs = readReportedIPs();
const { recentlyReported } = isIPReportedRecently(event.rayName, ip, reportedIPs); const { recentlyReported } = isIPReportedRecently(event.rayName, ip, reportedIPs);
if (recentlyReported) { 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++; cycleSkippedCount++;
continue; continue;
} }

20
package-lock.json generated
View file

@ -1,26 +1,26 @@
{ {
"name": "cf-waf-to-abuseipdb", "name": "cf-waf-to-abuseipdb",
"version": "1.3.1", "version": "1.4.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cf-waf-to-abuseipdb", "name": "cf-waf-to-abuseipdb",
"version": "1.3.1", "version": "1.4.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"axios": "^1.7.9", "axios": "^1.7.9",
"ipaddr.js": "^2.2.0" "ipaddr.js": "^2.2.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.19.0", "@eslint/js": "^9.20.0",
"globals": "^15.14.0" "globals": "^15.15.0"
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.19.0", "version": "9.20.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz",
"integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -100,9 +100,9 @@
} }
}, },
"node_modules/globals": { "node_modules/globals": {
"version": "15.14.0", "version": "15.15.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
"integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {

View file

@ -1,16 +1,7 @@
{ {
"name": "cf-waf-to-abuseipdb", "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.", "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", "homepage": "https://github.com/sefinek/Cloudflare-WAF-To-AbuseIPDB",
"bugs": { "bugs": {
"url": "https://github.com/sefinek/Cloudflare-WAF-To-AbuseIPDB/issues" "url": "https://github.com/sefinek/Cloudflare-WAF-To-AbuseIPDB/issues"
@ -32,7 +23,7 @@
"ipaddr.js": "^2.2.0" "ipaddr.js": "^2.2.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.19.0", "@eslint/js": "^9.20.0",
"globals": "^15.14.0" "globals": "^15.15.0"
} }
} }

11
services/getFilters.js Normal file
View file

@ -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);
}
};

View file

@ -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 };