90
README.md
90
README.md
@@ -149,14 +149,14 @@ CACHE_CHECK_INTERVAL=5000
|
||||
|
||||
## 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:**
|
||||
- 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.)
|
||||
- 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)
|
||||
- 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:**
|
||||
- Country code and name
|
||||
@@ -168,9 +168,17 @@ The application automatically enriches captured packets with geolocation data fo
|
||||
|
||||
**How it works:**
|
||||
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
|
||||
3. Remote IPs are enriched with GeoIP data from the local database
|
||||
4. Private IPs, loopback, and the server's own IP are excluded
|
||||
2. The public IP's geolocation is fetched and cached for the session
|
||||
3. For each packet:
|
||||
- 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:**
|
||||
```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:**
|
||||
```bash
|
||||
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": {
|
||||
"countries": {
|
||||
"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
|
||||
|
||||
- **Promiscuous mode** can generate high packet volumes on busy networks
|
||||
|
||||
24
index.js
24
index.js
@@ -29,6 +29,7 @@ const ES_CHECK_INTERVAL = config.cache.checkInterval;
|
||||
|
||||
// Public IP detection
|
||||
let publicIP = null;
|
||||
let publicIPGeoData = null;
|
||||
|
||||
// Statistics tracking
|
||||
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) {
|
||||
if (!ip || isPrivateIP(ip)) return false;
|
||||
if (publicIP && ip === publicIP) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -198,10 +199,15 @@ function isRemoteIP(ip) {
|
||||
* Get GeoIP information for an IP address
|
||||
*/
|
||||
function getGeoIPData(ip) {
|
||||
if (!ip || !isRemoteIP(ip)) {
|
||||
if (!ip || isPrivateIP(ip)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return cached GeoIP data for our public IP
|
||||
if (publicIP && ip === publicIP && publicIPGeoData) {
|
||||
return publicIPGeoData;
|
||||
}
|
||||
|
||||
try {
|
||||
const geo = geoip.lookup(ip);
|
||||
|
||||
@@ -825,10 +831,20 @@ async function main() {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Get public IP address for GeoIP filtering
|
||||
// Get public IP address and GeoIP data
|
||||
try {
|
||||
publicIP = await getPublicIP();
|
||||
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) {
|
||||
logger.warn('Failed to detect public IP address:', error.message);
|
||||
logger.warn('GeoIP will be applied to all non-private IPs');
|
||||
|
||||
Referencia en una nueva incidencia
Block a user