Documents all new features: - Extension enumeration detection with config examples - SIP message validation rules and modes - Topology hiding (B2BUA-lite) with request/response flow diagrams - Complete Caddyfile configuration reference - Prometheus metrics reference - Admin API endpoints - Integration examples for FreePBX, Kamailio, and HA setups - Security considerations Architecture diagram updated to show full processing pipeline.
16 KiB
16 KiB
Caddy SIP Guardian
A comprehensive Caddy module providing SIP-aware security at Layer 4. Protects your VoIP infrastructure with intelligent rate limiting, attack detection, message validation, and topology hiding.
Features
Core Protection
- Layer 4 SIP Proxying: Handle SIP traffic (UDP/TCP/TLS) before it reaches your PBX
- Intelligent Rate Limiting: Per-method token bucket rate limiting with burst support
- Automatic Banning: Ban IPs that exceed failure thresholds
- Attack Detection: Detect common SIP scanning tools (SIPVicious, friendly-scanner, etc.)
- CIDR Whitelisting: Whitelist trusted networks
- GeoIP Blocking: Block traffic by country using MaxMind databases
Extension Enumeration Detection
- Count-based Detection: Block IPs probing too many unique extensions
- Sequential Pattern Detection: Detect numeric extension scanning (100, 101, 102...)
- Rapid-fire Detection: Catch high-speed enumeration attempts
- Configurable Exemptions: Whitelist common extensions like voicemail
SIP Message Validation
- RFC 3261 Compliance: Enforce required headers and message structure
- Injection Prevention: Block NULL bytes and binary injection attacks
- Content-Length Validation: Detect body/header mismatches
- Multiple Modes: Permissive, strict, or paranoid validation
Topology Hiding (B2BUA-lite)
- Via Header Rewriting: Hide internal proxy chain
- Contact Header Rewriting: Mask internal IP addresses
- Sensitive Header Stripping: Remove P-Asserted-Identity, Server, etc.
- Call-ID Anonymization: Prevent dialog correlation attacks
- Private IP Masking: Automatically hide RFC 1918 addresses
Observability
- Prometheus Metrics: Comprehensive metrics for monitoring
- Webhook Notifications: Real-time alerts for security events
- SQLite Persistence: Durable ban storage across restarts
- Admin API: RESTful API for management and stats
Architecture
Internet
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Caddy SIP Guardian (Layer 4) │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ 1. SIP Matcher - Identifies SIP traffic ││
│ │ 2. Ban Check - Reject banned IPs ││
│ │ 3. Whitelist Check - Skip checks for trusted IPs ││
│ │ 4. GeoIP Check - Block by country ││
│ │ 5. Validation - RFC 3261 compliance ││
│ │ 6. Pattern Detection - Scanner fingerprinting ││
│ │ 7. Enumeration Check - Extension scanning detection ││
│ │ 8. Rate Limiting - Per-method token buckets ││
│ │ 9. Topology Hiding - Header rewriting (optional) ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ FreePBX / Asterisk / Kamailio │
│ (Protected from scanners, enumeration, and topology leaks) │
└─────────────────────────────────────────────────────────────┘
Quick Start
# Build the custom Caddy image
make build
# Start the stack
make run
# View logs
make logs
# Run tests
make test
Configuration
Complete Caddyfile Example
{
layer4 {
# UDP SIP (standard port)
udp/:5060 {
@sip sip {
methods REGISTER INVITE OPTIONS ACK BYE CANCEL INFO NOTIFY SUBSCRIBE MESSAGE
}
route @sip {
sip_guardian {
# Core settings
max_failures 5
find_time 10m
ban_time 1h
whitelist 10.0.0.0/8 192.168.0.0/16
# GeoIP blocking (optional)
geoip_db /etc/caddy/GeoLite2-Country.mmdb
blocked_countries CN RU
# Per-method rate limiting
rate_limit {
register 10/s burst 20
invite 5/s burst 10
options 20/s burst 50
}
# Extension enumeration detection
enumeration {
max_extensions 20
extension_window 5m
sequential_threshold 5
rapid_fire_count 10
rapid_fire_window 30s
ban_time 2h
exempt_extensions 100 200 9999
}
# SIP message validation
validation {
enabled true
mode strict
max_message_size 65535
ban_on_null_bytes true
ban_on_binary_injection true
}
# Prometheus metrics
metrics {
enabled true
}
# Webhook notifications
webhooks {
url https://hooks.example.com/sip-alerts
events ban unban attack enumeration
}
# SQLite persistence
storage {
path /var/lib/caddy/sip_guardian.db
}
}
# Optional: Topology hiding
sip_topology_hider {
proxy_host 203.0.113.1
proxy_port 5060
upstream udp/192.168.1.100:5060
rewrite_via
rewrite_contact
strip_headers P-Preferred-Identity P-Asserted-Identity Server User-Agent
hide_private_ips
# anonymize_call_id # Optional: randomize Call-IDs
}
proxy udp/freepbx:5060
}
}
# TCP SIP
tcp/:5060 {
@sip sip
route @sip {
sip_guardian { ... }
proxy tcp/freepbx:5060
}
}
# SIP over TLS
tcp/:5061 {
@sip tls sni sip.example.com
route @sip {
sip_guardian { ... }
tls
proxy tcp/freepbx:5060
}
}
}
}
# Admin API
:2020 {
handle /api/sip-guardian/* {
sip_guardian_admin
}
# Prometheus metrics endpoint
handle /metrics {
metrics
}
}
Environment Variables
| Variable | Default | Description |
|---|---|---|
SIP_UPSTREAM_HOST |
freepbx |
Upstream SIP server hostname |
SIP_UPSTREAM_PORT |
5060 |
Upstream SIP port |
SIP_GUARDIAN_MAX_FAILURES |
5 |
Failures before ban |
SIP_GUARDIAN_FIND_TIME |
10m |
Time window for counting failures |
SIP_GUARDIAN_BAN_TIME |
1h |
Ban duration |
Feature Details
Extension Enumeration Detection
Protects against tools like SIPVicious svwar that scan for valid extensions:
enumeration {
max_extensions 20 # Ban after 20 unique extensions probed
extension_window 5m # Within this time window
sequential_threshold 5 # Ban if 5+ consecutive extensions (100,101,102...)
rapid_fire_count 10 # Ban if 10+ extensions in rapid_fire_window
rapid_fire_window 30s
ban_time 2h # Enumeration bans last longer
exempt_extensions 100 200 9999 # Don't count these (voicemail, etc.)
}
Detection Methods:
- Count Threshold: Too many unique extensions from one IP
- Sequential Pattern: Consecutive numeric extensions indicate scanning
- Rapid Fire: High-speed probing is clearly automated
SIP Message Validation
Enforces RFC 3261 compliance and blocks malformed/malicious packets:
validation {
enabled true
mode strict # permissive, strict, or paranoid
max_message_size 65535 # Reject oversized messages
ban_on_null_bytes true # Immediate ban for NULL byte injection
ban_on_binary_injection true
disabled_rules via_invalid_branch # Skip specific rules
}
Validation Modes:
- Permissive: Log violations, only block critical attacks
- Strict: Enforce RFC 3261 required headers
- Paranoid: Additional heuristics for edge cases
Validation Rules:
| Rule | Severity | Action |
|---|---|---|
null_bytes |
CRITICAL | Immediate ban |
binary_injection |
CRITICAL | Immediate ban |
missing_via |
HIGH | Count toward ban |
missing_from |
HIGH | Count toward ban |
missing_to |
HIGH | Count toward ban |
missing_call_id |
HIGH | Count toward ban |
missing_cseq |
HIGH | Count toward ban |
content_length_mismatch |
HIGH | Count toward ban |
oversized_message |
HIGH | Count toward ban |
invalid_request_uri |
MEDIUM | Reject only |
Topology Hiding
Hide your internal infrastructure from external attackers:
sip_topology_hider {
# Your public-facing address
proxy_host 203.0.113.1
proxy_port 5060
# Internal PBX (never exposed)
upstream udp/192.168.1.100:5060
# Enable Via header insertion
rewrite_via
# Replace internal Contact URIs with proxy address
rewrite_contact
# Remove headers that leak internal info
strip_headers P-Preferred-Identity P-Asserted-Identity Remote-Party-ID Server User-Agent X-Asterisk-HangupCause
# Replace RFC 1918 addresses in all headers
hide_private_ips
# Optional: Randomize Call-IDs (prevents dialog correlation)
# anonymize_call_id
}
What It Hides:
- Internal IP addresses (192.168.x.x, 10.x.x.x, 172.16-31.x.x)
- Via header chain revealing internal proxies
- Contact URIs pointing to internal hosts
- Server/User-Agent revealing software versions
- P-Asserted-Identity revealing internal extensions
Request Flow:
External UA → Caddy → Asterisk
│
└─ Adds Via: SIP/2.0/UDP proxy.example.com;branch=z9hG4bK...
└─ Rewrites Contact: <sip:proxy.example.com:5060>
└─ Strips: Server, P-Asserted-Identity
Response Flow:
Asterisk → Caddy → External UA
│
└─ Removes top Via (proxy's)
└─ Dialog state routes response correctly
Admin API
List Banned IPs
curl http://localhost:2020/api/sip-guardian/bans
View Stats
curl http://localhost:2020/api/sip-guardian/stats
Response:
{
"total_requests": 15234,
"blocked_requests": 423,
"active_bans": 12,
"enumeration_detections": 5,
"validation_failures": 89,
"rate_limited": 156
}
Manually Ban IP
curl -X POST http://localhost:2020/api/sip-guardian/ban/192.168.1.100 \
-H "Content-Type: application/json" \
-d '{"reason": "manual_ban", "duration": "24h"}'
Unban IP
curl -X DELETE http://localhost:2020/api/sip-guardian/unban/192.168.1.100
View Enumeration Stats
curl http://localhost:2020/api/sip-guardian/enumeration/stats
View Validation Stats
curl http://localhost:2020/api/sip-guardian/validation/stats
Prometheus Metrics
# Core metrics
sip_guardian_requests_total{method="REGISTER"}
sip_guardian_blocked_total{reason="banned"}
sip_guardian_active_bans
# Rate limiting
sip_guardian_rate_limited_total{method="INVITE"}
# Enumeration detection
sip_guardian_enumeration_detections_total{reason="sequential_pattern"}
sip_guardian_enumeration_tracked_ips
# Validation
sip_guardian_validation_violations_total{rule="missing_via"}
sip_guardian_validation_results_total{result="valid"}
sip_guardian_message_size_bytes
# GeoIP
sip_guardian_geoip_blocked_total{country="CN"}
Detected Attack Patterns
The module automatically detects and flags:
- SIPVicious (
sipvicious,friendly-scanner) - SIPScan (
sip-scan,sipcli) - Asterisk scanners (
Asterisk PBX) - Common test extensions (100, 1000, 9999)
- Sequential extension probing
- NULL byte injection
- Binary payload injection
Building from Source
# Using xcaddy
xcaddy build \
--with github.com/mholt/caddy-l4 \
--with git.supported.systems/rsp2k/caddy-sip-guardian
# Or with local development
xcaddy build \
--with github.com/mholt/caddy-l4 \
--with git.supported.systems/rsp2k/caddy-sip-guardian=/path/to/local/module
Testing
# Run all unit tests
make test
# Test enumeration detection
make test-enumeration
# Test validation
make test-validation
# Test with SIPVicious (in sandbox)
make sandbox-up
make test-scanner
Integration Examples
With FreePBX/Asterisk
{
layer4 {
udp/:5060 {
@sip sip
route @sip {
sip_guardian {
max_failures 3
ban_time 24h
whitelist 10.0.0.0/8
}
proxy udp/freepbx:5060
}
}
}
}
With Kamailio (as SBC)
{
layer4 {
udp/:5060 {
@sip sip
route @sip {
sip_guardian { ... }
sip_topology_hider {
proxy_host sbc.example.com
proxy_port 5060
upstream udp/kamailio:5060
rewrite_via
rewrite_contact
}
proxy udp/kamailio:5060
}
}
}
}
High Availability Setup
{
layer4 {
udp/:5060 {
@sip sip
route @sip {
sip_guardian {
storage {
# Shared storage for HA
path /shared/sip_guardian.db
}
}
# Load balance across PBX cluster
proxy udp/pbx1:5060 udp/pbx2:5060 udp/pbx3:5060 {
lb_policy round_robin
health_check interval=30s
}
}
}
}
}
Security Considerations
- Whitelist Internal Networks: Always whitelist your internal networks to prevent self-blocking
- Start Permissive: Begin with permissive validation mode and tighten after monitoring
- Monitor False Positives: Watch metrics for legitimate traffic being blocked
- Regular Updates: Keep GeoIP databases current
- Webhook Alerts: Configure webhooks for immediate security event notification
License
MIT
Contributing
Contributions welcome! Please see CONTRIBUTING.md for guidelines.
Related Projects
- caddy-l4 - Layer 4 proxy for Caddy
- Caddy - The HTTP/2 web server with automatic HTTPS
- SIPVicious - SIP security testing tools