Major features: - Extension enumeration detection with 3 detection algorithms: - Max unique extensions threshold (default: 20 in 5 min) - Sequential pattern detection (e.g., 100,101,102...) - Rapid-fire detection (many extensions in short window) - Prometheus metrics for all SIP Guardian operations - SQLite persistent storage for bans and attack history - Webhook notifications for ban/unban/suspicious events - GeoIP-based country blocking with continent shortcuts - Per-method rate limiting with token bucket algorithm Bug fixes: - Fix whitelist count always reporting zero in stats - Fix whitelisted connections metric never incrementing - Fix Caddyfile config not being applied to shared guardian New files: - enumeration.go: Extension enumeration detector - enumeration_test.go: 14 comprehensive unit tests - metrics.go: Prometheus metrics handler - storage.go: SQLite persistence layer - webhooks.go: Webhook notification system - geoip.go: MaxMind GeoIP integration - ratelimit.go: Per-method rate limiting Testing: - sandbox/ contains complete Docker Compose test environment - All 14 enumeration tests pass
220 lines
5.4 KiB
YAML
220 lines
5.4 KiB
YAML
# SIP Guardian Testing Sandbox
|
|
#
|
|
# This provides a complete testing environment with:
|
|
# - FreePBX (real PBX for testing)
|
|
# - Caddy with SIP Guardian (the proxy under test)
|
|
# - Attack containers (sipvicious, custom scripts)
|
|
# - Valid client containers (pjsip for legitimate traffic)
|
|
#
|
|
# Usage:
|
|
# docker compose up -d
|
|
# docker compose logs -f caddy
|
|
# docker compose run --rm attacker sipvicious_svwar -e100-200 caddy
|
|
# docker compose run --rm client pjsua --registrar=sip:caddy
|
|
|
|
services:
|
|
# ============================================
|
|
# FreePBX - The Protected PBX
|
|
# ============================================
|
|
freepbx:
|
|
image: tiredofit/freepbx:latest
|
|
container_name: sandbox-freepbx
|
|
hostname: freepbx
|
|
restart: unless-stopped
|
|
privileged: true
|
|
environment:
|
|
- VIRTUAL_HOST=pbx.sandbox.local
|
|
- VIRTUAL_NETWORK=sandbox
|
|
- HTTP_PORT=80
|
|
- HTTPS_PORT=443
|
|
- UCP_FIRST_RUN=true
|
|
- DB_HOST=mariadb
|
|
- DB_PORT=3306
|
|
- DB_NAME=asterisk
|
|
- DB_USER=asterisk
|
|
- DB_PASS=asteriskpass
|
|
- ENABLE_FAIL2BAN=FALSE # We're replacing this!
|
|
- TZ=UTC
|
|
volumes:
|
|
- freepbx_data:/data
|
|
- freepbx_logs:/var/log
|
|
- freepbx_www:/var/www/html
|
|
depends_on:
|
|
- mariadb
|
|
networks:
|
|
sandbox:
|
|
ipv4_address: 10.55.0.10
|
|
|
|
mariadb:
|
|
image: mariadb:10.11
|
|
container_name: sandbox-mariadb
|
|
restart: unless-stopped
|
|
environment:
|
|
- MYSQL_ROOT_PASSWORD=rootpass
|
|
- MYSQL_DATABASE=asterisk
|
|
- MYSQL_USER=asterisk
|
|
- MYSQL_PASSWORD=asteriskpass
|
|
volumes:
|
|
- mariadb_data:/var/lib/mysql
|
|
networks:
|
|
sandbox:
|
|
ipv4_address: 10.55.0.11
|
|
|
|
# ============================================
|
|
# Caddy with SIP Guardian - The Proxy
|
|
# ============================================
|
|
caddy:
|
|
build:
|
|
context: ..
|
|
dockerfile: Dockerfile
|
|
container_name: sandbox-caddy
|
|
hostname: caddy
|
|
restart: unless-stopped
|
|
# Override default command to use explicit Caddyfile (ENTRYPOINT is "caddy")
|
|
command: ["run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
|
|
ports:
|
|
# Expose SIP ports to host for external testing
|
|
- "5060:5060/udp"
|
|
- "5060:5060/tcp"
|
|
- "5061:5061/tcp"
|
|
# Admin API
|
|
- "2020:2020"
|
|
volumes:
|
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
- caddy_data:/data
|
|
- caddy_config:/config
|
|
environment:
|
|
- SIP_UPSTREAM_HOST=freepbx
|
|
- SIP_UPSTREAM_PORT=5060
|
|
- SIP_UPSTREAM_TLS_PORT=5061
|
|
networks:
|
|
sandbox:
|
|
ipv4_address: 10.55.0.2
|
|
depends_on:
|
|
- freepbx
|
|
|
|
# ============================================
|
|
# Attack Simulation Containers
|
|
# ============================================
|
|
|
|
# SIPVicious scanner - for testing scanner detection
|
|
attacker:
|
|
image: python:3.11-slim
|
|
container_name: sandbox-attacker
|
|
hostname: attacker
|
|
profiles:
|
|
- testing
|
|
command: >
|
|
bash -c "
|
|
pip install sipvicious pysip3 &&
|
|
echo 'SIPVicious and tools installed. Use: sipvicious_svwar, sipvicious_svcrack, sipvicious_svmap' &&
|
|
tail -f /dev/null
|
|
"
|
|
networks:
|
|
sandbox:
|
|
ipv4_address: 10.55.0.100
|
|
depends_on:
|
|
- caddy
|
|
|
|
# Brute force simulation
|
|
bruteforcer:
|
|
image: python:3.11-slim
|
|
container_name: sandbox-bruteforcer
|
|
hostname: bruteforcer
|
|
profiles:
|
|
- testing
|
|
volumes:
|
|
- ./scripts:/scripts:ro
|
|
command: >
|
|
bash -c "
|
|
pip install sipsimple requests &&
|
|
echo 'Brute force tools ready. Run: python /scripts/bruteforce.py' &&
|
|
tail -f /dev/null
|
|
"
|
|
networks:
|
|
sandbox:
|
|
ipv4_address: 10.55.0.101
|
|
depends_on:
|
|
- caddy
|
|
|
|
# ============================================
|
|
# Legitimate Client Containers
|
|
# ============================================
|
|
|
|
# PJSIP-based SIP client
|
|
client:
|
|
image: alpine:latest
|
|
container_name: sandbox-client
|
|
hostname: client
|
|
profiles:
|
|
- testing
|
|
command: >
|
|
sh -c "
|
|
apk add --no-cache pjsua netcat-openbsd curl jq &&
|
|
echo 'PJSIP client ready. Use pjsua for SIP registration.' &&
|
|
tail -f /dev/null
|
|
"
|
|
networks:
|
|
sandbox:
|
|
ipv4_address: 10.55.0.50
|
|
depends_on:
|
|
- caddy
|
|
|
|
# Linphone CLI client
|
|
linphone:
|
|
image: alpine:latest
|
|
container_name: sandbox-linphone
|
|
hostname: linphone
|
|
profiles:
|
|
- testing
|
|
command: >
|
|
sh -c "
|
|
apk add --no-cache linphone netcat-openbsd curl &&
|
|
echo 'Linphone ready.' &&
|
|
tail -f /dev/null
|
|
"
|
|
networks:
|
|
sandbox:
|
|
ipv4_address: 10.55.0.51
|
|
depends_on:
|
|
- caddy
|
|
|
|
# ============================================
|
|
# Monitoring & Debugging
|
|
# ============================================
|
|
|
|
# Network sniffer for SIP traffic analysis
|
|
tcpdump:
|
|
image: alpine:latest
|
|
container_name: sandbox-tcpdump
|
|
hostname: tcpdump
|
|
profiles:
|
|
- debug
|
|
cap_add:
|
|
- NET_ADMIN
|
|
- NET_RAW
|
|
network_mode: "service:caddy"
|
|
command: >
|
|
sh -c "
|
|
apk add --no-cache tcpdump &&
|
|
tcpdump -i any -n 'udp port 5060 or tcp port 5060 or tcp port 5061' -vvv
|
|
"
|
|
depends_on:
|
|
- caddy
|
|
|
|
volumes:
|
|
freepbx_data:
|
|
freepbx_logs:
|
|
freepbx_www:
|
|
mariadb_data:
|
|
caddy_data:
|
|
caddy_config:
|
|
|
|
networks:
|
|
sandbox:
|
|
driver: bridge
|
|
ipam:
|
|
config:
|
|
- subnet: 10.55.0.0/24
|
|
gateway: 10.55.0.1
|