Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2026-02-12 00:36:42 +01:00
padre f725d02dea
commit 9e5479dd8c
Se han modificado 2 ficheros con 102 adiciones y 12 borrados

Ver fichero

@@ -149,14 +149,14 @@ CACHE_CHECK_INTERVAL=5000
## GeoIP Enrichment ## GeoIP Enrichment
The application automatically enriches captured packets with geolocation data for remote IP addresses: The application automatically enriches captured packets with geolocation data for public IP addresses:
**Features:** **Features:**
- Automatically detects the server's public IP address - Automatically detects the server's public IP address and its geolocation
- Identifies private/local IP addresses (RFC 1918, link-local, etc.) - Identifies private/local IP addresses (RFC 1918, link-local, etc.)
- Only enriches remote public IP addresses - Enriches all public IP addresses (including the server's own IP)
- Uses local GeoIP database (no external API calls during capture) - Uses local GeoIP database (no external API calls during capture)
- Adds geolocation data for both source and destination IPs - Adds geolocation data for both source and destination IPs when they are public
**GeoIP Data Included:** **GeoIP Data Included:**
- Country code and name - Country code and name
@@ -168,9 +168,17 @@ The application automatically enriches captured packets with geolocation data fo
**How it works:** **How it works:**
1. On startup, the application detects its public IP using an external service (ipify.org) 1. On startup, the application detects its public IP using an external service (ipify.org)
2. For each packet, it identifies if source/destination IPs are remote 2. The public IP's geolocation is fetched and cached for the session
3. Remote IPs are enriched with GeoIP data from the local database 3. For each packet:
4. Private IPs, loopback, and the server's own IP are excluded - Source IP: If public (including server's IP), GeoIP data is added to `geoip_src`
- Destination IP: If public (including server's IP), GeoIP data is added to `geoip_dst`
- Private IPs, loopback addresses are excluded from GeoIP enrichment
4. The server's own IP is included in geolocation to provide complete visibility of traffic origin and destination
**Traffic visibility:**
- **Outbound traffic**: `geoip_src` = server location, `geoip_dst` = remote destination location
- **Inbound traffic**: `geoip_src` = remote source location, `geoip_dst` = server location
- **External to external**: Both IPs geolocated (if packet is captured in transit)
**Example GeoIP document structure:** **Example GeoIP document structure:**
```json ```json
@@ -353,6 +361,38 @@ curl -X GET "localhost:9200/network-packets/_search?pretty" -H 'Content-Type: ap
' '
``` ```
**Find packets to a specific country:**
```bash
curl -X GET "localhost:9200/network-packets/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"term": {
"geoip_dst.country": "CN"
}
}
}
'
```
**Find all outbound international traffic:**
```bash
curl -X GET "localhost:9200/network-packets/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"bool": {
"must": [
{ "exists": { "field": "geoip_src" } },
{ "exists": { "field": "geoip_dst" } }
],
"must_not": [
{ "term": { "geoip_src.country": { "value": "geoip_dst.country" } } }
]
}
}
}
'
```
**Find packets to/from a specific geographic area:** **Find packets to/from a specific geographic area:**
```bash ```bash
curl -X GET "localhost:9200/network-packets/_search?pretty" -H 'Content-Type: application/json' -d' curl -X GET "localhost:9200/network-packets/_search?pretty" -H 'Content-Type: application/json' -d'
@@ -378,7 +418,8 @@ curl -X GET "localhost:9200/network-packets/_search?pretty" -H 'Content-Type: ap
"aggs": { "aggs": {
"countries": { "countries": {
"terms": { "terms": {
"field": "geoip_dst.country" "field": "geoip_dst.country",
"size": 20
} }
} }
} }
@@ -386,6 +427,39 @@ curl -X GET "localhost:9200/network-packets/_search?pretty" -H 'Content-Type: ap
' '
``` ```
**Find traffic between two specific countries:**
```bash
curl -X GET "localhost:9200/network-packets/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"bool": {
"must": [
{ "term": { "geoip_src.country": "US" } },
{ "term": { "geoip_dst.country": "GB" } }
]
}
}
}
'
```
**Map visualization - Get traffic with coordinates:**
```bash
curl -X GET "localhost:9200/network-packets/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"bool": {
"must": [
{ "exists": { "field": "geoip_src.location" } },
{ "exists": { "field": "geoip_dst.location" } }
]
}
},
"_source": ["ip.src", "ip.dst", "geoip_src.location", "geoip_dst.location", "geoip_src.city", "geoip_dst.city"]
}
'
```
## Performance Considerations ## Performance Considerations
- **Promiscuous mode** can generate high packet volumes on busy networks - **Promiscuous mode** can generate high packet volumes on busy networks

Ver fichero

@@ -29,6 +29,7 @@ const ES_CHECK_INTERVAL = config.cache.checkInterval;
// Public IP detection // Public IP detection
let publicIP = null; let publicIP = null;
let publicIPGeoData = null;
// Statistics tracking // Statistics tracking
const stats = { const stats = {
@@ -186,11 +187,11 @@ function isPrivateIP(ip) {
} }
/** /**
* Check if IP is remote (not local, not private, not our public IP) * Check if IP is remote (not local, not private)
* Now includes the public IP for geolocation
*/ */
function isRemoteIP(ip) { function isRemoteIP(ip) {
if (!ip || isPrivateIP(ip)) return false; if (!ip || isPrivateIP(ip)) return false;
if (publicIP && ip === publicIP) return false;
return true; return true;
} }
@@ -198,10 +199,15 @@ function isRemoteIP(ip) {
* Get GeoIP information for an IP address * Get GeoIP information for an IP address
*/ */
function getGeoIPData(ip) { function getGeoIPData(ip) {
if (!ip || !isRemoteIP(ip)) { if (!ip || isPrivateIP(ip)) {
return null; return null;
} }
// Return cached GeoIP data for our public IP
if (publicIP && ip === publicIP && publicIPGeoData) {
return publicIPGeoData;
}
try { try {
const geo = geoip.lookup(ip); const geo = geoip.lookup(ip);
@@ -825,10 +831,20 @@ async function main() {
process.exit(1); process.exit(1);
} }
// Get public IP address for GeoIP filtering // Get public IP address and GeoIP data
try { try {
publicIP = await getPublicIP(); publicIP = await getPublicIP();
logger.info(`Detected public IP: ${publicIP}`); logger.info(`Detected public IP: ${publicIP}`);
// Get GeoIP data for our public IP
if (publicIP) {
publicIPGeoData = getGeoIPData(publicIP);
if (publicIPGeoData) {
logger.info(`Public IP geolocation: ${publicIPGeoData.city || 'Unknown'}, ${publicIPGeoData.country || 'Unknown'}`);
} else {
logger.warn('Could not determine geolocation for public IP');
}
}
} catch (error) { } catch (error) {
logger.warn('Failed to detect public IP address:', error.message); logger.warn('Failed to detect public IP address:', error.message);
logger.warn('GeoIP will be applied to all non-private IPs'); logger.warn('GeoIP will be applied to all non-private IPs');