From now on, the code will no longer report WAF violations originating from your IP address
This commit is contained in:
parent
b59265218d
commit
6f47f85547
6 changed files with 38 additions and 24 deletions
20
config.js
Normal file
20
config.js
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Main interval of each cycle.
|
||||||
|
// In production mode, it's 3 hours, and in development mode, it's 8 seconds.
|
||||||
|
const CYCLE_INTERVAL = process.env.NODE_ENV === 'production' ? 3 * 60 * 60 * 1000 : 8 * 1000;
|
||||||
|
|
||||||
|
// The minimum time 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.
|
||||||
|
const REPORTED_IP_COOLDOWN_MS = 7 * 60 * 60 * 1000; // 7h
|
||||||
|
|
||||||
|
// The maximum URI length that can be reported to AbuseIPDB.
|
||||||
|
// If Cloudflare returns a longer URI, the API request will fail.
|
||||||
|
const MAX_URL_LENGTH = 1000;
|
||||||
|
|
||||||
|
// Additional delay after each successful IP report to avoid overloading the AbuseIPDB API.
|
||||||
|
const SUCCESS_COOLDOWN_MS = 2 * 1000; // 2s
|
||||||
|
|
||||||
|
// Interval for refreshing your IP address.
|
||||||
|
// This ensures that WAF violations originating from your IP address are not reported to AbuseIPDB.
|
||||||
|
const IP_REFRESH_INTERVAL = 9 * 60 * 1000; // 9m
|
||||||
|
|
||||||
|
module.exports = { CYCLE_INTERVAL, REPORTED_IP_COOLDOWN_MS, MAX_URL_LENGTH, SUCCESS_COOLDOWN_MS, IP_REFRESH_INTERVAL };
|
||||||
24
index.js
24
index.js
|
|
@ -1,6 +1,7 @@
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
|
|
||||||
const { axios, moduleVersion } = require('./services/axios.js');
|
const { axios, moduleVersion } = require('./services/axios.js');
|
||||||
|
const { CYCLE_INTERVAL, REPORTED_IP_COOLDOWN_MS, MAX_URL_LENGTH, SUCCESS_COOLDOWN_MS } = require('./config.js');
|
||||||
const PAYLOAD = require('./scripts/payload.js');
|
const PAYLOAD = require('./scripts/payload.js');
|
||||||
const generateComment = require('./scripts/generateComment.js');
|
const generateComment = require('./scripts/generateComment.js');
|
||||||
const isImageRequest = require('./scripts/isImageRequest.js');
|
const isImageRequest = require('./scripts/isImageRequest.js');
|
||||||
|
|
@ -10,14 +11,6 @@ const formatDelay = require('./scripts/formatDelay.js');
|
||||||
const clientIp = require('./scripts/clientIp.js');
|
const clientIp = require('./scripts/clientIp.js');
|
||||||
const log = require('./scripts/log.js');
|
const log = require('./scripts/log.js');
|
||||||
|
|
||||||
const MAIN_DELAY = process.env.NODE_ENV === 'production'
|
|
||||||
? 3 * 60 * 60 * 1000
|
|
||||||
: 8 * 1000;
|
|
||||||
|
|
||||||
const REPORTED_IP_COOLDOWN_MS = 7 * 60 * 60 * 1000;
|
|
||||||
const COOLDOWN_MS = 2000;
|
|
||||||
const MAX_URL_LENGTH = 2000;
|
|
||||||
|
|
||||||
const fetchBlockedIPs = async () => {
|
const fetchBlockedIPs = async () => {
|
||||||
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 });
|
||||||
|
|
@ -56,7 +49,7 @@ const reportIP = async (event, url, country, cycleErrorCounts) => {
|
||||||
|
|
||||||
if (event.clientIP === clientIp.address) {
|
if (event.clientIP === clientIp.address) {
|
||||||
logToCSV(event.rayName, event.clientIP, url, 'Your IP address', country);
|
logToCSV(event.rayName, event.clientIP, url, 'Your IP address', country);
|
||||||
log('warn', `Your IP address (${event.clientIP}) was unexpectedly received from Cloudflare. URI: ${url}; Ignoring...`);
|
log('log', `Your IP address (${event.clientIP}) was unexpectedly received from Cloudflare. URI: ${url}; Ignoring...`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,10 +93,10 @@ const reportIP = async (event, url, country, cycleErrorCounts) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log('info', 'Starting, please wait...');
|
log('info', 'Loading data, please wait...');
|
||||||
await clientIp.fetchIPAddress();
|
await clientIp.fetchIPAddress();
|
||||||
let cycleId = 1;
|
|
||||||
|
|
||||||
|
let cycleId = 1;
|
||||||
while (true) {
|
while (true) {
|
||||||
log('info', `===================== New Reporting Cycle (v${moduleVersion}) =====================`);
|
log('info', `===================== New Reporting Cycle (v${moduleVersion}) =====================`);
|
||||||
|
|
||||||
|
|
@ -113,6 +106,9 @@ const reportIP = async (event, url, country, cycleErrorCounts) => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userIp = clientIp.getAddress();
|
||||||
|
if (!userIp) log('warn', `Your IP address is missing! Received: ${userIp}`);
|
||||||
|
|
||||||
const reportedIPs = readReportedIPs();
|
const reportedIPs = readReportedIPs();
|
||||||
let cycleImageSkippedCount = 0, cycleProcessedCount = 0, cycleReportedCount = 0, cycleSkippedCount = 0;
|
let cycleImageSkippedCount = 0, cycleProcessedCount = 0, cycleReportedCount = 0, cycleSkippedCount = 0;
|
||||||
const cycleErrorCounts = { blocked: 0, noResponse: 0, otherErrors: 0 };
|
const cycleErrorCounts = { blocked: 0, noResponse: 0, otherErrors: 0 };
|
||||||
|
|
@ -150,7 +146,7 @@ const reportIP = async (event, url, country, cycleErrorCounts) => {
|
||||||
const wasReported = await reportIP(event, url, country, cycleErrorCounts);
|
const wasReported = await reportIP(event, url, country, cycleErrorCounts);
|
||||||
if (wasReported) {
|
if (wasReported) {
|
||||||
cycleReportedCount++;
|
cycleReportedCount++;
|
||||||
await new Promise(resolve => setTimeout(resolve, COOLDOWN_MS));
|
await new Promise(resolve => setTimeout(resolve, SUCCESS_COOLDOWN_MS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,8 +160,8 @@ const reportIP = async (event, url, country, cycleErrorCounts) => {
|
||||||
log('info', `- Other errors: ${cycleErrorCounts.otherErrors}`);
|
log('info', `- Other errors: ${cycleErrorCounts.otherErrors}`);
|
||||||
log('info', '==================== End of Reporting Cycle ====================');
|
log('info', '==================== End of Reporting Cycle ====================');
|
||||||
|
|
||||||
log('info', `Waiting ${formatDelay(MAIN_DELAY)}...`);
|
log('info', `Waiting ${formatDelay(CYCLE_INTERVAL)}...`);
|
||||||
cycleId++;
|
cycleId++;
|
||||||
await new Promise(resolve => setTimeout(resolve, MAIN_DELAY));
|
await new Promise(resolve => setTimeout(resolve, CYCLE_INTERVAL));
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "cf-waf-to-abuseipdb",
|
"name": "cf-waf-to-abuseipdb",
|
||||||
"version": "1.0.1",
|
"version": "1.1.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cf-waf-to-abuseipdb",
|
"name": "cf-waf-to-abuseipdb",
|
||||||
"version": "1.0.1",
|
"version": "1.1.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cf-waf-to-abuseipdb",
|
"name": "cf-waf-to-abuseipdb",
|
||||||
"version": "1.0.1",
|
"version": "1.1.0",
|
||||||
"description": "A Node.js project that enables automatic reporting of incidents detected by Cloudflare WAF to the AbuseIPDB database.",
|
"description": "A Node.js project that enables automatic reporting of incidents detected by Cloudflare WAF to the AbuseIPDB database.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"abuseipdb",
|
"abuseipdb",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
const { axios } = require('../services/axios.js');
|
const { axios } = require('../services/axios.js');
|
||||||
|
const { IP_REFRESH_INTERVAL } = require('../config.js');
|
||||||
const log = require('./log.js');
|
const log = require('./log.js');
|
||||||
|
|
||||||
let address = null; // Holds the IP address
|
let address = null; // Holds the IP address
|
||||||
const refreshInterval = 360000; // 6 minutes
|
|
||||||
|
|
||||||
const fetchIPAddress = async () => {
|
const fetchIPAddress = async () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -17,6 +17,7 @@ const fetchIPAddress = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setInterval(fetchIPAddress, refreshInterval);
|
|
||||||
|
|
||||||
module.exports = { fetchIPAddress, address };
|
setInterval(fetchIPAddress, IP_REFRESH_INTERVAL);
|
||||||
|
|
||||||
|
module.exports = { fetchIPAddress, getAddress: () => address };
|
||||||
|
|
@ -4,7 +4,4 @@ const levels = {
|
||||||
error: '[FAIL]'
|
error: '[FAIL]'
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = (level, message) => {
|
module.exports = (level, msg) => console[level](`${levels[level]} ${msg}`);
|
||||||
const timestamp = process.env.NODE_ENV === 'development' ? `${new Date().toISOString()}: ` : '';
|
|
||||||
console[level](`${levels[level]} ${timestamp}${message}`);
|
|
||||||
};
|
|
||||||
Loading…
Add table
Reference in a new issue