Behavioral Network Fingerprinting & Drift Intelligence Engine
Enterprise-grade passive network telemetry analysis system for SOC environments. NetDNA constructs deterministic behavioral fingerprints from network traffic patterns and detects anomalous drift from established baselines.
- Overview
- Features
- Quick Start
- Installation
- Command Reference
- Architecture
- Algorithms
- Output Examples
- Configuration
- Troubleshooting
- Developer Guide
- Contributing
- Security Considerations
- Performance Tuning
- FAQ
- License
NetDNA is designed for deployment inside Security Operations Center (SOC) environments where passive behavioral analysis of network traffic is required. Unlike signature-based detection systems, NetDNA builds statistical profiles of host behavior and detects deviations that may indicate:
- Compromised hosts exhibiting C2 beaconing behavior
- DNS tunneling or Domain Generation Algorithm (DGA) activity
- Unauthorized automated tools or scripts
- Lateral movement patterns
- Data exfiltration attempts
The system operates in passive-only mode - it captures and analyzes traffic but never injects packets or modifies network flows.
| Feature | Description |
|---|---|
| Passive Capture | AF_PACKET-based zero-copy packet capture on Linux |
| Flow Aggregation | Sliding time-window aggregation with bounded memory |
| Behavioral Features | Timing, DNS, TLS, periodicity, and burst metrics |
| Fingerprinting | Deterministic feature vector construction |
| Baseline Storage | JSON persistence with version-safe schema |
| Drift Detection | Statistical z-score analysis with severity classification |
| Alert Engine | Deduplication, rules, and structured output |
| JSON Export | Machine-parseable output for SIEM integration |
┌─────────────────────────────────────────────────────────────┐
│ BEHAVIORAL METRICS │
├─────────────────┬─────────────────┬─────────────────────────┤
│ TIMING │ DNS │ PERIODICITY │
├─────────────────┼─────────────────┼─────────────────────────┤
│ • Mean IPI │ • Shannon │ • FFT Spectral │
│ • Std Deviation │ Entropy │ Analysis │
│ • Coeff. Var. │ • NXDOMAIN │ • Dominant Period │
│ • Burst Score │ Ratio │ • Regularity Score │
│ • Packet Rate │ • Unique Domains│ • Spectral Dominance │
└─────────────────┴─────────────────┴─────────────────────────┘
# Build from source
git clone https://github.com/0xdevren/NetDNA.git
cd NetDNA
go build -o netdna .
# Generate a fingerprint for a host
./netdna fingerprint --host 192.168.1.100 --window 10m
# Export fingerprint to file
./netdna fingerprint --host 192.168.1.100 --export host.json
# Analyze drift against baseline
./netdna drift --baseline baseline.json --threshold 3.0
# Compare two fingerprints
./netdna compare --source hostA.json --target hostB.json- Go 1.21 or later
- Linux kernel 3.0+ (for AF_PACKET support)
- Root or CAP_NET_RAW capabilities for packet capture
# Clone repository
git clone https://github.com/0xdevren/NetDNA.git
cd NetDNA
# Download dependencies
go mod tidy
# Build binary
go build -o netdna .
# Install to system path (optional)
sudo cp netdna /usr/local/bin/# Enable SQLite for historical storage
go build -tags sqlite -o netdna .For non-root packet capture:
sudo setcap cap_net_raw,cap_net_admin=eip ./netdnaCapture packets and generate behavioral baselines.
netdna observe [flags]| Flag | Short | Default | Description |
|---|---|---|---|
--interface |
-i |
eth0 |
Network interface to capture |
--duration |
-d |
10m |
Capture duration (0 = unlimited) |
--filter |
"" |
BPF filter expression | |
--baseline |
"" |
Baseline operation (save/load) |
|
--output |
-o |
"" |
Output file path |
--daemon |
false |
Run in daemon mode | |
--snaplen |
65536 |
Snapshot length | |
--promisc |
true |
Enable promiscuous mode |
# Basic capture for 15 minutes
./netdna observe --interface eth0 --duration 15m
# Capture with BPF filter, save baseline
./netdna observe -i eth0 -d 10m \
--filter "tcp or udp" \
--baseline save \
--output baseline.json
# Capture only DNS traffic
./netdna observe -i eth0 -d 5m --filter "udp port 53"[NETDNA FINGERPRINT SUMMARY]
Host: 192.168.1.23
Window: 15m
Timing Metrics:
Mean Inter-Packet Interval: 43.1 ms
Std Deviation: 5.2 ms
Burst Score: 1.21
DNS Intelligence:
Entropy Score: 2.81
NXDOMAIN Ratio: 0.03
Periodicity Metrics:
Periodicity Score: 0.15
Regularity Score: 0.85
Behavior Classification:
Stable Interactive Workstation
Baseline saved to baseline.json (profiles: 1)
Generate behavioral fingerprint for a specific host.
netdna fingerprint [flags]| Flag | Default | Description |
|---|---|---|
--host |
"" |
Host IP address |
--window |
10m |
Window duration |
--export |
"" |
Export fingerprint to JSON |
--input |
"" |
Input flows file |
# Generate fingerprint
./netdna fingerprint --host 192.168.1.23 --window 10m
# Export to file
./netdna fingerprint --host 192.168.1.23 --export host.json
# JSON output
./netdna fingerprint --host 192.168.1.23 --json[NETDNA FINGERPRINT]
Host: 192.168.1.23
Window: 10m0s
Timestamp: 2026-02-22T12:00:00Z
Classification: Stable Interactive
Metadata:
Packet Count: 1500
Byte Count: 125.50 KB
Flow Count: 25
Unique Destinations: 12
Features:
timing_mean_ipi 43.1000
timing_stddev 5.2000
timing_burst_score 1.2100
dns_entropy 2.8100
periodicity_score 0.1500
periodicity_regularity 0.8500
Analyze behavioral drift against a baseline profile.
netdna drift [flags]| Flag | Default | Description |
|---|---|---|
--baseline |
"" |
Baseline JSON file |
--current |
"" |
Current observation JSON |
--host |
"" |
Host to analyze |
--threshold |
3.0 |
Drift threshold (sigma) |
| Drift Index | Severity | Action |
|---|---|---|
| < 2.0 | None | No action required |
| 2.0 - 3.0 | Low | Continue monitoring |
| 3.0 - 4.0 | Medium | Add to watchlist |
| 4.0 - 5.0 | High | Escalate to analyst |
| ≥ 5.0 | Critical | Isolate and investigate |
# Analyze drift with default threshold
./netdna drift --baseline baseline.json
# Custom threshold
./netdna drift --baseline baseline.json --threshold 2.5
# JSON output
./netdna drift --baseline baseline.json --json[NETDNA DRIFT ALERT]
Host: 192.168.1.45
Timestamp: 2026-02-21T12:45:09Z
Drift Index: 4.31 (Critical)
Feature Deviations:
--------------------------------------------------
DNS Entropy +3.2σ
Outbound Ratio +2.8σ
Beacon Periodicity +4.9σ
Burst Score +3.5σ
--------------------------------------------------
Assessment:
Critical behavioral deviation detected. High likelihood
of automated or malicious activity.
Recommended Action:
Isolate host and initiate forensic capture. Review recent
network activity.
Compare two fingerprints using similarity metrics.
netdna compare [flags]| Flag | Default | Description |
|---|---|---|
--source |
"" |
Source fingerprint JSON |
--target |
"" |
Target fingerprint JSON |
--metric |
cosine |
Comparison metric |
--threshold |
0.5 |
Similarity threshold |
| Metric | Range | Interpretation |
|---|---|---|
cosine |
0-1 | Higher = more similar |
euclidean |
0-∞ | Lower = more similar |
manhattan |
0-∞ | Lower = more similar |
jaccard |
0-1 | Higher = more similar |
pearson |
-1 to 1 | Higher correlation = similar |
# Compare with cosine similarity
./netdna compare --source hostA.json --target hostB.json
# Use Euclidean distance
./netdna compare --source hostA.json --target hostB.json \
--metric euclidean --threshold 10.0[NETDNA FINGERPRINT COMPARISON]
Source: 192.168.1.100
Timestamp: 2026-02-22 10:00:00
Features: 17
Target: 192.168.1.200
Timestamp: 2026-02-22 11:00:00
Features: 17
Comparison:
Metric: cosine
Threshold: 0.50
Similarity: 0.9847
Match: true
Feature Analysis:
--------------------------------------------------
timing_mean_ipi 43.1000 -> 45.2000 ( +4.87%)
dns_entropy 2.8100 -> 2.9500 ( +4.98%)
periodicity_score 0.1500 -> 0.1620 ( +8.00%)
Manage baseline profiles.
netdna baseline [flags]| Flag | Default | Description |
|---|---|---|
--file |
"" |
Baseline file path |
--mode |
view |
Operation mode |
--host |
"" |
Host to operate on |
--list |
false |
List all hosts |
--delete |
"" |
Delete host from baseline |
--merge |
"" |
Merge with another baseline |
# List all hosts in baseline
./netdna baseline --file baseline.json --list
# View baseline details
./netdna baseline --file baseline.json
# View specific host
./netdna baseline --file baseline.json --host 192.168.1.23
# Delete host from baseline
./netdna baseline --file baseline.json --delete 192.168.1.23
# Merge two baselines
./netdna baseline --file baseline1.json --merge baseline2.jsonDeep feature introspection.
netdna inspect [flags]| Flag | Default | Description |
|---|---|---|
--host |
"" |
Host IP address |
--feature |
"" |
Specific feature to inspect |
--timeline |
false |
Show feature timeline |
--baseline |
"" |
Baseline file for comparison |
--fingerprint |
"" |
Fingerprint file to inspect |
--limit |
10 |
Maximum items to display |
# Inspect all features
./netdna inspect --host 192.168.1.23 --fingerprint host.json
# Inspect specific feature
./netdna inspect --host 192.168.1.23 \
--feature dns_entropy \
--fingerprint host.json
# Show feature timeline
./netdna inspect --host 192.168.1.23 \
--feature periodicity_score \
--timeline[NETDNA FEATURE INSPECTION]
Host: 192.168.1.23
Timestamp: 2026-02-22T12:00:00Z
Window: 10m0s
Class: Stable Interactive Workstation
Features (6 total):
--------------------------------------------------
timing_mean_ipi 43.1000 ████████████████████
timing_stddev 5.2000 ██████████░░░░░░░░░░
dns_entropy 2.8100 █████░░░░░░░░░░░░░░░
timing_burst_score 1.2100 ██░░░░░░░░░░░░░░░░░░
periodicity_regularity 0.8500 █░░░░░░░░░░░░░░░░░░░
periodicity_score 0.1500 ░░░░░░░░░░░░░░░░░░░░
--------------------------------------------------
Metadata:
Packets: 1500
Bytes: 122.07 KB
Flows: 25
Destinations: 12
graph TB
subgraph "Capture Layer"
A[Network Interface] --> B[AF_PACKET Engine]
B --> C[Packet Channel]
end
subgraph "Processing Layer"
C --> D[Flow Aggregator]
D --> E[Feature Extractors]
E --> F[Timing]
E --> G[DNS]
E --> H[Periodicity]
E --> I[Burst]
E --> J[TLS]
end
subgraph "Analysis Layer"
F & G & H & I & J --> K[Fingerprint Builder]
K --> L[Baseline Storage]
K --> M[Drift Analyzer]
M --> N[Alert Engine]
end
subgraph "Output Layer"
N --> O[CLI Output]
N --> P[JSON Export]
L --> Q[SQLite/JSON]
end
style A fill:#e1f5fe
style O fill:#fff3e0
style P fill:#fff3e0
sequenceDiagram
participant NIC as Network Interface
participant Capture as Capture Engine
participant Flow as Flow Aggregator
participant Features as Feature Extractors
participant Fingerprint as Fingerprint Builder
participant Storage as Baseline Storage
participant Drift as Drift Analyzer
participant Alert as Alert Engine
NIC->>Capture: Raw Packets
Capture->>Flow: Parsed Packets
Flow->>Flow: Aggregate by Host
Flow->>Features: Flow Records
Features->>Features: Extract Timing
Features->>Features: Extract DNS
Features->>Features: Extract Periodicity
Features->>Features: Extract Burst
Features->>Fingerprint: Feature Vector
Fingerprint->>Storage: Persist Baseline
Fingerprint->>Drift: Compare to Baseline
alt Drift Detected
Drift->>Alert: Generate Alert
Alert->>Alert: Apply Rules
Alert-->>Output: Structured Alert
else Normal Behavior
Drift-->>Output: Status OK
end
graph LR
subgraph "Internal Packages"
capture[capture]
flow[flow]
features[features]
fingerprint[fingerprint]
drift[drift]
alert[alert]
storage[storage]
end
subgraph "Utility Packages"
logger[logger]
utils[utils]
end
subgraph "External Dependencies"
gopacket[gopacket]
cobra[cobra]
sqlite3[sqlite3]
end
capture --> gopacket
flow --> capture
features --> flow
fingerprint --> features
drift --> fingerprint
alert --> drift
storage --> fingerprint
storage --> sqlite3
logger -.-> capture
logger -.-> flow
logger -.-> alert
Used for DNS query analysis and payload characterization.
Formula:
H = -Σ p(x) log₂ p(x)
Implementation:
func ComputeEntropy(data []byte) float64 {
freq := make(map[byte]int)
for _, b := range data {
freq[b]++
}
entropy := 0.0
total := float64(len(data))
for _, count := range freq {
p := float64(count) / total
if p > 0 {
entropy -= p * math.Log2(p)
}
}
return entropy
}Interpretation:
| Entropy | Classification | Typical Use Case |
|---|---|---|
| 0-2 bits | Very Low | Structured protocols |
| 2-4 bits | Medium | Normal text/DNS |
| 4-6 bits | High | Compressed data |
| 6-8 bits | Very High | Encrypted/random |
Statistical measure of deviation from baseline.
Formula:
z = (x - μ) / σ
DriftIndex = WeightedMean(|z|)
Severity Classification:
func ClassifySeverity(driftIndex float64) Severity {
switch {
case driftIndex >= 5.0:
return SeverityCritical
case driftIndex >= 4.0:
return SeverityHigh
case driftIndex >= 3.0:
return SeverityMedium
case driftIndex >= 2.0:
return SeverityLow
default:
return SeverityNone
}
}Measures similarity between two fingerprint vectors.
Formula:
similarity = (A · B) / (||A|| × ||B||)
Implementation:
func CosineSimilarity(a, b map[string]float64) float64 {
var dot, normA, normB float64
for k, vA := range a {
normA += vA * vA
if vB, exists := b[k]; exists {
dot += vA * vB
}
}
for _, vB := range b {
normB += vB * vB
}
denom := math.Sqrt(normA) * math.Sqrt(normB)
if denom == 0 {
return 0
}
return dot / denom
}Identifies beaconing behavior through spectral analysis.
Algorithm:
- Collect inter-packet intervals
- Apply Hanning window
- Compute FFT (Cooley-Tukey)
- Find dominant frequency
- Calculate spectral dominance ratio
Beaconing Detection:
func DetectBeaconing(timestamps []time.Time) (confidence float64, period float64) {
detector := NewPeriodicityDetector(10*time.Minute, 500)
for _, t := range timestamps {
detector.AddPacket(t)
}
metrics := detector.Extract()
// High periodicity + low variation = beaconing
confidence = metrics.PeriodicityScore
if metrics.CoefficientOfVar < 0.1 {
confidence = math.Min(confidence+0.2, 1.0)
}
return confidence, metrics.DominantPeriod
}Measures traffic burstiness.
Formula:
burstScore = peakPacketsPerSecond / avgPacketsPerSecond
Classification:
| Score | Classification | Behavior |
|---|---|---|
| < 1.5 | Steady | Interactive traffic |
| 1.5-3 | Moderate | Mixed traffic |
| 3-5 | High | Automated traffic |
| > 5 | Extreme | Beaconing/bulk transfer |
# /etc/netdna/config.yaml
capture:
interface: eth0
snaplen: 65536
promisc: true
timeout: 1s
aggregation:
window_duration: 10m
max_inter_arrivals: 1000
max_timestamps: 500
drift:
threshold: 3.0
severity_levels:
low: 2.0
medium: 3.0
high: 4.0
critical: 5.0
storage:
baseline_path: /var/lib/netdna/baselines
sqlite_path: /var/lib/netdna/netdna.db
logging:
level: info
json: false
output: /var/log/netdna/netdna.log| Variable | Default | Description |
|---|---|---|
NETDNA_CONFIG |
/etc/netdna/config.yaml |
Config file path |
NETDNA_LOG_LEVEL |
info |
Log level |
NETDNA_OUTPUT_DIR |
/var/lib/netdna |
Output directory |
# List available interfaces
ip link show
# Verify interface is up
sudo ip link set eth0 up
# Check interface permissions
ip link show eth0# Option 1: Run as root
sudo ./netdna observe -i eth0
# Option 2: Set capabilities
sudo setcap cap_net_raw,cap_net_admin=eip ./netdna
# Option 3: Add user to netdev group
sudo usermod -aG netdev $USER# Reduce window size
./netdna observe -i eth0 --window 5m
# Reduce buffer sizes in config
# aggregation.max_inter_arrivals: 500
# aggregation.max_timestamps: 250# Verify traffic on interface
tcpdump -i eth0 -c 10
# Check BPF filter syntax
./netdna observe -i eth0 --filter "tcp port 80"
# Try without filter first
./netdna observe -i eth0 --filter ""# Enable verbose logging
./netdna observe -i eth0 --verbose
# JSON output for debugging
./netdna fingerprint --host 192.168.1.1 --json
# Check baseline file validity
cat baseline.json | jq .NetDNA/
├── cmd/ # CLI commands
│ ├── root.go # Root command setup
│ ├── observe.go # observe command
│ ├── fingerprint.go # fingerprint command
│ ├── drift.go # drift command
│ ├── compare.go # compare command
│ ├── baseline.go # baseline command
│ └── inspect.go # inspect command
├── internal/ # Private packages
│ ├── capture/ # Packet capture
│ ├── flow/ # Flow aggregation
│ ├── features/ # Feature extraction
│ ├── fingerprint/ # Fingerprint construction
│ ├── drift/ # Drift analysis
│ ├── alert/ # Alert engine
│ └── storage/ # Persistence
├── pkg/ # Public packages
│ ├── logger/ # Logging
│ └── utils/ # Utilities
├── configs/ # Example configs
├── docs/ # Documentation
└── main.go # Entry point
# Standard build
go build -o netdna .
# Build with race detector
go build -race -o netdna .
# Build for production
CGO_ENABLED=0 go build -ldflags="-s -w" -o netdna .
# Cross-compile for Linux ARM64
GOOS=linux GOARCH=arm64 go build -o netdna-arm64 .# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Run specific package tests
go test ./internal/features/...
# Benchmark tests
go test -bench=. ./internal/drift/...-
New Feature Extractor (
internal/features/):package features // NewFeature extracts custom metrics func NewFeature(data []byte) float64 { // Implementation }
-
Register in Fingerprint Builder (
internal/fingerprint/builder.go):func (b *Builder) Build(...) *Fingerprint { // Add new feature extraction features["new_feature"] = features.NewFeature(data) }
-
Add CLI Flag (
cmd/):cmd.Flags().Float64("new-threshold", 1.0, "New feature threshold")
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Go best practices (
go fmt,go vet) - Write tests for new functionality
- Document public APIs with godoc comments
- Keep functions focused and small
- Avoid global state
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests pass
- [ ] Manual testing completed
## Checklist
- [ ] Code follows project guidelines
- [ ] Self-review completed
- [ ] Comments added where necessary
- [ ] Documentation updatedNetDNA is designed as a passive-only system:
- ❌ No packet injection
- ❌ No active scanning
- ❌ No network modification
- ✅ Capture and analyze only
- Baseline files may contain sensitive network information
- Store baselines with appropriate permissions (0600)
- Consider encrypting baseline data at rest
- Implement log rotation for capture logs
All CLI inputs are validated:
- BPF filter expressions are sanitized
- File paths are validated
- IP addresses are parsed safely
- No shell command injection vectors
capture:
# Increase ring buffer for high traffic
block_size: 2097152 # 2MB blocks
num_blocks: 256 # 512MB total buffer
# Reduce for low-traffic environments
block_size: 524288 # 512KB blocks
num_blocks: 64 # 32MB total buffer| Setting | Low Memory | Standard | High Performance |
|---|---|---|---|
max_inter_arrivals |
250 | 1000 | 5000 |
max_timestamps |
100 | 500 | 2000 |
window_duration |
5m | 10m | 30m |
# Pin to specific CPU cores
taskset -c 0-3 ./netdna observe -i eth0
# Increase process priority
nice -n -10 ./netdna observe -i eth0Q: Can NetDNA detect encrypted C2 traffic?
A: Yes, through behavioral analysis. While payload content is encrypted, timing patterns, packet sizes, and periodicity can indicate automated C2 beaconing.
Q: Does NetDNA work with encrypted DNS (DoH/DoT)?
A: Behavioral metrics still apply (timing, burst, periodicity), but DNS-specific entropy analysis requires plaintext DNS.
Q: What is the minimum hardware requirement?
A: NetDNA can run on modest hardware (2 CPU, 4GB RAM) for typical enterprise traffic. High-traffic environments benefit from more resources.
Q: Can I integrate NetDNA with my SIEM?
A: Yes, use JSON output mode (--json flag) and forward to your SIEM via syslog or file monitoring.
Q: How often should baselines be updated?
A: Baselines should be refreshed periodically (weekly/monthly) to account for normal network changes. Use the baseline merge command to combine multiple observations.
This project is licensed under the MIT License - see the LICENSE file for details.
Copyright (c) 2026 NetDNA Project
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
NetDNA - Behavioral Network Fingerprinting & Drift Intelligence Engine