This commit is contained in:
Sefinek 2025-02-02 03:05:21 +01:00
parent 5860aba631
commit c09400eb82
6 changed files with 28 additions and 62 deletions

View file

@ -28,10 +28,10 @@ exports.CONFIG = {
SEFINEK_API: { SEFINEK_API: {
// Report IP addresses to api.sefinek.net to support the development of the repository at https://github.com/sefinek/Malicious-IP-Addresses. SECRET_TOKEN is required if true. // Report IP addresses to api.sefinek.net to support the development of the repository at https://github.com/sefinek/Malicious-IP-Addresses. SECRET_TOKEN is required if true.
REPORT_TO_SEFIN_API: true, REPORT_TO_SEFIN_API: false,
// Secret key for api.sefinek.net // Secret key for api.sefinek.net
SECRET_TOKEN: 'HKKAUZHTDAH7W87SyL6XsWkV8UeUFVA9VvvXhn6H9Wn6kfDW6ZsXCtbahmkaYcLbxZGyrAKPmSkXb3AJ6pCU3VuDyTjUSehMyDZ', SECRET_TOKEN: '',
// How often should the log (reported_ips.csv) be analyzed and sent to the Sefinek API? In hours. // How often should the log (reported_ips.csv) be analyzed and sent to the Sefinek API? In hours.
INTERVAL: 60 * 60 * 1000, // Frequency for analyzing and submitting logs to the Sefinek API INTERVAL: 60 * 60 * 1000, // Frequency for analyzing and submitting logs to the Sefinek API

View file

@ -2,13 +2,13 @@ const axios = require('./services/axios.js');
const { CONFIG, GENERATE_COMMENT } = require('./config.js'); const { CONFIG, GENERATE_COMMENT } = require('./config.js');
const PAYLOAD = require('./services/payload.js'); const PAYLOAD = require('./services/payload.js');
const SefinekAPI = require('./services/SefinekAPI.js'); const SefinekAPI = require('./services/SefinekAPI.js');
const isImageRequest = require('./utils/isImageRequest.js');
const headers = require('./utils/headers.js'); const headers = require('./utils/headers.js');
const { logToCSV, readReportedIPs, wasImageRequestLogged } = 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 whitelist = require('./utils/whitelist.js');
const log = require('./utils/log.js'); const log = require('./utils/log.js');
const imgExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.svg', '.webp'];
const fetchBlockedIPs = async () => { const fetchBlockedIPs = async () => {
try { try {
@ -17,15 +17,9 @@ const fetchBlockedIPs = async () => {
if (events) { if (events) {
const filtered = events.filter(x => const filtered = events.filter(x =>
x.ip !== fetchServerIP() && x.ip !== fetchServerIP() &&
( !imgExtensions.some(ext => x.clientRequestPath.endsWith(ext)) &&
x.source === 'securitylevel' || !whitelist.domains.some(subdomain => x.clientRequestHTTPHost?.includes(subdomain)) &&
x.source === 'badscore' || !whitelist.endpoints.some(endpoint => x.clientRequestPath?.includes(endpoint))
(
!whitelist.domains.some(subdomain => x.clientRequestHTTPHost?.includes(subdomain)) &&
!whitelist.userAgents.some(ua => x.userAgent?.includes(ua)) &&
!whitelist.endpoints.some(endpoint => x.clientRequestPath?.includes(endpoint))
)
)
); );
log(0, `Fetched ${events.length} (filtered ${filtered.length}) events from Cloudflare`); log(0, `Fetched ${events.length} (filtered ${filtered.length}) events from Cloudflare`);
@ -92,7 +86,7 @@ const reportIP = async (event, uri, country, hostname, endpoint, cycleErrorCount
log(0, `429 for ${event.clientIP} (${event.rayName}); Endpoint: ${endpoint}`); log(0, `429 for ${event.clientIP} (${event.rayName}); Endpoint: ${endpoint}`);
cycleErrorCounts.blocked++; cycleErrorCounts.blocked++;
} else { } else {
log(2, `Error ${err.response?.status} while reporting ${event.clientIP}; URI: ${uri}; (${err.response?.data || err.message})`); log(2, `Error ${err.response?.status} while reporting ${event.clientIP}; URI: ${uri}; ${err.response?.data?.errors[0]?.detail || JSON.stringify(err.response?.data) || err.message}`);
cycleErrorCounts.otherErrors++; cycleErrorCounts.otherErrors++;
} }
@ -104,6 +98,8 @@ const reportIP = async (event, uri, country, hostname, endpoint, cycleErrorCount
log(0, 'Loading data, please wait...'); log(0, 'Loading data, please wait...');
// Sefinek API // Sefinek API
await SefinekAPI();
return;
if (CONFIG.SEFINEK_API.REPORT_TO_SEFIN_API && CONFIG.SEFINEK_API.INTERVAL && CONFIG.SEFINEK_API.SECRET_TOKEN) { if (CONFIG.SEFINEK_API.REPORT_TO_SEFIN_API && CONFIG.SEFINEK_API.INTERVAL && CONFIG.SEFINEK_API.SECRET_TOKEN) {
setInterval(SefinekAPI, CONFIG.SEFINEK_API.INTERVAL); setInterval(SefinekAPI, CONFIG.SEFINEK_API.INTERVAL);
} }
@ -128,17 +124,16 @@ const reportIP = async (event, uri, country, hostname, endpoint, cycleErrorCount
continue; continue;
} }
const userIp = fetchServerIP(); const serverIP = fetchServerIP();
if (!userIp) log(1, `Your IP address is missing! Received: ${userIp}`); if (!serverIP) log(1, `Server IP address is missing! Received: ${serverIP}`);
let cycleImageSkippedCount = 0, cycleProcessedCount = 0, cycleReportedCount = 0, cycleSkippedCount = 0; let cycleProcessedCount = 0, cycleReportedCount = 0, cycleSkippedCount = 0;
const cycleErrorCounts = { blocked: 0, otherErrors: 0 }; const cycleErrorCounts = { blocked: 0, otherErrors: 0 };
let imageRequestLogged = false;
for (const event of blockedIPEvents) { for (const event of blockedIPEvents) {
cycleProcessedCount++; cycleProcessedCount++;
const ip = event.clientIP; const ip = event.clientIP;
if (ip === userIp) { if (ip === serverIP) {
log(0, `The IP address ${ip} belongs to this machine. Ignoring...`); log(0, `The IP address ${ip} belongs to this machine. Ignoring...`);
cycleSkippedCount++; cycleSkippedCount++;
continue; continue;
@ -160,17 +155,6 @@ const reportIP = async (event, uri, country, hostname, endpoint, cycleErrorCount
continue; continue;
} }
if (isImageRequest(event.clientRequestPath)) {
cycleImageSkippedCount++;
if (!wasImageRequestLogged(ip, reportedIPs)) {
if (imageRequestLogged) continue;
log(0, 'Skipping image requests in this cycle...');
imageRequestLogged = true;
}
continue;
}
const wasReported = await reportIP(event, `${event.clientRequestHTTPHost}${event.clientRequestPath}`, event.clientCountryName, event.clientRequestHTTPHost, event.clientRequestPath, cycleErrorCounts); const wasReported = await reportIP(event, `${event.clientRequestHTTPHost}${event.clientRequestPath}`, event.clientCountryName, event.clientRequestHTTPHost, event.clientRequestPath, cycleErrorCounts);
if (wasReported) { if (wasReported) {
cycleReportedCount++; cycleReportedCount++;
@ -181,7 +165,6 @@ const reportIP = async (event, uri, country, hostname, endpoint, cycleErrorCount
log(0, `- Reported IPs: ${cycleReportedCount}`); log(0, `- Reported IPs: ${cycleReportedCount}`);
log(0, `- Total IPs processed: ${cycleProcessedCount}`); log(0, `- Total IPs processed: ${cycleProcessedCount}`);
log(0, `- Skipped IPs: ${cycleSkippedCount}`); log(0, `- Skipped IPs: ${cycleSkippedCount}`);
log(0, `- Ignored image requests: ${cycleImageSkippedCount}`);
log(0, `- Rate-limits: ${cycleErrorCounts.blocked}`); log(0, `- Rate-limits: ${cycleErrorCounts.blocked}`);
log(0, `- Other errors: ${cycleErrorCounts.otherErrors}`); log(0, `- Other errors: ${cycleErrorCounts.otherErrors}`);
log(0, '===================== End of Reporting Cycle ====================='); log(0, '===================== End of Reporting Cycle =====================');

View file

@ -2,26 +2,10 @@ const axios = require('./axios.js');
const { readReportedIPs, updateSefinekAPIInCSV } = require('./csv.js'); const { readReportedIPs, updateSefinekAPIInCSV } = require('./csv.js');
const log = require('../utils/log.js'); const log = require('../utils/log.js');
const fetchServerIP = require('./fetchServerIP.js'); const fetchServerIP = require('./fetchServerIP.js');
const whitelist = require('../utils/whitelist.js'); const { SEFINEK_API } = require('../config.js').CONFIG;
const { MAIN } = require('../config.js').CONFIG;
module.exports = async () => { module.exports = async () => {
const reportedIPs = (readReportedIPs() || []).filter(x => const reportedIPs = (readReportedIPs() || []).filter(x => x.status === 'REPORTED' && x.ip !== fetchServerIP() && !x.sefinekAPI);
x.status === 'REPORTED' &&
x.ip !== fetchServerIP() &&
!x.sefinekAPI &&
(
x.source === 'securitylevel' ||
x.source === 'badscore' ||
(
!(/crawler|spider|bot/gi).test(x.userAgent) &&
!whitelist.domains.some(subdomain => x.clientRequestHTTPHost?.includes(subdomain)) &&
!whitelist.userAgents.some(ua => x.userAgent?.includes(ua)) &&
!whitelist.endpoints.some(endpoint => x.clientRequestPath?.includes(endpoint))
)
)
);
if (!reportedIPs.length) return; if (!reportedIPs.length) return;
const seenIPs = new Set(); const seenIPs = new Set();
@ -34,7 +18,8 @@ module.exports = async () => {
if (!uniqueLogs.length) return log(0, 'No unique IPs to send to Sefinek API'); if (!uniqueLogs.length) return log(0, 'No unique IPs to send to Sefinek API');
try { try {
const res = await axios.post('https://api.sefinek.net/api/v2/cloudflare-waf-abuseipdb/post', { // http://127.0.0.1:4010/api/v2/cloudflare-waf-abuseipdb
const res = await axios.post('https://api.sefinek.net/api/v2/cloudflare-waf-abuseipdb', {
reportedIPs: uniqueLogs.map(ip => ({ reportedIPs: uniqueLogs.map(ip => ({
rayId: ip.rayId, rayId: ip.rayId,
ip: ip.ip, ip: ip.ip,
@ -44,12 +29,15 @@ module.exports = async () => {
country: ip.country, country: ip.country,
timestamp: ip.timestamp, timestamp: ip.timestamp,
})), })),
}, { headers: { 'Authorization': MAIN.SECRET_TOKEN } }); }, { headers: { 'Authorization': SEFINEK_API.SECRET_TOKEN } });
log(0, `Successfully sent ${uniqueLogs.length} logs to Sefinek API. Status: ${res.status}`); log(0, `Successfully sent ${uniqueLogs.length} logs to Sefinek API! Status: ${res.status}`);
uniqueLogs.forEach(ip => updateSefinekAPIInCSV(ip.rayId, true)); uniqueLogs.forEach(ip => updateSefinekAPIInCSV(ip.rayId, true));
} catch (err) { } catch (err) {
log(2, `Failed to send logs to Sefinek API. Status: ${err.response?.status}. Message: ${err.response?.data?.message || err.stack}`); const msg = err.response?.data?.message ?? err.message;
if (!msg?.includes('No valid or unique')) {
log(2, `Failed to send logs to Sefinek API! Status: ${err.response?.status ?? 'Unknown'}; Message: ${msg}`);
}
} }
}; };

View file

@ -76,6 +76,4 @@ 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'); module.exports = { logToCSV, readReportedIPs, updateSefinekAPIInCSV };
module.exports = { logToCSV, readReportedIPs, updateSefinekAPIInCSV, wasImageRequestLogged };

View file

@ -1,2 +0,0 @@
const extensions = ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.svg', '.webp'];
module.exports = loc => extensions.some(ext => loc.toLowerCase().endsWith(ext));

View file

@ -1,5 +1,4 @@
const domains = ['api.', 'cdn.', 'blocklist.sefinek.net', 'bucket.sefinek.net']; const domains = ['blocklist.sefinek.net', 'bucket.sefinek.net'];
const userAgents = ['Chrome/129', 'Chrome/130', 'Chrome/131', 'Chrome/132', 'StellaLauncher', 'PrepareStella']; const endpoints = ['favicon.ico', 'favicon.png', 'sitemap.xml', 'robots.txt'];
const endpoints = ['/api/', '//video', '//js', '//images', '//imgs', 'favicon.ico', 'sitemap.xml', 'robots.txt'];
module.exports = { domains, userAgents, endpoints }; module.exports = { domains, endpoints };