# 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 ```bash # Build the custom Caddy image make build # Start the stack make run # View logs make logs # Run tests make test ``` ## Configuration ### Complete Caddyfile Example ```caddyfile { 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: ```caddyfile 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:** 1. **Count Threshold**: Too many unique extensions from one IP 2. **Sequential Pattern**: Consecutive numeric extensions indicate scanning 3. **Rapid Fire**: High-speed probing is clearly automated ### SIP Message Validation Enforces RFC 3261 compliance and blocks malformed/malicious packets: ```caddyfile 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: ```caddyfile 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: └─ 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 ```bash curl http://localhost:2020/api/sip-guardian/bans ``` ### View Stats ```bash curl http://localhost:2020/api/sip-guardian/stats ``` Response: ```json { "total_requests": 15234, "blocked_requests": 423, "active_bans": 12, "enumeration_detections": 5, "validation_failures": 89, "rate_limited": 156 } ``` ### Manually Ban IP ```bash 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 ```bash curl -X DELETE http://localhost:2020/api/sip-guardian/unban/192.168.1.100 ``` ### View Enumeration Stats ```bash curl http://localhost:2020/api/sip-guardian/enumeration/stats ``` ### View Validation Stats ```bash 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 ```bash # 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 ```bash # 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 ```caddyfile { 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) ```caddyfile { 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 ```caddyfile { 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 1. **Whitelist Internal Networks**: Always whitelist your internal networks to prevent self-blocking 2. **Start Permissive**: Begin with permissive validation mode and tighten after monitoring 3. **Monitor False Positives**: Watch metrics for legitimate traffic being blocked 4. **Regular Updates**: Keep GeoIP databases current 5. **Webhook Alerts**: Configure webhooks for immediate security event notification ## License MIT ## Contributing Contributions welcome! Please see CONTRIBUTING.md for guidelines. ## Related Projects - [caddy-l4](https://github.com/mholt/caddy-l4) - Layer 4 proxy for Caddy - [Caddy](https://caddyserver.com/) - The HTTP/2 web server with automatic HTTPS - [SIPVicious](https://github.com/EnableSecurity/sipvicious) - SIP security testing tools