Unlink scripts submodule and commit contents as normal directory
This commit is contained in:
1 parent
4f7dea111f
commit
6488b3ea85
48 files changed
+2876
-1
No files matched your search
@@ -0,0 +1,154 @@
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const logger = require('../logger.js');
|
||||
const isSpecialPurposeIP = require('../isSpecialPurposeIP.js');
|
||||
|
||||
const filePath = path.resolve(__dirname, '..', '..', 'whitelist.txt');
|
||||
let whitelistedIPs = new Set();
|
||||
let whitelistedPorts = new Set(); // @chillcog Port Whitelist
|
||||
let reloadTimer = null;
|
||||
|
||||
const parse = content => {
|
||||
// @chillcog Port Whitelist
|
||||
const ipSet = new Set();
|
||||
const portSet = new Set();
|
||||
|
||||
const invalidIPs = [], skippedIPs = [];
|
||||
const invalidPorts = [], skippedPorts = [];
|
||||
|
||||
let section = 'ip';
|
||||
const lines = content.split('\n');
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const raw = lines[i];
|
||||
|
||||
const header = raw.trim().toLowerCase();
|
||||
if (header.includes('[port whitelist]') || (header.includes('port whitelist') && header.includes('['))) {
|
||||
section = 'port';
|
||||
continue;
|
||||
}
|
||||
if (header.includes('[ip whitelist]') || (header.includes('ip whitelist') && header.includes('['))) {
|
||||
section = 'ip';
|
||||
continue;
|
||||
}
|
||||
|
||||
const line = raw.split('#')[0].trim();
|
||||
if (!line) continue;
|
||||
|
||||
if (section === 'port') {
|
||||
const portStr = String(line).split(':').pop().split('/')[0].trim();
|
||||
const port = Number(portStr);
|
||||
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
||||
invalidPorts.push(`${line} (line ${i + 1})`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (portSet.has(port)) {
|
||||
skippedPorts.push(`${line} (line ${i + 1})`);
|
||||
continue;
|
||||
}
|
||||
|
||||
portSet.add(port);
|
||||
continue;
|
||||
}
|
||||
|
||||
const { is, range } = isSpecialPurposeIP(line);
|
||||
if (range === null) {
|
||||
invalidIPs.push(`${line} (line ${i + 1})`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is) {
|
||||
skippedIPs.push(`${line} (${range})`);
|
||||
continue;
|
||||
}
|
||||
|
||||
ipSet.add(line);
|
||||
}
|
||||
|
||||
if (invalidIPs.length > 0) {
|
||||
logger.warn(`Invalid IP address${invalidIPs.length > 1 ? 'es' : ''} in whitelist, skipping: ${invalidIPs.join(', ')}`);
|
||||
}
|
||||
|
||||
if (skippedIPs.length > 0) {
|
||||
logger.warn(`Special-purpose IP${skippedIPs.length > 1 ? 's' : ''} detected in whitelist.txt, was this intentional? ${skippedIPs.join(', ')}`);
|
||||
}
|
||||
|
||||
if (invalidPorts.length > 0) {
|
||||
logger.warn(`Invalid port${invalidPorts.length > 1 ? 's' : ''} in whitelist, skipping: ${invalidPorts.join(', ')}`);
|
||||
}
|
||||
|
||||
if (skippedPorts.length > 0) {
|
||||
logger.warn(`Skipped duplicate port${skippedPorts.length > 1 ? 's' : ''} in whitelist.txt: ${skippedPorts.join(', ')}`);
|
||||
}
|
||||
|
||||
return { ipSet, portSet };
|
||||
};
|
||||
|
||||
const load = () => {
|
||||
try {
|
||||
const content = fs.readFileSync(filePath, 'utf-8');
|
||||
const { ipSet, portSet } = parse(content);
|
||||
whitelistedIPs = ipSet;
|
||||
whitelistedPorts = portSet;
|
||||
|
||||
if (whitelistedIPs.size > 0) logger.info(`Loaded ${whitelistedIPs.size} whitelisted IP${whitelistedIPs.size > 1 ? 's' : ''} from ${filePath}`);
|
||||
if (whitelistedPorts.size > 0) logger.info(`Loaded ${whitelistedPorts.size} whitelisted port${whitelistedPorts.size > 1 ? 's' : ''} from ${filePath}`);
|
||||
} catch (err) {
|
||||
logger.error(`Failed to load whitelist file: ${err.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
const initWhitelist = () => {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
fs.writeFileSync(
|
||||
filePath,
|
||||
[
|
||||
'# UFW AbuseIPDB Reporter - whitelist.txt',
|
||||
'# Changes to this file are detected and applied automatically (no restart required)',
|
||||
'',
|
||||
'# ====== [IP WHITELIST] ======',
|
||||
'# One IP address per line (IPv4 or IPv6)',
|
||||
'# Lines starting with # are comments',
|
||||
'#',
|
||||
'# Examples:',
|
||||
'# 79.186.0.0',
|
||||
'# 2a01:11bf:4504:b10c:8a32:ffe7:510a:6d4e',
|
||||
'',
|
||||
'# ====== [PORT WHITELIST] ======',
|
||||
'# One destination port per line. Applies to ALL IPs.',
|
||||
'# Optional: you may write entries like "22/tcp"; the numeric port will be extracted.',
|
||||
'# Added if you have certain services that trigger false positives and you want to exclude',
|
||||
'# them from triggering reports regardless of source IP. Use with caution, as this will ignore',
|
||||
'# all traffic to the specified port(s) and may cause you to miss legitimate reports if that port is attacked.',
|
||||
'# Examples:',
|
||||
'# 22',
|
||||
'# 25565',
|
||||
'# 1194/tcp',
|
||||
].join('\n') + '\n'
|
||||
);
|
||||
logger.info(`Created default whitelist file: ${filePath}`);
|
||||
}
|
||||
// @chillcog end;
|
||||
load();
|
||||
|
||||
const dir = path.dirname(filePath);
|
||||
const filename = path.basename(filePath);
|
||||
|
||||
try {
|
||||
const watcher = fs.watch(dir, (event, file) => {
|
||||
if (file !== filename) return;
|
||||
clearTimeout(reloadTimer);
|
||||
reloadTimer = setTimeout(load, 200);
|
||||
});
|
||||
watcher.on('error', err => logger.error(`Whitelist watcher error: ${err.message}`));
|
||||
} catch (err) {
|
||||
logger.error(`Failed to watch whitelist file: ${err.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
initWhitelist,
|
||||
isWhitelisted: ip => whitelistedIPs.has(ip),
|
||||
isPortWhitelisted: port => whitelistedPorts.has(port),
|
||||
};
|
||||
Reference in new issue
Block a user