Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2026-02-11 22:07:33 +01:00
padre cffe892c8e
commit 8382a3de99

113
index.js
Ver fichero

@@ -120,6 +120,45 @@ function buildBPFFilter() {
return filters.length > 0 ? filters.join(' and ') : ''; return filters.length > 0 ? filters.join(' and ') : '';
} }
/**
* Validate and format IP address for Elasticsearch
* Returns null if invalid
*/
function validateIPAddress(ipString) {
if (!ipString || typeof ipString !== 'string') return null;
// IPv4 validation regex
const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
// IPv6 validation - check if it contains colons and valid hex characters
const ipv6Regex = /^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$/;
// Check if it's a valid IPv4
if (ipv4Regex.test(ipString)) {
const parts = ipString.split('.');
const allValid = parts.every(part => {
const num = parseInt(part, 10);
return num >= 0 && num <= 255;
});
return allValid ? ipString : null;
}
// Check if it's a valid IPv6
if (ipv6Regex.test(ipString)) {
return ipString;
}
// Try to convert MAC-like format to IPv6 (fe:80:... -> fe80::...)
// Some decoders might return IPv6 in an incorrect format
if (ipString.includes(':') && ipString.length > 20) {
// This might be a malformed IPv6, try to detect and skip
logger.debug(`Skipping malformed IP address: ${ipString}`);
return null;
}
return null;
}
/** /**
* Check if content is ASCII/readable * Check if content is ASCII/readable
*/ */
@@ -321,14 +360,31 @@ async function processPacket(buffer, interfaceInfo) {
const ipRet = decoders.IPV4(buffer, ret.offset); const ipRet = decoders.IPV4(buffer, ret.offset);
if (ipRet) { if (ipRet) {
packet.ip = { const srcAddr = validateIPAddress(ipRet.info.srcaddr);
version: 4, const dstAddr = validateIPAddress(ipRet.info.dstaddr);
src: ipRet.info.srcaddr,
dst: ipRet.info.dstaddr, // Only add IP fields if addresses are valid
protocol: ipRet.info.protocol, if (srcAddr && dstAddr) {
ttl: ipRet.info.ttl, packet.ip = {
length: ipRet.info.totallen version: 4,
}; src: srcAddr,
dst: dstAddr,
protocol: ipRet.info.protocol,
ttl: ipRet.info.ttl,
length: ipRet.info.totallen
};
} else {
// Store raw addresses if validation fails
packet.ip_raw = {
version: 4,
src: ipRet.info.srcaddr,
dst: ipRet.info.dstaddr,
protocol: ipRet.info.protocol,
ttl: ipRet.info.ttl,
length: ipRet.info.totallen
};
logger.debug(`Invalid IPv4 addresses: ${ipRet.info.srcaddr} -> ${ipRet.info.dstaddr}`);
}
// Decode TCP // Decode TCP
if (ipRet.info.protocol === PROTOCOL.IP.TCP) { if (ipRet.info.protocol === PROTOCOL.IP.TCP) {
@@ -402,13 +458,29 @@ async function processPacket(buffer, interfaceInfo) {
const ipv6Ret = decoders.IPV6(buffer, ret.offset); const ipv6Ret = decoders.IPV6(buffer, ret.offset);
if (ipv6Ret) { if (ipv6Ret) {
packet.ip = { const srcAddr = validateIPAddress(ipv6Ret.info.srcaddr);
version: 6, const dstAddr = validateIPAddress(ipv6Ret.info.dstaddr);
src: ipv6Ret.info.srcaddr,
dst: ipv6Ret.info.dstaddr, // Only add IP fields if addresses are valid
protocol: ipv6Ret.info.protocol, if (srcAddr && dstAddr) {
hop_limit: ipv6Ret.info.hoplimit packet.ip = {
}; version: 6,
src: srcAddr,
dst: dstAddr,
protocol: ipv6Ret.info.protocol,
hop_limit: ipv6Ret.info.hoplimit
};
} else {
// Store raw addresses if validation fails
packet.ip_raw = {
version: 6,
src: ipv6Ret.info.srcaddr,
dst: ipv6Ret.info.dstaddr,
protocol: ipv6Ret.info.protocol,
hop_limit: ipv6Ret.info.hoplimit
};
logger.debug(`Invalid IPv6 addresses: ${ipv6Ret.info.srcaddr} -> ${ipv6Ret.info.dstaddr}`);
}
} }
} }
@@ -510,6 +582,17 @@ async function initializeElasticsearch() {
hop_limit: { type: 'integer' } hop_limit: { type: 'integer' }
} }
}, },
ip_raw: {
properties: {
version: { type: 'integer' },
src: { type: 'keyword' },
dst: { type: 'keyword' },
protocol: { type: 'integer' },
ttl: { type: 'integer' },
length: { type: 'integer' },
hop_limit: { type: 'integer' }
}
},
tcp: { tcp: {
properties: { properties: {
src_port: { type: 'integer' }, src_port: { type: 'integer' },