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: {
// 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_TOKEN: 'HKKAUZHTDAH7W87SyL6XsWkV8UeUFVA9VvvXhn6H9Wn6kfDW6ZsXCtbahmkaYcLbxZGyrAKPmSkXb3AJ6pCU3VuDyTjUSehMyDZ',
SECRET_TOKEN: '',
// 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

View file

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

View file

@ -2,26 +2,10 @@ const axios = require('./axios.js');
const { readReportedIPs, updateSefinekAPIInCSV } = require('./csv.js');
const log = require('../utils/log.js');
const fetchServerIP = require('./fetchServerIP.js');
const whitelist = require('../utils/whitelist.js');
const { MAIN } = require('../config.js').CONFIG;
const { SEFINEK_API } = require('../config.js').CONFIG;
module.exports = async () => {
const reportedIPs = (readReportedIPs() || []).filter(x =>
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))
)
)
);
const reportedIPs = (readReportedIPs() || []).filter(x => x.status === 'REPORTED' && x.ip !== fetchServerIP() && !x.sefinekAPI);
if (!reportedIPs.length) return;
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');
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 => ({
rayId: ip.rayId,
ip: ip.ip,
@ -44,12 +29,15 @@ module.exports = async () => {
country: ip.country,
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));
} 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'));
};
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 };

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 userAgents = ['Chrome/129', 'Chrome/130', 'Chrome/131', 'Chrome/132', 'StellaLauncher', 'PrepareStella'];
const endpoints = ['/api/', '//video', '//js', '//images', '//imgs', 'favicon.ico', 'sitemap.xml', 'robots.txt'];
const domains = ['blocklist.sefinek.net', 'bucket.sefinek.net'];
const endpoints = ['favicon.ico', 'favicon.png', 'sitemap.xml', 'robots.txt'];
module.exports = { domains, userAgents, endpoints };
module.exports = { domains, endpoints };