Synit WAF
Beispielkonfigurationen
Kundensichere Beispielkonfigurationen für Synit WAF: Basic, Intermediate, Advanced, Optimized, Docker Swarm, API-Profil, WordPress-Profil und CRS-Grundeinstellungen.
Beispielkonfigurationen
Diese Beispiele sind Startpunkte für eigene Konfigurationen. Sie nutzen .example.test Domains und Platzhalter. Übernehmen Sie keine Secrets, Tokens, Passwort-Hashes oder internen Hostnamen in öffentliche Repositories.
Starten Sie neue Profile im Audit Mode. Aktivieren Sie Blocking erst, wenn Logs, False Positives, Rollback und Supportweg geprüft sind.
Basic: erste Website oder Portalstrecke
Datei: config.basic.yml
global_settings:
log_level: "INFO"
response_buffer_limit: 1048576
read_timeout: "15s"
write_timeout: "15s"
idle_timeout: "60s"
global_rate_limit:
requests_per_minute: 2000
burst: 500
trust_forwarded_for: false
license:
key: "<product-access-key>"
server_url: "<validation-url-from-handoff>"
waf_rule_sets:
"base-protection": |
SecRule REQUEST_METHOD "@rx (?i:^(trace|track)$)" "id:110001,phase:1,deny,status:403,log,msg:'Blocked unsafe HTTP method'"
SecRule ARGS|REQUEST_URI "@rx (?i:(\\bunion\\b.{0,20}\\bselect\\b|\\bor\\b\\s+1=1|\\bdrop\\b\\s+table\\b))" "id:110002,phase:2,deny,status:403,log,msg:'Blocked SQL injection pattern'"
SecRule ARGS|REQUEST_URI "@rx (?i:(\\.\\./|%2e%2e%2f|%2e%2e/|/etc/passwd))" "id:110003,phase:2,deny,status:403,log,msg:'Blocked traversal pattern'"
tenants:
"www.example.test":
upstreams:
- url: "http://website:8080"
security:
waf_enabled: true
audit_mode: true
paranoia_level: 1
include_rule_sets:
- "base-protection"
Intermediate: API plus CrowdSec
Datei: config.intermediate.yml
global_settings:
log_level: "INFO"
response_buffer_limit: 1048576
read_timeout: "15s"
write_timeout: "15s"
idle_timeout: "60s"
license:
key: "<product-access-key>"
server_url: "<validation-url-from-handoff>"
crowdsec:
api_url: "http://crowdsec:8080/"
api_key: "<crowdsec-bouncer-key>"
waf_rule_sets:
"base-protection": |
SecRule REQUEST_METHOD "@rx (?i:^(trace|track)$)" "id:110001,phase:1,deny,status:403,log,msg:'Blocked unsafe HTTP method'"
SecRule ARGS|REQUEST_URI "@rx (?i:(\\bunion\\b.{0,20}\\bselect\\b|\\bor\\b\\s+1=1|\\bdrop\\b\\s+table\\b))" "id:110002,phase:2,deny,status:403,log,msg:'Blocked SQL injection pattern'"
SecRule ARGS|REQUEST_URI "@rx (?i:(\\.\\./|%2e%2e%2f|%2e%2e/|/etc/passwd))" "id:110003,phase:2,deny,status:403,log,msg:'Blocked traversal pattern'"
"advanced-protection": |
SecRule REQUEST_METHOD "@rx (?i:^(trace|track)$)" "id:120001,phase:1,deny,status:403,log,msg:'Blocked unsafe HTTP method'"
SecRule ARGS|REQUEST_URI "@rx (?i:(\\bunion\\b.{0,20}\\bselect\\b|\\bor\\b\\s+1=1|\\bdrop\\b\\s+table\\b))" "id:120002,phase:2,deny,status:403,log,msg:'Blocked SQL injection pattern'"
SecRule ARGS|REQUEST_URI "@rx (?i:(\\.\\./|%2e%2e%2f|%2e%2e/|/etc/passwd))" "id:120003,phase:2,deny,status:403,log,msg:'Blocked traversal pattern'"
SecRule REQUEST_HEADERS:User-Agent "@rx (?i:(sqlmap|nikto|acunetix|nessus|masscan|nmap))" "id:120004,phase:1,deny,status:403,log,msg:'Blocked scanner user-agent'"
tenants:
"api.example.test":
upstreams:
- url: "http://api-service:3000"
security:
waf_enabled: true
audit_mode: true
paranoia_level: 2
crowdsec_enabled: true
include_rule_sets:
- "advanced-protection"
"www.example.test":
upstreams:
- url: "http://frontend-service:80"
security:
waf_enabled: true
audit_mode: true
paranoia_level: 1
crowdsec_enabled: true
include_rule_sets:
- "base-protection"
custom_rules: |
SecRule REQUEST_HEADERS:User-Agent "@contains BadBot/1.0" "id:220001,phase:1,deny,status:403,log,msg:'Blocked custom bad bot for website'"
Advanced: Adminbereich, GeoIP und Header
Datei: config.advanced.yml
global_settings:
log_level: "DEBUG"
response_buffer_limit: 2097152
read_timeout: "20s"
write_timeout: "20s"
idle_timeout: "120s"
global_rate_limit:
requests_per_minute: 5000
burst: 1000
trust_forwarded_for: true
ip_sets:
allow_list:
- "10.0.0.0/8"
block_list:
- "192.0.2.10/32"
acme:
enabled: true
email: "security@example.test"
storage_path: "/etc/waf/certs/acme"
staging: true
dns_provider: "cloudflare"
dns_token: "<dns-api-token>"
logging:
access_log:
enabled: true
path: "/var/log/waf/access-%yyyy-%MM-%dd.log"
format: "json"
error_log:
enabled: true
path: "/var/log/waf/error.log"
format: "text"
license:
key: "<product-access-key>"
server_url: "<validation-url-from-handoff>"
crowdsec:
api_url: "http://crowdsec:8080/"
api_key: "<crowdsec-bouncer-key>"
geoip:
db_path: "/etc/waf/geoip/GeoLite2-Country.mmdb"
waf_rule_sets:
"optimized-protection": |
SecRule REQUEST_METHOD "@rx (?i:^(trace|track)$)" "id:130001,phase:1,deny,status:403,log,msg:'Blocked unsafe HTTP method'"
SecRule ARGS|REQUEST_URI "@rx (?i:(\\bunion\\b.{0,20}\\bselect\\b|\\bor\\b\\s+1=1|\\bdrop\\b\\s+table\\b|\\bwaitfor\\s+delay\\b))" "id:130002,phase:2,deny,status:403,log,msg:'Blocked SQL injection pattern'"
SecRule ARGS|REQUEST_URI "@rx (?i:(\\.\\./|%2e%2e%2f|%2e%2e/|/etc/passwd|/proc/self/environ))" "id:130003,phase:2,deny,status:403,log,msg:'Blocked traversal pattern'"
SecRule REQUEST_HEADERS:User-Agent "@rx (?i:(sqlmap|nikto|acunetix|nessus|masscan|nmap|zgrab|nuclei))" "id:130004,phase:1,deny,status:403,log,msg:'Blocked scanner user-agent'"
SecRule REQUEST_URI "@rx (?i:(\\.env|\\.git/|composer\\.json|package-lock\\.json|backup\\.zip|dump\\.sql))" "id:130005,phase:2,deny,status:403,log,msg:'Blocked sensitive artifact access'"
tenants:
"app.example.test":
upstreams:
- url: "http://app-service:80"
upstreamInsecure: false
header_transform:
inject_request:
X-Synit-Tenant: "{{TENANT}}"
strip_response:
- "Server"
- "X-Powered-By"
security:
waf_enabled: true
audit_mode: true
circuit_breaker:
enabled: true
threshold: 5
cooldown: "30s"
failure_status_codes: [502, 503, 504]
response_masking:
- pattern: "(?i)(api[_-]?token=)[^&\\s]+"
replacement: "$1[redacted]"
block_page_url: "https://status.example.test/security-blocked"
jwt_validation:
enabled: true
jwks_endpoint: "https://auth.example.test/.well-known/jwks.json"
paranoia_level: 3
crowdsec_enabled: true
geoip_enabled: true
blocked_countries: ["RU", "CN"]
include_rule_sets:
- "optimized-protection"
"admin.example.test":
upstreams:
- url: "http://admin-service:80"
security:
waf_enabled: true
audit_mode: true
paranoia_level: 2
crowdsec_enabled: true
include_rule_sets:
- "optimized-protection"
basic_auth:
- user: "ops"
password: "<bcrypt-password-hash>"
"*.customer.example.test":
upstreams:
- url: "http://customer-platform-ingress:80"
security:
waf_enabled: true
audit_mode: true
paranoia_level: 2
crowdsec_enabled: true
include_rule_sets:
- "optimized-protection"
Optimized: getunte Produktion mit Geschäftsregeln
Datei: config.optimized.yml
global_settings:
log_level: "INFO"
response_buffer_limit: 4194304
read_timeout: "20s"
write_timeout: "20s"
idle_timeout: "120s"
logging:
access_log:
enabled: true
path: "/var/log/waf/access-%yyyy-%MM-%dd.log"
format: "json"
error_log:
enabled: true
path: "/var/log/waf/error-%yyyy-%MM-%dd.log"
format: "json"
license:
key: "<product-access-key>"
server_url: "<validation-url-from-handoff>"
crowdsec:
api_url: "http://crowdsec:8080/"
api_key: "<crowdsec-bouncer-key>"
geoip:
db_path: "/etc/waf/geoip/GeoLite2-Country.mmdb"
waf_rule_sets:
"optimized-protection": |
SecRule REQUEST_METHOD "@rx (?i:^(trace|track)$)" "id:130001,phase:1,deny,status:403,log,msg:'Blocked unsafe HTTP method'"
SecRule ARGS|REQUEST_URI "@rx (?i:(\\bunion\\b.{0,20}\\bselect\\b|\\bor\\b\\s+1=1|\\bdrop\\b\\s+table\\b|\\bwaitfor\\s+delay\\b))" "id:130002,phase:2,deny,status:403,log,msg:'Blocked SQL injection pattern'"
SecRule ARGS|REQUEST_URI "@rx (?i:(\\.\\./|%2e%2e%2f|%2e%2e/|/etc/passwd|/proc/self/environ))" "id:130003,phase:2,deny,status:403,log,msg:'Blocked traversal pattern'"
SecRule REQUEST_HEADERS:User-Agent "@rx (?i:(sqlmap|nikto|acunetix|nessus|masscan|nmap|zgrab|nuclei))" "id:130004,phase:1,deny,status:403,log,msg:'Blocked scanner user-agent'"
SecRule REQUEST_URI "@rx (?i:(\\.env|\\.git/|composer\\.json|package-lock\\.json|backup\\.zip|dump\\.sql))" "id:130005,phase:2,deny,status:403,log,msg:'Blocked sensitive artifact access'"
SecRule REQUEST_URI|ARGS "@rx (?i:(169\\.254\\.169\\.254|metadata\\.google\\.internal))" "id:130006,phase:2,deny,status:403,log,msg:'Blocked metadata endpoint access pattern'"
"business-core": |
SecRule REQUEST_URI "@rx ^/v[0-9]+/" "id:240001,phase:1,pass,log,msg:'Versioned API route observed'"
SecRule ARGS_NAMES "@rx (?i:(secret|token|api[_-]?key|private[_-]?key))" "id:240002,phase:2,deny,status:403,log,msg:'Sensitive argument name blocked'"
tenants:
"api.example.test":
upstreams:
- url: "http://api-service-a:8080"
- url: "http://api-service-b:8080"
security:
waf_enabled: true
audit_mode: true
paranoia_level: 2
crowdsec_enabled: true
geoip_enabled: true
blocked_countries: ["RU", "CN"]
include_rule_sets:
- "optimized-protection"
- "business-core"
custom_rules: |
SecRule REQUEST_HEADERS:X-Auth-Legacy "@rx .+" "id:240003,phase:1,deny,status:400,log,msg:'Deprecated auth header blocked'"
"admin.example.test":
upstreams:
- url: "http://admin-service:8080"
security:
waf_enabled: true
audit_mode: true
paranoia_level: 3
crowdsec_enabled: true
geoip_enabled: true
blocked_countries: ["RU", "CN"]
include_rule_sets:
- "optimized-protection"
basic_auth:
- user: "ops"
password: "<bcrypt-password-hash>"
"*.customer.example.test":
upstreams:
- url: "http://customer-ingress:80"
security:
waf_enabled: true
audit_mode: true
paranoia_level: 2
crowdsec_enabled: true
include_rule_sets:
- "optimized-protection"
Docker Swarm
Datei: swarm-stack.yml
version: "3.9"
services:
synit-waf:
image: <container-image>
environment:
EDGE_WAF_CONFIG: /etc/waf/config.yml
ports:
- target: 80
published: 80
protocol: tcp
mode: ingress
volumes:
- /etc/waf/config.yml:/etc/waf/config.yml:ro
- /etc/waf/rules:/etc/waf/rules:ro
- /etc/waf/geoip:/etc/waf/geoip:ro
- /etc/waf/certs:/etc/waf/certs:ro
networks:
- edge
- upstream
deploy:
replicas: 3
endpoint_mode: vip
update_config:
parallelism: 1
delay: 10s
order: start-first
rollback_config:
parallelism: 1
order: stop-first
restart_policy:
condition: on-failure
resources:
limits:
cpus: "1.0"
memory: 1024M
reservations:
cpus: "0.25"
memory: 256M
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80/healthz"]
interval: 30s
timeout: 5s
retries: 3
upstream-app:
image: hashicorp/http-echo:1.0.0
command: ["-listen=:5678", "-text=ok"]
networks:
- upstream
deploy:
replicas: 2
networks:
edge:
driver: overlay
attachable: true
upstream:
driver: overlay
attachable: true
Skalieren:
docker stack deploy -c swarm-stack.yml synit-waf-cluster
docker service scale synit-waf-cluster_synit-waf=5
API-Regelprofil
Datei: rules/profiles/api-strict.conf
SecRule REQUEST_METHOD "!@rx ^(GET|POST|PUT|DELETE|PATCH|OPTIONS)$" "id:210001,phase:1,deny,status:405,msg:'Method not allowed'"
SecRule REQUEST_METHOD "@rx ^(POST|PUT)$" "id:210002,phase:1,chain,deny,status:415,msg:'JSON Content-Type required'"
SecRule REQUEST_HEADERS:Content-Type "!@contains application/json" "t:none"
SecRule REQUEST_URI "@rx \\.(env|git|bak|sql)$" "id:210003,phase:1,deny,status:403,msg:'Blocked sensitive file access'"
Dieses Profil passt für JSON-APIs. Prüfen Sie Uploads, Webhooks und Form-Posts vor Blocking.
WordPress-Regelprofil
Datei: rules/profiles/wordpress.conf
SecRule REQUEST_URI "@contains /wp-admin/" "id:200001,phase:1,pass,nolog,ctl:ruleRemoveById=942100"
SecRule REQUEST_URI "@contains wp-config.php" "id:200002,phase:1,deny,status:403,msg:'Blocked access to wp-config.php'"
SecRule REQUEST_URI "@contains xmlrpc.php" "id:200003,phase:1,deny,status:403,msg:'Blocked access to xmlrpc.php'"
Passen Sie WordPress-Ausnahmen eng an. Admin- und Editor-Workflows sollten vor produktivem Blocking getestet werden.
CRS-Grundeinstellungen
Datei: rules/crs-setup.local.conf
SecAction \
"id:900000,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:tx.paranoia_level=1"
SecAction \
"id:900100,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:tx.critical_anomaly_score=5,\
setvar:tx.error_anomaly_score=4,\
setvar:tx.warning_anomaly_score=3,\
setvar:tx.notice_anomaly_score=2"
SecAction \
"id:900200,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'"
Paranoia-Level 1 ist ein sinnvoller Start. Höhere Level erhöhen Abdeckung und False-Positive-Risiko. Testen Sie sie zuerst in Staging oder mit einzelnen Tenants im Audit Mode.