1.1.6: Migrate to .env, bugfixes
This commit is contained in:
parent
6fef5548e5
commit
140a142243
6 changed files with 74 additions and 44 deletions
37
.env.default
37
.env.default
|
|
@ -1,13 +1,40 @@
|
|||
# production or development
|
||||
NODE_ENV=production
|
||||
|
||||
# Cloudflare: https://dash.cloudflare.com/profile/api-tokens
|
||||
############################### TOKENS ###############################
|
||||
# Cloudflare (https://dash.cloudflare.com/profile/api-tokens)
|
||||
CLOUDFLARE_EMAIL=
|
||||
CLOUDFLARE_ZONE_ID=
|
||||
CLOUDFLARE_API_KEY=
|
||||
CLOUDFLARE_ZONE_ID=00000000000000000000000000000000
|
||||
CLOUDFLARE_API_KEY=0000000000000000000000000000000000000000
|
||||
|
||||
# AbuseIPDB: https://www.abuseipdb.com/account/api
|
||||
ABUSEIPDB_API_KEY=
|
||||
# AbuseIPDB (https://www.abuseipdb.com/account/api)
|
||||
ABUSEIPDB_API_KEY=00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
|
||||
# API key for api.sefinek.net. Contact me at contact@sefinek.net to obtain it and contribute to the sefinek24/Malicious-IP-Addresses. Leave empty if you don't have a token.
|
||||
SEFINEK_API_SECRET=
|
||||
|
||||
############################### CYCLES ###############################
|
||||
# Main interval (in minutes) of each cycle.
|
||||
CYCLE_INTERVAL=120
|
||||
|
||||
# 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.
|
||||
REPORTED_IP_COOLDOWN_MS=6
|
||||
|
||||
# The maximum URI length that can be reported to AbuseIPDB.
|
||||
# If Cloudflare returns a longer URI, the API request will fail.
|
||||
MAX_URL_LENGTH=920
|
||||
|
||||
# Additional delay (in seconds) after each successful IP report to avoid overloading the AbuseIPDB API.
|
||||
SUCCESS_COOLDOWN_MS=2
|
||||
|
||||
# Interval for refreshing your IP address (in minutes).
|
||||
# This ensures that WAF violations originating from your IP address are not reported to AbuseIPDB.
|
||||
IP_REFRESH_INTERVAL=80
|
||||
|
||||
############################### SEFINEK API ###############################
|
||||
# Report IP addresses to api.sefinek.net to support the development of the repository at https://github.com/sefinek24/Malicious-IP-Addresses. SEFINEK_API_SECRET is required if true.
|
||||
REPORT_TO_SEFINEK_API=true
|
||||
|
||||
# How often should the log (reported_ips.csv) be analyzed and sent to the Sefinek API? In minutes.
|
||||
SEFINEK_API_INTERVAL=60
|
||||
37
config.js
37
config.js
|
|
@ -1,26 +1,25 @@
|
|||
// Main interval of each cycle.
|
||||
// In production mode, it's 2 hours, and in development mode, it's 8 seconds.
|
||||
const CYCLE_INTERVAL = process.env.NODE_ENV === 'production' ? 2 * 60 * 60 * 1000 : 8 * 1000;
|
||||
const CYCLE_INTERVAL = process.env.NODE_ENV === 'production' ?
|
||||
parseInt(process.env.CYCLE_INTERVAL) * 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 = 6 * 60 * 60 * 1000; // 6h
|
||||
const REPORTED_IP_COOLDOWN_MS = parseInt(process.env.REPORTED_IP_COOLDOWN_MS) * 60 * 60 * 1000;
|
||||
|
||||
// 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 = 920;
|
||||
const MAX_URL_LENGTH = parseInt(process.env.MAX_URL_LENGTH);
|
||||
|
||||
// Additional delay after each successful IP report to avoid overloading the AbuseIPDB API.
|
||||
const SUCCESS_COOLDOWN_MS = 2 * 1000; // 2s
|
||||
const SUCCESS_COOLDOWN_MS = parseInt(process.env.SUCCESS_COOLDOWN_MS);
|
||||
|
||||
// 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 = 80 * 60 * 1000; // 80m
|
||||
const IP_REFRESH_INTERVAL = parseInt(process.env.IP_REFRESH_INTERVAL) * 60 * 1000;
|
||||
|
||||
// Report IP addresses to api.sefinek.net to support the development of the repository at https://github.com/sefinek24/Malicious-IP-Addresses. If true, please see the .env file.
|
||||
const REPORT_TO_SEFINEK_API = true;
|
||||
const REPORT_TO_SEFINEK_API = process.env.REPORT_TO_SEFINEK_API === 'true';
|
||||
|
||||
// How often should the log (reported_ips.csv) be analyzed and sent to the Sefinek API?
|
||||
const SEFINEK_API_INTERVAL = process.env.NODE_ENV === 'production' ? 60 * 60 * 1000 : 5 * 1000;
|
||||
const SEFINEK_API_INTERVAL = process.env.NODE_ENV === 'production' ?
|
||||
parseInt(process.env.SEFINEK_API_INTERVAL) * 60 * 1000 : 5 * 1000;
|
||||
|
||||
module.exports = { CYCLE_INTERVAL, REPORTED_IP_COOLDOWN_MS, MAX_URL_LENGTH, SUCCESS_COOLDOWN_MS, IP_REFRESH_INTERVAL, REPORT_TO_SEFINEK_API, SEFINEK_API_INTERVAL };
|
||||
module.exports = {
|
||||
CYCLE_INTERVAL,
|
||||
REPORTED_IP_COOLDOWN_MS,
|
||||
MAX_URL_LENGTH,
|
||||
SUCCESS_COOLDOWN_MS,
|
||||
IP_REFRESH_INTERVAL,
|
||||
REPORT_TO_SEFINEK_API,
|
||||
SEFINEK_API_INTERVAL
|
||||
};
|
||||
32
index.js
32
index.js
|
|
@ -30,16 +30,20 @@ const fetchBlockedIPs = async () => {
|
|||
};
|
||||
|
||||
const isIPReportedRecently = (rayId, ip, reportedIPs) => {
|
||||
const lastReport = reportedIPs.find(entry =>
|
||||
(entry.rayId === rayId || entry.ip === ip) &&
|
||||
(entry.action === 'REPORTED' || entry.action === 'TOO_MANY_REQUESTS')
|
||||
);
|
||||
const lastReport = reportedIPs.reduce((latest, entry) => {
|
||||
if (
|
||||
(entry.rayId === rayId || entry.ip === ip) &&
|
||||
(entry.status === 'TOO_MANY_REQUESTS' || entry.status === 'REPORTED') &&
|
||||
(!latest || entry.timestamp > latest.timestamp)
|
||||
) return entry;
|
||||
return latest;
|
||||
}, null);
|
||||
|
||||
if (lastReport) {
|
||||
const lastTimestamp = new Date(lastReport.timestamp).getTime();
|
||||
const currentTime = Date.now();
|
||||
const timeDifference = currentTime - lastTimestamp;
|
||||
if (timeDifference < REPORTED_IP_COOLDOWN_MS) return { recentlyReported: true, timeDifference };
|
||||
const timeDifference = Date.now() - lastReport.timestamp;
|
||||
if (timeDifference < REPORTED_IP_COOLDOWN_MS) {
|
||||
return { recentlyReported: true, timeDifference, reason: lastReport.status === 'TOO_MANY_REQUESTS' ? 'RATE-LIMITED' : 'REPORTED' };
|
||||
}
|
||||
}
|
||||
|
||||
return { recentlyReported: false };
|
||||
|
|
@ -96,7 +100,7 @@ const reportIP = async (event, country, hostname, endpoint, userAgent, cycleErro
|
|||
|
||||
// Sefinek API
|
||||
if (REPORT_TO_SEFINEK_API && SEFINEK_API_INTERVAL && process.env.SEFINEK_API_SECRET) {
|
||||
setInterval(async () => await SefinekAPI(), SEFINEK_API_INTERVAL);
|
||||
setInterval(SefinekAPI, SEFINEK_API_INTERVAL);
|
||||
}
|
||||
|
||||
// Ready
|
||||
|
|
@ -111,7 +115,7 @@ const reportIP = async (event, country, hostname, endpoint, userAgent, cycleErro
|
|||
// AbuseIPDB
|
||||
let cycleId = 1;
|
||||
while (true) {
|
||||
log('log', `===================== New Reporting Cycle (v${moduleVersion}) =====================`);
|
||||
log('log', `================ New Reporting Cycle v${moduleVersion}; ID: ${cycleId} ================`);
|
||||
|
||||
const blockedIPEvents = await fetchBlockedIPs();
|
||||
if (!blockedIPEvents) {
|
||||
|
|
@ -136,12 +140,13 @@ const reportIP = async (event, country, hostname, endpoint, userAgent, cycleErro
|
|||
}
|
||||
|
||||
const reportedIPs = readReportedIPs();
|
||||
const { recentlyReported, timeDifference } = isIPReportedRecently(event.rayName, ip, reportedIPs);
|
||||
const { recentlyReported, timeDifference, reason } = isIPReportedRecently(event.rayName, ip, reportedIPs);
|
||||
if (recentlyReported) {
|
||||
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('log', `${ip} was reported or rate-limited ${hoursAgo}h ${minutesAgo}m ${secondsAgo}s ago. Skipping...`);
|
||||
|
||||
log('log', `${ip} was ${reason} ${hoursAgo}h ${minutesAgo}m ${secondsAgo}s ago. Skipping...`);
|
||||
cycleSkippedCount++;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -164,7 +169,6 @@ const reportIP = async (event, country, hostname, endpoint, userAgent, cycleErro
|
|||
}
|
||||
}
|
||||
|
||||
log('log', `Cycle Summary [${cycleId}]:`);
|
||||
log('log', `- Reported IPs: ${cycleReportedCount}`);
|
||||
log('log', `- Total IPs processed: ${cycleProcessedCount}`);
|
||||
log('log', `- Skipped IPs: ${cycleSkippedCount}`);
|
||||
|
|
@ -172,7 +176,7 @@ const reportIP = async (event, country, hostname, endpoint, userAgent, cycleErro
|
|||
log('log', `- 429 Too Many Requests: ${cycleErrorCounts.blocked}`);
|
||||
log('log', `- No response errors: ${cycleErrorCounts.noResponse}`);
|
||||
log('log', `- Other errors: ${cycleErrorCounts.otherErrors}`);
|
||||
log('log', '==================== End of Reporting Cycle ====================');
|
||||
log('log', '===================== End of Reporting Cycle =====================');
|
||||
|
||||
log('log', `Waiting ${formatDelay(CYCLE_INTERVAL)}...`);
|
||||
cycleId++;
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "waf-to-abuseipdb",
|
||||
"version": "1.1.5",
|
||||
"version": "1.1.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "waf-to-abuseipdb",
|
||||
"version": "1.1.5",
|
||||
"version": "1.1.6",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.7",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "waf-to-abuseipdb",
|
||||
"version": "1.1.5",
|
||||
"version": "1.1.6",
|
||||
"description": "A Node.js project that enables automatic reporting of incidents detected by Cloudflare WAF to the AbuseIPDB database.",
|
||||
"keywords": [
|
||||
"abuseipdb",
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
"url": "git+https://github.com/sefinek24/Node-Cloudflare-WAF-AbuseIPDB.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": "Sefinek <contact@nekosia.cat> (https://sefinek.net)",
|
||||
"author": "Sefinek <contact@sefinek.net> (https://sefinek.net)",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const SEFINEK_API_URL = process.env.SEFINEK_API_URL || `${process.env.NODE_ENV =
|
|||
module.exports = async () => {
|
||||
const userIp = clientIp.getAddress();
|
||||
const reportedIPs = readReportedIPs().filter(x => x.status === 'REPORTED' && x.ip !== userIp && !x.sefinekAPI);
|
||||
if (reportedIPs.length === 0) return log('log', 'No IPs with `action Reported` and `SefinekAPI false` to send to Sefinek API');
|
||||
if (reportedIPs.length === 0) return;
|
||||
|
||||
const uniqueLogs = reportedIPs.reduce((acc, ip) => {
|
||||
if (acc.seen.has(ip.ip)) return acc;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue