113
index.js
113
index.js
@@ -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' },
|
||||||
|
|||||||
Referencia en una nueva incidencia
Block a user