Files
rodrigonet/src/cgn_list/parser.js
T
2026-04-09 20:37:26 -03:00

81 lines
2.3 KiB
JavaScript

const fs = require('fs');
const path = require('path');
class CgnatParser {
constructor() {
this._data = null;
}
/**
* Carrega e parseia o nat_list.txt (lazy load).
* Retorna Map<publicIP, Array<{privateIP, portStart, portEnd}>>
*/
load() {
if (this._data) return this._data;
const filePath = path.join(__dirname, 'nat_list.txt');
const lines = fs.readFileSync(filePath, 'utf8').split('\n');
const data = new Map();
let currentPublicIp = null;
for (const line of lines) {
const trimmed = line.trim();
const natMatch = trimmed.match(/^NAT Address:\s+(\S+)/);
if (natMatch) {
currentPublicIp = natMatch[1];
if (!data.has(currentPublicIp)) {
data.set(currentPublicIp, []);
}
continue;
}
if (currentPublicIp) {
const entryMatch = trimmed.match(/^(\d+\.\d+\.\d+\.\d+)\s+(\d+)\s+to\s+(\d+)/);
if (entryMatch) {
data.get(currentPublicIp).push({
privateIP: entryMatch[1],
portStart: parseInt(entryMatch[2], 10),
portEnd: parseInt(entryMatch[3], 10)
});
}
}
}
this._data = data;
console.log(`📋 CgnatParser: ${data.size} IPs públicos carregados`);
return data;
}
/**
* Dado um IP público e porta, retorna a entrada { privateIP, portStart, portEnd } ou null.
*/
lookupByPort(publicIp, port) {
const data = this.load();
const entries = data.get(publicIp);
if (!entries) return null;
const portNum = parseInt(port, 10);
return entries.find(e => portNum >= e.portStart && portNum <= e.portEnd) || null;
}
/**
* Retorna todos os IPs privados mapeados a um IP público, ou null se não encontrado.
*/
lookupAll(publicIp) {
const data = this.load();
return data.get(publicIp) || null;
}
/**
* Verifica se um IP público existe no mapa CGNAT.
*/
hasPublicIp(publicIp) {
const data = this.load();
return data.has(publicIp);
}
}
module.exports = new CgnatParser();