refactor(server): reduz a complexidade das funções de netGuard

This commit is contained in:
evandro committed 2026-10-10 04:01:25 -03:00
1 parent 656e7b3b5d
commit 37b88f3ff2
1 file changed
+44 -33
+44 -33
View File
@@ -27,59 +27,70 @@ function parseIPv4(ip: string): number[] | null {
: null;
}
// Faixas IPv4 não públicas: [primeiro octeto, 2º octeto mín., 2º octeto máx.],
// e o terceiro octeto só importa em 192.0.0.0/24.
const BLOCKED_IPV4_RANGES: Array<[number, number, number]> = [
[0, 0, 255], // "esta rede"
[10, 0, 255], // privada
[127, 0, 255], // loopback
[100, 64, 127], // CGNAT
[169, 254, 254], // link-local / metadados de nuvem
[172, 16, 31], // privada
[192, 168, 168], // privada
[198, 18, 19], // benchmarking
];
function isBlockedIPv4([a, b, c]: number[]): boolean {
return (
a === 0 || // "esta rede"
a === 10 || // privada
a === 127 || // loopback
(a === 100 && b >= 64 && b <= 127) || // CGNAT
(a === 169 && b === 254) || // link-local / metadados de nuvem
(a === 172 && b >= 16 && b <= 31) || // privada
(a === 192 && b === 0 && c === 0) || // IETF protocol assignments
(a === 192 && b === 168) || // privada
(a === 198 && (b === 18 || b === 19)) || // benchmarking
a >= 224 // multicast, reservado e broadcast
);
if (a >= 224) return true; // multicast, reservado e broadcast
if (a === 192 && b === 0 && c === 0) return true; // IETF protocol assignments
return BLOCKED_IPV4_RANGES.some(([first, min, max]) => a === first && b >= min && b <= max);
}
/** Troca um IPv4 embutido no fim ("::ffff:1.2.3.4") por dois grupos hexa. */
function expandEmbeddedIPv4(text: string): string | null {
const embedded = text.match(/^(.*:)(\d+\.\d+\.\d+\.\d+)$/);
if (!embedded) return text;
const v4 = parseIPv4(embedded[2]);
if (!v4) return null;
return `${embedded[1]}${((v4[0] << 8) | v4[1]).toString(16)}:${((v4[2] << 8) | v4[3]).toString(16)}`;
}
/** Expande um IPv6 para 8 grupos de 16 bits (ou null se for inválido). */
function parseIPv6(ip: string): number[] | null {
let text = ip.split("%")[0].toLowerCase(); // remove zone id
const embedded = text.match(/^(.*:)(\d+\.\d+\.\d+\.\d+)$/);
if (embedded) {
const v4 = parseIPv4(embedded[2]);
if (!v4) return null;
text = `${embedded[1]}${((v4[0] << 8) | v4[1]).toString(16)}:${((v4[2] << 8) | v4[3]).toString(16)}`;
}
const text = expandEmbeddedIPv4(ip.split("%")[0].toLowerCase()); // remove zone id
if (text === null) return null;
const halves = text.split("::");
if (halves.length > 2) return null;
const head = halves[0] ? halves[0].split(":") : [];
const tail = halves.length === 2 && halves[1] ? halves[1].split(":") : [];
const missing = 8 - head.length - tail.length;
if (missing < (halves.length === 2 ? 1 : 0) || (halves.length === 1 && missing !== 0)) return null;
const compressed = halves.length === 2;
if (compressed ? missing < 1 : missing !== 0) return null;
const groups = [...head, ...Array(missing).fill("0"), ...tail].map((g) => parseInt(g, 16));
return groups.length === 8 && groups.every((g) => g >= 0 && g <= 0xffff) ? groups : null;
return groups.every((g) => g >= 0 && g <= 0xffff) ? groups : null;
}
function isReservedIPv6Prefix(first: number): boolean {
return (
(first & 0xfe00) === 0xfc00 || // fc00::/7 (unique local)
(first & 0xffc0) === 0xfe80 || // fe80::/10 (link-local)
(first & 0xff00) === 0xff00 // multicast
);
}
function isBlockedIPv6(ip: string): boolean {
const g = parseIPv6(ip);
if (!g) return true; // não conseguiu interpretar: recusa por segurança
const allZeroUntil = (n: number) => g.slice(0, n).every((x) => x === 0);
const v4FromTail = () => [g[6] >> 8, g[6] & 0xff, g[7] >> 8, g[7] & 0xff];
const zeros = (from: number, to: number) => g.slice(from, to).every((x) => x === 0);
const embeddedV4 = [g[6] >> 8, g[6] & 0xff, g[7] >> 8, g[7] & 0xff];
if (allZeroUntil(7) && g[7] <= 1) return true; // :: e ::1
if (allZeroUntil(5) && g[5] === 0xffff) return isBlockedIPv4(v4FromTail()); // ::ffff:a.b.c.d
if (g[0] === 0x64 && g[1] === 0xff9b && g.slice(2, 6).every((x) => x === 0)) {
return isBlockedIPv4(v4FromTail()); // NAT64 64:ff9b::/96
}
return (
(g[0] & 0xfe00) === 0xfc00 || // fc00::/7 (unique local)
(g[0] & 0xffc0) === 0xfe80 || // fe80::/10 (link-local)
(g[0] & 0xff00) === 0xff00 // multicast
);
if (zeros(0, 7) && g[7] <= 1) return true; // :: e ::1
if (zeros(0, 5) && g[5] === 0xffff) return isBlockedIPv4(embeddedV4); // ::ffff:a.b.c.d
if (g[0] === 0x64 && g[1] === 0xff9b && zeros(2, 6)) return isBlockedIPv4(embeddedV4); // NAT64
return isReservedIPv6Prefix(g[0]);
}
/** true se o endereço IP (v4 ou v6) pertence a uma faixa não pública. */