Private
Public Access
2
0
Files
bgwaf/ansible/roles/waf_config/templates/Caddyfile
2026-01-19 21:00:14 +03:00

153 lines
4.4 KiB
Caddyfile

{
grace_period 10s
order coraza_waf first
{% if waf_config_email | default(None) != None %}
email "{{ waf_config_email }}"
{% endif %}
{% if waf_config_ca_root | default(None) != None %}
tls {
ca_root "{{ waf_config_ca_root }}"
}
{% endif %}
log waf {
format json
include "http.handlers.waf"
output stdout
}
{% if waf_config_local_ca_name | default(None) != None %}
pki {
ca local {
name "{{ waf_config_local_ca_name }}"
}
}
{% endif %}
}
{% for site in waf_config_sites %}
{% if (site.redirect_from_aliases | default(true)) and (site.aliases | default([]) | length) > 0 %}
{{ site.aliases | join(', ') }} {
redir https://{{ site.site }}{uri}
}
{% else %}
{% for alias in site.aliases | default([]) %}
{{ alias }},
{% endfor %}
{% endif %}
{{ site.site }} {
encode gzip zstd
{% for path in site.paths %}
handle {{ path.path | default('*') }} {
reverse_proxy {
to {{ path.addrs | join(' ') }}
header_up X-Real-IP {remote}
lb_policy ip_hash
# Active checks
# health_uri /
# health_interval 10s
# health_timeout 5s
# health_status 200
# Passive checks
fail_duration 30s
max_fails 3
unhealthy_latency 2000ms
transport http {
# tls_server_name {host}
# tls_insecure_skip_verify
}
}
}
{% endfor %}
{% if site.custom_cert | default (false) %}
tls {{ site.custom_cert_file }} {{ site.custom_key_file }}
{% endif %}
{% if site.blacklist | default([]) | length > 0 %}
@blocked {
{% for ip in site.blacklist | default([]) %}
remote_ip {{ ip }}
{% endfor %}
}
respond @blocked "Access Denied" 403
{% endif %}
{% if site.bot_barrier | default (false) %}
bot_barrier {
secret {{ waf_config_bot_barrier_secret }}
complexity 18
valid_for 30m
seed_cookie_name __chall_{{ site.name }}_seed
solution_cookie_name __chall_{{ site.name }}_solution
mac_cookie_name __chall_{{ site.name }}_mac
template /etc/caddy/bot_barrier_template.html
}
{% endif %}
rate_limit {
# distributed
zone remote_ip {
key {remote.ip}
events {{ site.rate_events | default('1000') }}
window {{ site.rate_window | default('1m') }}
}
}
coraza_waf {
load_owasp_crs
directives `
Include "/etc/caddy/sites/{{ site.name }}/coraza.conf"
Include "/etc/caddy/sites/{{ site.name }}/crs-setup.conf"
{% for plugin in site.plugins | default(waf_config_defaults.plugins) %}
Include "/etc/caddy/plugins/{{ plugin }}-config.conf"
Include "/etc/caddy/plugins/{{ plugin }}-before.conf"
{% endfor %}
Include "/etc/caddy/sites/{{ site.name }}/exclusions-request-before.conf"
Include "/etc/caddy/coreruleset-{{ waf_config_owasp_crs_version }}/rules/*.conf"
Include "/etc/caddy/sites/{{ site.name }}/exclusions-response-after.conf"
{% for plugin in site.plugins | default(waf_config_defaults.plugins) %}
Include "/etc/caddy/plugins/{{ plugin }}-after.conf"
{% endfor %}
SecRuleEngine On
`
}
# Cf. https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html
header {
# Access-Control-Allow-Origin "https://secure.gravatar.com"
Content-Security-Policy "upgrade-insecure-requests; worker-src 'self' blob:; connect-src 'self'; media-src 'self'; img-src 'self' data: https://secure.gravatar.com/avatar/; font-src 'self' data:; style-src 'self' 'unsafe-inline'; object-src 'none'; frame-src 'self' blob:; child-src 'self'; form-action 'self'; frame-ancestors 'self'"
# Cross-Origin-Embedder-Policy "require-corp"
Cross-Origin-Opener-Policy "same-origin"
Cross-Origin-Resource-Policy "same-site"
Permissions-Policy "geolocation=(), camera=(), microphone=(), interest-cohort=()"
Referrer-Policy "strict-origin-when-cross-origin"
Strict-Transport-Security "max-age=2635200; includeSubDomains"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
X-Robots-Tag "noindex, nofollow"
?Content-Type "text/html; charset=UTF-8"
>Set-Cookie "(.*)" "$1; SameSite=None; Secure;"
-Server
-Via
-X-Powered-By
-X-AspNet-Version
-X-AspNetMvc-Version
}
handle_errors 403 {
header X-Blocked "true"
respond "Your request was blocked."
}
log {
format json
output file /var/log/caddy/site_{{ site.name }}.log
}
}
{% endfor %}