Bug fixes (1.1.1)
This commit is contained in:
parent
d8765975f3
commit
a3d7869877
5 changed files with 32 additions and 32 deletions
18
index.js
18
index.js
|
|
@ -30,7 +30,7 @@ const fetchBlockedIPs = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const isIPReportedRecently = (ip, reportedIPs) => {
|
const isIPReportedRecently = (ip, reportedIPs) => {
|
||||||
const lastReport = reportedIPs.find(entry => entry.ip === ip && (entry.action === 'Reported' || entry.action.startsWith('Failed')));
|
const lastReport = reportedIPs.find(entry => entry.ip === ip && (entry.action === 'REPORTED' || entry.action.startsWith('TOO_MANY_REQUESTS')));
|
||||||
if (lastReport) {
|
if (lastReport) {
|
||||||
const lastTimestamp = new Date(lastReport.timestamp).getTime();
|
const lastTimestamp = new Date(lastReport.timestamp).getTime();
|
||||||
const currentTime = Date.now();
|
const currentTime = Date.now();
|
||||||
|
|
@ -41,23 +41,23 @@ const isIPReportedRecently = (ip, reportedIPs) => {
|
||||||
return { recentlyReported: false };
|
return { recentlyReported: false };
|
||||||
};
|
};
|
||||||
|
|
||||||
const reportIP = async (event, hostname, endpoint, userAgent, country, cycleErrorCounts) => {
|
const reportIP = async (event, country, hostname, endpoint, userAgent, cycleErrorCounts) => {
|
||||||
const uri = `${hostname}${endpoint}`;
|
const uri = `${hostname}${endpoint}`;
|
||||||
|
|
||||||
if (!uri) {
|
if (!uri) {
|
||||||
logToCSV(event.rayName, event.clientIP, hostname, endpoint, event.userAgent, 'Failed - Missing URL', country);
|
logToCSV(event.rayName, event.clientIP, country, hostname, endpoint, event.userAgent, 'MISSING_URI');
|
||||||
log('warn', `Missing URL ${event.clientIP}; URI: ${uri}`);
|
log('warn', `Missing URL ${event.clientIP}; URI: ${uri}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.clientIP === clientIp.address) {
|
if (event.clientIP === clientIp.address) {
|
||||||
logToCSV(event.rayName, event.clientIP, hostname, endpoint, event.userAgent, 'Your IP address', country);
|
logToCSV(event.rayName, event.clientIP, country, hostname, endpoint, event.userAgent, 'YOUR_IP_ADDRESS');
|
||||||
log('log', `Your IP address (${event.clientIP}) was unexpectedly received from Cloudflare. URI: ${uri}; Ignoring...`);
|
log('log', `Your IP address (${event.clientIP}) was unexpectedly received from Cloudflare. URI: ${uri}; Ignoring...`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uri.length > MAX_URL_LENGTH) {
|
if (uri.length > MAX_URL_LENGTH) {
|
||||||
logToCSV(event.rayName, event.clientIP, hostname, endpoint, event.userAgent, 'Failed - URL too long', country);
|
logToCSV(event.rayName, event.clientIP, country, hostname, endpoint, event.userAgent, 'URI_TOO_LONG');
|
||||||
log('log', `URL too long ${event.clientIP}; URI: ${uri}`);
|
log('log', `URL too long ${event.clientIP}; URI: ${uri}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -69,13 +69,13 @@ const reportIP = async (event, hostname, endpoint, userAgent, country, cycleErro
|
||||||
comment: generateComment(event)
|
comment: generateComment(event)
|
||||||
}, { headers: headers.ABUSEIPDB });
|
}, { headers: headers.ABUSEIPDB });
|
||||||
|
|
||||||
logToCSV(event.rayName, event.clientIP, hostname, endpoint, event.userAgent, 'Reported', country);
|
logToCSV(event.rayName, event.clientIP, country, hostname, endpoint, event.userAgent, 'REPORTED');
|
||||||
log('log', `Reported ${event.clientIP}; URI: ${uri}`);
|
log('log', `Reported ${event.clientIP}; URI: ${uri}`);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.response?.status === 429) {
|
if (err.response?.status === 429) {
|
||||||
logToCSV(event.rayName, event.clientIP, hostname, endpoint, event.userAgent, 'Failed - 429 Too Many Requests', country);
|
logToCSV(event.rayName, event.clientIP, country, hostname, endpoint, event.userAgent, 'TOO_MANY_REQUESTS');
|
||||||
log('log', `Rate limited (429) while reporting ${event.clientIP}; URI: ${uri}`);
|
log('log', `Rate limited (429) while reporting ${event.clientIP}; URI: ${uri}`);
|
||||||
cycleErrorCounts.blocked++;
|
cycleErrorCounts.blocked++;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -143,7 +143,7 @@ const reportIP = async (event, hostname, endpoint, userAgent, country, cycleErro
|
||||||
if (isImageRequest(event.clientRequestPath)) {
|
if (isImageRequest(event.clientRequestPath)) {
|
||||||
cycleImageSkippedCount++;
|
cycleImageSkippedCount++;
|
||||||
if (!wasImageRequestLogged(ip, reportedIPs)) {
|
if (!wasImageRequestLogged(ip, reportedIPs)) {
|
||||||
logToCSV(event.rayName, ip, hostname, endpoint, null, 'Skipped - Image Request', country);
|
logToCSV(event.rayName, ip, country, hostname, endpoint, null, 'SKIPPED_IMAGE_REQUEST');
|
||||||
|
|
||||||
if (imageRequestLogged) continue;
|
if (imageRequestLogged) continue;
|
||||||
log('log', 'Skipping image requests in this cycle...');
|
log('log', 'Skipping image requests in this cycle...');
|
||||||
|
|
@ -153,7 +153,7 @@ const reportIP = async (event, hostname, endpoint, userAgent, country, cycleErro
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wasReported = await reportIP(event, hostname, endpoint, event.userAgent, country, cycleErrorCounts);
|
const wasReported = await reportIP(event, country, hostname, endpoint, event.userAgent, cycleErrorCounts);
|
||||||
if (wasReported) {
|
if (wasReported) {
|
||||||
cycleReportedCount++;
|
cycleReportedCount++;
|
||||||
await new Promise(resolve => setTimeout(resolve, SUCCESS_COOLDOWN_MS));
|
await new Promise(resolve => setTimeout(resolve, SUCCESS_COOLDOWN_MS));
|
||||||
|
|
|
||||||
18
package-lock.json
generated
18
package-lock.json
generated
|
|
@ -1,26 +1,26 @@
|
||||||
{
|
{
|
||||||
"name": "cf-waf-to-abuseipdb",
|
"name": "cf-waf-to-abuseipdb",
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cf-waf-to-abuseipdb",
|
"name": "cf-waf-to-abuseipdb",
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"dotenv": "^16.4.5"
|
"dotenv": "^16.4.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.9.1",
|
"@eslint/js": "^9.10.0",
|
||||||
"globals": "^15.9.0"
|
"globals": "^15.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.9.1",
|
"version": "9.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz",
|
||||||
"integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==",
|
"integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -78,9 +78,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.8",
|
"version": "1.15.9",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.8.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||||
"integrity": "sha512-xgrmBhBToVKay1q2Tao5LI26B83UhrB/vM1avwVSDzt8rx3rO6AizBAaF46EgksTVr+rFTQaqZZ9MVBfUe4nig==",
|
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cf-waf-to-abuseipdb",
|
"name": "cf-waf-to-abuseipdb",
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"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",
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
"dotenv": "^16.4.5"
|
"dotenv": "^16.4.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.9.1",
|
"@eslint/js": "^9.10.0",
|
||||||
"globals": "^15.9.0"
|
"globals": "^15.9.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ const log = require('./log.js');
|
||||||
|
|
||||||
const CSV_FILE_PATH = path.join(__dirname, '..', 'reported_ips.csv');
|
const CSV_FILE_PATH = path.join(__dirname, '..', 'reported_ips.csv');
|
||||||
const MAX_CSV_SIZE_BYTES = 4 * 1024 * 1024; // 4 MB
|
const MAX_CSV_SIZE_BYTES = 4 * 1024 * 1024; // 4 MB
|
||||||
const CSV_HEADER = 'Timestamp,RayID,IP,Hostname,Endpoint,User-Agent,Action,Country,SefinekAPI\n';
|
const CSV_HEADER = 'Timestamp,CF RayID,IP,Country,Hostname,Endpoint,User-Agent,Action,SefinekAPI\n';
|
||||||
|
|
||||||
if (!fs.existsSync(CSV_FILE_PATH)) fs.writeFileSync(CSV_FILE_PATH, CSV_HEADER);
|
if (!fs.existsSync(CSV_FILE_PATH)) fs.writeFileSync(CSV_FILE_PATH, CSV_HEADER);
|
||||||
|
|
||||||
|
|
@ -21,9 +21,9 @@ const escapeCSVValue = value => {
|
||||||
return value || '';
|
return value || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
const logToCSV = (rayId, ip, hostname, endpoint, useragent, action, country, sefinekAPI) => {
|
const logToCSV = (rayId, ip, country, hostname, endpoint, useragent, action, sefinekAPI) => {
|
||||||
checkCSVSize();
|
checkCSVSize();
|
||||||
const logLine = `${new Date().toISOString()},${rayId},${ip},${hostname},${escapeCSVValue(endpoint)},${escapeCSVValue(useragent)},${action},${country || 'N/A'},${sefinekAPI || false}`;
|
const logLine = `${new Date().toISOString()},${rayId},${ip},${country || 'N/A'},${hostname},${escapeCSVValue(endpoint)},${escapeCSVValue(useragent)},${action},${sefinekAPI || false}`;
|
||||||
fs.appendFileSync(CSV_FILE_PATH, logLine + '\n');
|
fs.appendFileSync(CSV_FILE_PATH, logLine + '\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -36,18 +36,18 @@ const readReportedIPs = () => {
|
||||||
.slice(1)
|
.slice(1)
|
||||||
.filter(line => line.trim() !== '')
|
.filter(line => line.trim() !== '')
|
||||||
.map(line => {
|
.map(line => {
|
||||||
const parts = line.match(/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g);
|
const parts = line.match(/(".*?"|[^",]+)(?=\s*,|\s*$)/g);
|
||||||
if (!parts || parts.length < 9) return null;
|
if (!parts || parts.length < 9) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
timestamp: new Date(parts[0]),
|
timestamp: new Date(parts[0]),
|
||||||
rayId: parts[1],
|
rayId: parts[1],
|
||||||
ip: parts[2],
|
ip: parts[2],
|
||||||
hostname: parts[3],
|
country: parts[3],
|
||||||
endpoint: parts[4],
|
hostname: parts[4],
|
||||||
useragent: parts[5],
|
endpoint: parts[5],
|
||||||
action: parts[6],
|
useragent: parts[6].replace(/(^"|"$)/g, ''),
|
||||||
country: parts[7],
|
action: parts[7],
|
||||||
sefinekAPI: parts[8]
|
sefinekAPI: parts[8]
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
@ -75,6 +75,6 @@ const updateSefinekAPIInCSV = (rayId, reportedToSefinekAPI) => {
|
||||||
fs.writeFileSync(CSV_FILE_PATH, updatedLines.join('\n'));
|
fs.writeFileSync(CSV_FILE_PATH, updatedLines.join('\n'));
|
||||||
};
|
};
|
||||||
|
|
||||||
const wasImageRequestLogged = (ip, reportedIPs) => reportedIPs.some(entry => entry.ip === ip && entry.action === 'Skipped - Image Request');
|
const wasImageRequestLogged = (ip, reportedIPs) => reportedIPs.some(entry => entry.ip === ip && entry.action === 'SKIPPED_IMAGE_REQUEST');
|
||||||
|
|
||||||
module.exports = { logToCSV, readReportedIPs, updateSefinekAPIInCSV, wasImageRequestLogged };
|
module.exports = { logToCSV, readReportedIPs, updateSefinekAPIInCSV, wasImageRequestLogged };
|
||||||
|
|
@ -5,8 +5,8 @@ const log = require('./log.js');
|
||||||
const SEFINEK_API_URL = process.env.SEFINEK_API_URL || `${process.env.NODE_ENV === 'production' ? 'https://api.sefinek.net' : 'http://127.0.0.1:4010'}/api/v2/cloudflare-waf-abuseipdb/post`;
|
const SEFINEK_API_URL = process.env.SEFINEK_API_URL || `${process.env.NODE_ENV === 'production' ? 'https://api.sefinek.net' : 'http://127.0.0.1:4010'}/api/v2/cloudflare-waf-abuseipdb/post`;
|
||||||
|
|
||||||
module.exports = async () => {
|
module.exports = async () => {
|
||||||
const reportedIPs = readReportedIPs().filter(ip => ip.action === 'Reported' && ip.sefinekAPI === 'false');
|
const reportedIPs = readReportedIPs().filter(ip => ip.action === 'REPORTED' && ip.sefinekAPI === 'false');
|
||||||
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 log('log', 'No IPs with `action Reported` and `SefinekAPI false` to send to Sefinek API');
|
||||||
|
|
||||||
const uniqueLogs = reportedIPs.reduce((acc, ip) => {
|
const uniqueLogs = reportedIPs.reduce((acc, ip) => {
|
||||||
if (acc.seen.has(ip.ip)) return acc;
|
if (acc.seen.has(ip.ip)) return acc;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue