Private
Public Access
2
0

caddy: refact variables name, global options, add caddy_my_name

This commit is contained in:
2026-01-23 11:20:54 +03:00
parent 69b4bb6c88
commit c217cc8d7c
11 changed files with 560 additions and 505 deletions

View File

@@ -11,8 +11,8 @@ common:
datacenter: "lab" datacenter: "lab"
sites: sites:
- name: "test" - id: "test"
site: "test.lab" name: "test.lab"
paths: paths:
- addrs: - addrs:
- "http://www1" - "http://www1"
@@ -20,7 +20,8 @@ common:
- "http://www3" - "http://www3"
custom_cert: true custom_cert: true
custom_cert_file: "/etc/ssl/certs/test.lab.crt" custom_cert_file: "/etc/ssl/certs/test.lab.crt"
custom_key_file: "/etc/ssl/private/test.lab.key" custom_cert_key_file: "/etc/ssl/private/test.lab.key"
filter_whitelist: ["10.60.117.1"]
crs_plugins: crs_plugins:
- "wordpress-rule-exclusions" - "wordpress-rule-exclusions"
crs_exceptions: crs_exceptions:

View File

@@ -1,16 +1,28 @@
# Defaults # Defaults
caddy_config_only: false caddy_config_only: false
caddy_debug: false caddy_debug: false
caddy_go_version: "1.25.5" caddy_http_port: 80
caddy_https_port: 443
caddy_default_bind: ""
caddy_version: "2.10.2"
caddy_go_version: "1.25.6"
caddy_xcaddy_version: "0.4.5" caddy_xcaddy_version: "0.4.5"
caddy_caddy_version: "2.10.2"
caddy_coraza_caddy_version: "2.1.0" # Coraza v3.3.3 caddy_coraza_caddy_version: "2.1.0" # Coraza v3.3.3
caddy_owasp_crs_version: "4.22.0" caddy_owasp_crs_versions: ["4.22.0"]
caddy_system_user: "byow"
caddy_system_group: "byow" caddy_my_name: "mywaf"
caddy_home_dir: "/opt/{{ caddy_system_user }}" caddy_system_user: "{{ caddy_my_name }}"
caddy_config_dir: "/etc/{{ caddy_system_user }}" caddy_system_group: "{{ caddy_my_name }}"
caddy_log_dir: "/var/log/{{ caddy_system_user }}" caddy_home_dir: "/opt/{{ caddy_my_name }}"
caddy_config_dir: "/etc/{{ caddy_my_name }}"
caddy_log_dir: "/var/log/{{ caddy_my_name }}"
# Required for Let's Encrypt auto certificates
caddy_email: null
# If a custom CA root have to be used
caddy_ca_root: null
# Cf.: https://github.com/coreruleset/plugin-registry # Cf.: https://github.com/coreruleset/plugin-registry
caddy_crs_plugins: caddy_crs_plugins:
@@ -32,378 +44,16 @@ caddy_crs_plugins:
version: "1.0.4" version: "1.0.4"
provider: "EsadCetiner" provider: "EsadCetiner"
# Required unless not site.custom_cert
caddy_email: null
# Required if site.bot_barrier
caddy_bot_barrier_secret: null
# Optionnal
caddy_local_ca_name: null
caddy_ca_root: null
# For each site, mandatories parameters
caddy_sites: [] caddy_sites: []
# - name: "" # - id: ""
# site: "" # name: ""
# paths: # paths:
# - path: "*" # - path: "" (default "*")
# addrs: # addrs: (minimum 1 required)
# - ""
# blacklist:
# - ""
# aliases:
# - ""
# crs_exceptions:
# before_request:
# - ""
# after_response:
# - "" # - ""
caddy_waf_defaults:
redirect_from_aliases: true
custom_cert: false
custom_cert_file: ""
custom_key_file: ""
# Security headers # Will be merged with caddy_global_sites_defaults
header_content_security_policy: caddy_my_sites_defaults: {}
# https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html#detailed-csp-directives
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy#directives
## Fetch directives
child-src: "'self'"
connect-src: "'self'"
font-src: "'self'"
img-src: "'self'"
manifest-src: "'self'"
media-src: "'self'"
# Deprecated: prefetch-src: "'self'"
object-src: "'none'"
script-src: "'none'"
script-src-attr: "'none'"
script-src-elem: "'none'"
style-src: "'self'"
style-src-attr: "'self'"
style-src-elem: "'self'"
default-src: "'self'"
## Document directives
# base-uri
# plugin-types
# sandbox
## Navigation directives
form-action: "'self'"
frame-ancestors: "'self'"
# https://developer.mozilla.org/fr/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/frame-src
frame-src: "'self'"
# https://developer.mozilla.org/fr/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/worker-src
worker-src: "'self'"
# https://developer.mozilla.org/fr/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/block-all-mixed-content
block-all-mixed-content:
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/fenced-frame-src
fenced-frame-src: "'self'"
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/upgrade-insecure-requests
upgrade-insecure-requests:
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cross-Origin-Embedder-Policy
header_cross_origin_embedder_policy: "require-corp"
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cross-Origin-Opener-Policy
header_cross_origin_opener_policy: "same-origin"
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cross-Origin-Resource-Policy
header_cross_origin_resource_policy: "same-site"
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Permissions-Policy
header_permissions_policy:
accelerometer: "()"
ambient-light-sensor: "()"
aria-notify: "()"
attribution-reporting: "()"
autoplay: "()"
bluetooth: "()"
browsing-topics: "()"
camera: "()"
captured-surface-control: "()"
compute-pressure: "()"
cross-origin-isolated: "()"
deferred-fetch: "()"
deferred-fetch-minimal: "()"
display-capture: "()"
encrypted-media: "()"
fullscreen: "()"
gamepad: "()"
geolocation: "()"
gyroscope: "()"
hid: "()"
identity-credentials-get: "()"
idle-detection: "()"
language-detector: "()"
local-fonts: "()"
magnetometer: "()"
microphone: "()"
midi: "()"
on-device-speech-recognition: "()"
otp-credentials: "()"
payment: "()"
picture-in-picture: "()"
private-state-token-issuance: "()"
private-state-token-redemption: "()"
publickey-credentials-create: "()"
publickey-credentials-get: "()"
screen-wake-lock: "()"
serial: "()"
speaker-selection: "()"
storage-access: "()"
translator: "()"
summarizer: "()"
usb: "()"
web-share: "()"
window-management: "()"
xr-spatial-tracking: "()"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#floc-federated-learning-of-cohorts
interest-cohort: "()"
# ???
battery: "()"
document-domain: "()"
execution-while-not-rendered: "()"
execution-while-out-of-viewport: "()"
navigation-override: "()"
# https://www.geeksforgeeks.org/computer-networks/http-headers-feature-policy/
header_feature_policy:
accelerometer: "'none'"
ambient-light-sensor: "'none'"
autoplay: "'none'"
battery: "'none'"
camera: "'none'"
display-capture: "'none'"
document-domain: "'none'"
encrypted-media: "'none'"
fullscreen: "'none'"
geolocation: "'none'"
gyroscope: "'none'"
layout-animation: "'none'"
legacy-image-formats: "'none'"
magnetometer: "'none'"
microphone: "'none'"
midi: "'none'"
oversized-images: "'none'"
payment: "'none'"
picture-in-picture: "'none'"
publickey-credentials-get: "'none'"
sync-xhr: "'none'"
usb: "'none'"
screen-wake-lock: "'none'"
xr-spatial-tracking: "'none'"
# ???
execution-while-not-rendered: "'none'"
execution-while-out-of-viewport: "'none'"
navigation-override: "'none'"
speaker-selection: "'none'"
unoptimized-images: "'none'"
unsized-media: "'none'"
web-share: "'none'"
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referrer-Policy
header_referrer_policy: "strict-origin-when-cross-origin"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Strict_Transport_Security_Cheat_Sheet.html
header_strict_transport_security: "max-age=2635200; includeSubDomains"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-content-type-options
header_x_content_type_options: "nosniff"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-frame-options
header_x_frame_options: "DENY"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-robots-tag
header_x_robots_tag: "noindex, nofollow"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#content-type
default_content_type: "text/html; charset=UTF-8"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#set-cookie
cookies_attributes: "SameSite=None; Secure;"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-dns-prefetch-control
# FIXME
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#server
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-aspnet-version
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-aspnetmvc-version
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-powered-by
delete_headers:
- "Server"
- "Via"
- "X-AspNet-Version"
- "X-AspNetMvc-Version"
- "X-Powered-By"
custom_headers: {}
# - name: <string>
# value: <string>
# caddy-ratelimit
rate_events: 1000
rate_window: "1m"
# steffenbusch/caddy-bot-barrier
bot_barrier: false
# corazawaf/coraza-caddy
enable_crs: true
crs_plugins: []
log_only: false
paranoia_level: 1
detection_paranoia_level: null
enforce_bodyproc_urlencoded: 1
critical_anomaly_score: 5
error_anomaly_score: 4
warning_anomaly_score: 3
notice_anomaly_score: 2
inbound_anomaly_score_threshold: 5
outbound_anomaly_score_threshold: 4
reporting_level: 4
max_num_args: 255
arg_name_length: 100
arg_length: 1000
total_arg_length: 64000
max_file_size: 10485760 # 10 Mo
combined_file_sizes: 20970520 # 20 Mo
sampling_percentage: 100
allowed_methods:
- "GET"
- "HEAD"
- "POST"
- "OPTIONS"
allowed_request_content_type:
- "|application/csp-report|"
- "|application/json|"
- "|application/reports+json|"
- "|application/soap+xml|"
- "|application/x-www-form-urlencoded|"
- "|application/xml|"
- "|multipart/form-data|"
- "|text/xml|"
restricted_extensions:
- ".ani/"
- ".asa/"
- ".asax/"
- ".ascx/"
- ".back/"
- ".backup/"
- ".bak/"
- ".bat/"
- ".bck/"
- ".bk/"
- ".bkp/"
- ".cdx/"
- ".cer/"
- ".cfg/"
- ".cmd/"
- ".cnf/"
- ".com/"
- ".compositefont/"
- ".conf/"
- ".config/"
- ".copy/"
- ".crt/"
- ".cs/"
- ".csproj/"
- ".csr/"
- ".dat/"
- ".db/"
- ".dbf/"
- ".dist/"
- ".dll/"
- ".dos/"
- ".dpkg-dist/"
- ".drv/"
- ".gadget/"
- ".hta/"
- ".htr/"
- ".htw/"
- ".ida/"
- ".idc/"
- ".idq/"
- ".inc/"
- ".inf/"
- ".ini/"
- ".jse/"
- ".key/"
- ".licx/"
- ".lnk/"
- ".log/"
- ".mdb/"
- ".msc/"
- ".ocx/"
- ".old/"
- ".pass/"
- ".pdb/"
- ".pem/"
- ".pfx/"
- ".pif/"
- ".pol/"
- ".prf/"
- ".printer/"
- ".pwd/"
- ".rdb/"
- ".rdp/"
- ".reg/"
- ".resources/"
- ".resx/"
- ".sav/"
- ".save/"
- ".scr/"
- ".sct/"
- ".sh/"
- ".shs/"
- ".sql/"
- ".sqlite/"
- ".sqlite3/"
- ".swp/"
- ".sys/"
- ".temp/"
- ".tlb/"
- ".tmp/"
- ".vb/"
- ".vbe/"
- ".vbproj/"
- ".vbs/"
- ".vsdisco/"
- ".vxd/"
- ".webinfo/"
- ".ws/"
- ".wsc/"
- ".wsf/"
- ".wsh/"
- ".xsd/"
- ".xsx/"
restricted_headers_basic:
- "/content-encoding/"
- "/content-range/"
- "/expect/"
- "/if/"
- "/lock-token/"
- "/proxy/"
- "/x-http-method-override/"
- "/x-http-method/"
- "/x-method-override/"
- "/x-middleware-subrequest/"
restricted_headers_extended:
- "/accept-charset/"
allowed_http_versions:
- "HTTP/1.0"
- "HTTP/1.1"
- "HTTP/2"
- "HTTP/2.0"
- "HTTP/3"
- "HTTP/3.0"
allowed_request_content_type_charset:
- "|utf-8|"
- "|iso-8859-1|"
- "|iso-8859-15|"
- "|windows-1252|"

View File

@@ -1,4 +1,4 @@
- name: Restart Caddy - name: Restart Caddy
ansible.builtin.service: ansible.builtin.service:
name: "{{ caddy_system_user }}" name: "{{ caddy_my_name }}"
state: "restarted" state: "restarted"

View File

@@ -1,7 +1,11 @@
- name: Set sites defaults
ansible.builtin.set_fact:
caddy_sites_defaults: "{{ caddy_global_sites_defaults | combine(caddy_my_sites_defaults) }}"
- name: Create sites config directories - name: Create sites config directories
loop: "{{ caddy_sites }}" loop: "{{ caddy_sites }}"
ansible.builtin.file: ansible.builtin.file:
path: "{{ caddy_config_dir }}/sites/{{ item.name }}" path: "{{ caddy_config_dir }}/sites/{{ item.id }}"
state: "directory" state: "directory"
group: "{{ caddy_system_group }}" group: "{{ caddy_system_group }}"
mode: "0750" mode: "0750"
@@ -12,7 +16,7 @@
loop_var: "site" loop_var: "site"
ansible.builtin.template: ansible.builtin.template:
src: "templates/coraza.conf" src: "templates/coraza.conf"
dest: "{{ caddy_config_dir }}/sites/{{ site.name }}/coraza.conf" dest: "{{ caddy_config_dir }}/sites/{{ site.id }}/coraza.conf"
group: "{{ caddy_system_group }}" group: "{{ caddy_system_group }}"
mode: "0640" mode: "0640"
notify: notify:
@@ -24,7 +28,7 @@
loop_var: "site" loop_var: "site"
ansible.builtin.template: ansible.builtin.template:
src: "templates/crs-setup.conf" src: "templates/crs-setup.conf"
dest: "{{ caddy_config_dir }}/sites/{{ site.name }}/crs-setup.conf" dest: "{{ caddy_config_dir }}/sites/{{ site.id }}/crs-setup.conf"
group: "{{ caddy_system_group }}" group: "{{ caddy_system_group }}"
mode: "0640" mode: "0640"
notify: notify:
@@ -36,7 +40,7 @@
loop_var: "site" loop_var: "site"
ansible.builtin.template: ansible.builtin.template:
src: "templates/exclusions-request-before.conf" src: "templates/exclusions-request-before.conf"
dest: "{{ caddy_config_dir }}/sites/{{ site.name }}/exclusions-request-before.conf" dest: "{{ caddy_config_dir }}/sites/{{ site.id }}/exclusions-request-before.conf"
group: "{{ caddy_system_group }}" group: "{{ caddy_system_group }}"
mode: "0640" mode: "0640"
notify: notify:
@@ -48,7 +52,7 @@
loop_var: "site" loop_var: "site"
ansible.builtin.template: ansible.builtin.template:
src: "templates/exclusions-response-after.conf" src: "templates/exclusions-response-after.conf"
dest: "{{ caddy_config_dir }}/sites/{{ site.name }}/exclusions-response-after.conf" dest: "{{ caddy_config_dir }}/sites/{{ site.id }}/exclusions-response-after.conf"
group: "{{ caddy_system_group }}" group: "{{ caddy_system_group }}"
mode: "0640" mode: "0640"
notify: notify:
@@ -71,3 +75,10 @@
mode: "0640" mode: "0640"
notify: notify:
- "Restart Caddy" - "Restart Caddy"
- name: Enable and start Caddy
ansible.builtin.service:
name: "{{ caddy_my_name }}"
state: "started"
enabled: true
daemon_reload: true

View File

@@ -2,5 +2,5 @@
when: "not(caddy_config_only)" when: "not(caddy_config_only)"
ansible.builtin.include_tasks: "caddy_install.yml" ansible.builtin.include_tasks: "caddy_install.yml"
- name: Config Caddy - name: Configure Caddy
ansible.builtin.include_tasks: "caddy_config.yml" ansible.builtin.include_tasks: "caddy_config.yml"

View File

@@ -1,6 +1,11 @@
{ {
grace_period 10s http_port {{ caddy_http_port }}
https_port {{ caddy_https_port }}
default_bind {{ caddy_default_bind }}
order coraza_waf first order coraza_waf first
admin off
persist_config off
{% if caddy_email | default(None) != None %} {% if caddy_email | default(None) != None %}
email "{{ caddy_email }}" email "{{ caddy_email }}"
{% endif %} {% endif %}
@@ -9,43 +14,38 @@
tls { tls {
ca_root "{{ caddy_ca_root }}" ca_root "{{ caddy_ca_root }}"
} }
{% endif %} {% endif %}
{% if caddy_debug %} {% if caddy_debug %}
log { log {
format json format json
level DEBUG level DEBUG
output file {{ caddy_log_dir }}/debug.log output file {{ caddy_log_dir }}/debug.log
} }
{% endif %} {% endif %}
log waf { log waf {
format json format json
include "http.handlers.waf" include "http.handlers.waf"
output file {{ caddy_log_dir }}/waf.log output file {{ caddy_log_dir }}/waf.log
} }
{% if caddy_local_ca_name | default(None) != None %}
pki {
ca local {
name "{{ caddy_local_ca_name }}"
}
}
{% endif %}
} }
{% for site in caddy_sites %} {% for site in caddy_sites %}
{% if (site.redirect_from_aliases | default(true)) and (site.aliases | default([]) | length) > 0 %}
{{ site.aliases | join(', ') }} { {% if (site.site_redirect_from_aliases | default(caddy_sites_defaults.site_redirect_from_aliases)) and (site.site_aliases | default([]) | length) > 0 %}
redir https://{{ site.site }}{uri}
{{ site.site_aliases | join(', ') }} {
redir https://{{ site.name }}{uri}
} }
{% else %} {% else %}
{% for alias in site.aliases | default([]) %}
{% for alias in site.site_aliases | default(caddy_sites_defaults.site_aliases) %}
{{ alias }}, {{ alias }},
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{{ site.site }} { {{ site.name }} {
encode gzip zstd encode gzip zstd
{% for path in site.paths %} {% for path in site.paths %}
@@ -53,7 +53,7 @@
reverse_proxy { reverse_proxy {
to {{ path.addrs | join(' ') }} to {{ path.addrs | join(' ') }}
header_up X-Real-IP {remote} header_up X-Real-IP {remote}
lb_policy ip_hash lb_policy {{ site.proxy_lb_policy | default(caddy_sites_defaults.proxy_lb_policy) }}
# Active checks # Active checks
# health_uri / # health_uri /
# health_interval 10s # health_interval 10s
@@ -72,53 +72,61 @@
{% endfor %} {% endfor %}
{% if site.custom_cert | default (false) %} {% if site.custom_cert | default (false) %}
tls {{ site.custom_cert_file }} {{ site.custom_key_file }} tls {{ site.custom_cert_file }} {{ site.custom_cert_key_file }}
{% endif %} {% endif %}
{% if site.blacklist | default([]) | length > 0 %}
{% if site.filter_blacklist | default(caddy_sites_defaults.filter_blacklist) | length > 0 %}
@blocked { @blocked {
{% for ip in site.blacklist | default([]) %} {% for ip in site.filter_blacklist | default(caddy_sites_defaults.filter_blacklist) %}
remote_ip {{ ip }} remote_ip {{ ip }}
{% endfor %} {% endfor %}
} }
respond @blocked "Access Denied" 403 respond @blocked "Access Denied" 403
{% endif %} {% endif %}
{% if site.bot_barrier | default (false) %}
bot_barrier { @not_whitelisted not {
secret {{ caddy_bot_barrier_secret }} {% for ip in site.filter_whitelist | default(caddy_sites_defaults.filter_whitelist) %}
complexity 18 remote_ip {{ ip }}
valid_for 30m {% endfor %}
seed_cookie_name __chall_{{ site.name }}_seed
solution_cookie_name __chall_{{ site.name }}_solution
mac_cookie_name __chall_{{ site.name }}_mac
template {{ caddy_config_dir }}/bot_barrier_template.html
} }
{% if site.bot_barrier | default(caddy_sites_defaults.bot_barrier) %}
bot_barrier @not_whitelisted {
secret {{ site.bot_barrier_secret | default(caddy_sites_defaults.bot_barrier_secret) | mandatory }}
complexity {{ site.bot_barrier_complexity | default(caddy_sites_defaults.bot_barrier_complexity) }}
valid_for {{ site.bot_barrier_valid_for | default(caddy_sites_defaults.bot_barrier_valid_for) }}
seed_cookie_name __chall_{{ site.id }}_seed
solution_cookie_name __chall_{{ site.id }}_solution
mac_cookie_name __chall_{{ site.id }}_mac
template {{ caddy_config_dir }}/bot_barrier_template.html
}
{% endif %} {% endif %}
rate_limit {
{% if site.rate_limit | default(caddy_sites_defaults.rate_limit) %}
rate_limit @not_whitelisted {
# distributed # distributed
zone remote_ip { zone remote_ip {
key {remote.ip} key {remote.ip}
events {{ site.rate_events | default('1000') }} events {{ site.rate_limit_events | default(caddy_sites_defaults.rate_limit_events) }}
window {{ site.rate_window | default('1m') }} window {{ site.rate_limit_window | default(caddy_sites_defaults.rate_limit_window) }}
} }
} }
{% if site.enable_crs | default(caddy_waf_defaults.enable_crs) %} {% endif %}
coraza_waf { {% if site.crs | default(caddy_sites_defaults.crs) %}
coraza_waf @not_whitelisted {
load_owasp_crs load_owasp_crs
directives ` directives `
Include "{{ caddy_config_dir }}/sites/{{ site.name }}/coraza.conf" Include "{{ caddy_config_dir }}/sites/{{ site.id }}/coraza.conf"
Include "{{ caddy_config_dir }}/sites/{{ site.name }}/crs-setup.conf" Include "{{ caddy_config_dir }}/sites/{{ site.id }}/crs-setup.conf"
{% for plugin in site.crs_plugins | default(caddy_waf_defaults.crs_plugins) %} {% for plugin in site.crs_plugins | default(caddy_sites_defaults.crs_plugins) %}
Include "{{ caddy_config_dir }}/crs-plugins/{{ plugin }}-config.conf" Include "{{ caddy_config_dir }}/crs-plugins/{{ plugin }}-config.conf"
Include "{{ caddy_config_dir }}/crs-plugins/{{ plugin }}-before.conf" Include "{{ caddy_config_dir }}/crs-plugins/{{ plugin }}-before.conf"
{% endfor %} {% endfor %}
Include "{{ caddy_config_dir }}/sites/{{ site.name }}/exclusions-request-before.conf" Include "{{ caddy_config_dir }}/sites/{{ site.id }}/exclusions-request-before.conf"
Include "{{ caddy_config_dir }}/coreruleset-{{ caddy_owasp_crs_version }}/rules/*.conf" Include "{{ caddy_config_dir }}/coreruleset-{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}/rules/*.conf"
Include "{{ caddy_config_dir }}/sites/{{ site.name }}/exclusions-response-after.conf" Include "{{ caddy_config_dir }}/sites/{{ site.id }}/exclusions-response-after.conf"
{% for plugin in site.crs_plugins | default(caddy_waf_defaults.crs_plugins) %} {% for plugin in site.crs_plugins | default(caddy_sites_defaults.crs_plugins) %}
Include "{{ caddy_config_dir }}/crs-plugins/{{ plugin }}-after.conf" Include "{{ caddy_config_dir }}/crs-plugins/{{ plugin }}-after.conf"
{% endfor %} {% endfor %}
SecRuleEngine On SecRuleEngine On
@@ -127,35 +135,35 @@
{% endif %} {% endif %}
header { header {
Content-Security-Policy "{{ caddy_waf_defaults.header_content_security_policy | combine(site.header_content_security_policy | default({})) | dict2str(sep1=' ', sep2='; ', sep3=';') }}" Content-Security-Policy "{{ caddy_sites_defaults.header_content_security_policy | combine(site.header_content_security_policy | default({})) | dict2str(sep1=' ', sep2='; ', sep3=';') }}"
Cross-Origin-Embedder-Policy "{{ site.header_cross_origin_embedder_policy | default(caddy_waf_defaults.header_cross_origin_embedder_policy) }}" Cross-Origin-Embedder-Policy "{{ site.header_cross_origin_embedder_policy | default(caddy_sites_defaults.header_cross_origin_embedder_policy) }}"
Cross-Origin-Opener-Policy "{{ site.header_cross_origin_opener_policy | default(caddy_waf_defaults.header_cross_origin_opener_policy) }}" Cross-Origin-Opener-Policy "{{ site.header_cross_origin_opener_policy | default(caddy_sites_defaults.header_cross_origin_opener_policy) }}"
Cross-Origin-Resource-Policy "{{ site.header_cross_origin_resource_policy | default(caddy_waf_defaults.header_cross_origin_resource_policy) }}" Cross-Origin-Resource-Policy "{{ site.header_cross_origin_resource_policy | default(caddy_sites_defaults.header_cross_origin_resource_policy) }}"
Feature-Policy "{{ caddy_waf_defaults.header_feature_policy | combine(site.header_feature_policy | default({})) | dict2str(sep1=' ', sep2='; ', sep3=';') }}" Feature-Policy "{{ caddy_sites_defaults.header_feature_policy | combine(site.header_feature_policy | default({})) | dict2str(sep1=' ', sep2='; ', sep3=';') }}"
Permissions-Policy "{{ caddy_waf_defaults.header_permissions_policy | combine(site.header_permissions_policy | default({})) | dict2str(sep2=', ') }}" Permissions-Policy "{{ caddy_sites_defaults.header_permissions_policy | combine(site.header_permissions_policy | default({})) | dict2str(sep2=', ') }}"
Referrer-Policy "{{ site.header_referrer_policy | default(caddy_waf_defaults.header_referrer_policy) }}" Referrer-Policy "{{ site.header_referrer_policy | default(caddy_sites_defaults.header_referrer_policy) }}"
Strict-Transport-Security "{{ site.header_strict_transport_security | default(caddy_waf_defaults.header_strict_transport_security) }}" Strict-Transport-Security "{{ site.header_strict_transport_security | default(caddy_sites_defaults.header_strict_transport_security) }}"
X-Content-Type-Options "{{ site.header_x_content_type_options | default(caddy_waf_defaults.header_x_content_type_options) }}" X-Content-Type-Options "{{ site.header_x_content_type_options | default(caddy_sites_defaults.header_x_content_type_options) }}"
X-Frame-Options "{{ site.header_x_frame_options | default(caddy_waf_defaults.header_x_frame_options) }}" X-Frame-Options "{{ site.header_x_frame_options | default(caddy_sites_defaults.header_x_frame_options) }}"
X-Robots-Tag "{{ site.header_x_robots_tag | default(caddy_waf_defaults.header_x_robots_tag) }}" X-Robots-Tag "{{ site.header_x_robots_tag | default(caddy_sites_defaults.header_x_robots_tag) }}"
?Content-Type "{{ site.default_content_type | default(caddy_waf_defaults.default_content_type) }}" ?Content-Type "{{ site.header_default_content_type | default(caddy_sites_defaults.header_default_content_type) }}"
>Set-Cookie "(.*)" "$1; {{ site.cookies_attributes | default(caddy_waf_defaults.cookies_attributes) }}" >Set-Cookie "(.*)" "$1; {{ site.header_cookies_attributes | default(caddy_sites_defaults.header_cookies_attributes) }}"
{% for header in site.delete_headers | default(caddy_waf_defaults.delete_headers) %} {% for header in site.header_delete | default(caddy_sites_defaults.header_delete) %}
-{{ header }} -{{ header }}
{% endfor %} {% endfor %}
{% for header in site.custom_headers | default(caddy_waf_defaults.custom_headers) %} {% for header in site.header_add | default(caddy_sites_defaults.header_add) %}
{{ header.name }} "{{ header.value }}" {{ header.name }} "{{ header.value }}"
{% endfor %} {% endfor %}
} }
handle_errors 403 { handle_errors 403 {
header X-Blocked "true" header X-Blocked "true"
respond "Your request was blocked." respond "Your request was blocked. 🔴"
} }
log { log {
format json format json
output file {{ caddy_log_dir }}/site_{{ site.name }}.log output file {{ caddy_log_dir }}/site_{{ site.id }}.log
} }
} }

View File

@@ -1,6 +1,5 @@
[Unit] [Unit]
Description=Caddy Description=WAF {{ caddy_my_name }} (built with BYOW: Build Your Own WAF)
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target After=network.target network-online.target
Requires=network-online.target Requires=network-online.target
@@ -8,8 +7,8 @@ Requires=network-online.target
Type=notify Type=notify
User={{ caddy_system_user }} User={{ caddy_system_user }}
Group={{ caddy_system_group }} Group={{ caddy_system_group }}
ExecStart=/usr/local/bin/caddy run --environ --config {{ caddy_config_dir }}/Caddyfile ExecStart=/usr/local/bin/{{ caddy_my_name }} run --environ --config {{ caddy_config_dir }}/Caddyfile
ExecReload=/usr/local/bin/caddy reload --config {{ caddy_config_dir }}/Caddyfile --force ExecReload=/usr/local/bin/{{ caddy_my_name }} reload --config {{ caddy_config_dir }}/Caddyfile --force
TimeoutStopSec=15s TimeoutStopSec=15s
LimitNOFILE=1048576 LimitNOFILE=1048576
PrivateTmp=true PrivateTmp=true

View File

@@ -10,9 +10,9 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.blocking_paranoia_level={{ site.paranoia_level | default(caddy_waf_defaults.paranoia_level) }}" setvar:tx.blocking_crs_paranoia_level={{ site.crs_paranoia_level | default(caddy_sites_defaults.crs_paranoia_level) }}"
{% if site.detection_paranoia_level | default(caddy_waf_defaults.detection_paranoia_level) != None %} {% if site.crs_detection_paranoia_level | default(caddy_sites_defaults.crs_detection_paranoia_level) != None %}
## Detection paranoia level ## Detection paranoia level
SecAction \ SecAction \
@@ -22,8 +22,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.detection_paranoia_level={{ site.detection_paranoia_level | default(caddy_waf_defaults.detection_paranoia_level) }}" setvar:tx.crs_detection_paranoia_level={{ site.crs_detection_paranoia_level | default(caddy_sites_defaults.crs_detection_paranoia_level) }}"
{% endif %} {% endif %}
## Enforce Body Processor URLENCODED ## Enforce Body Processor URLENCODED
@@ -34,8 +34,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.enforce_bodyproc_urlencoded={{ site.enforce_bodyproc_urlencoded | default(caddy_waf_defaults.enforce_bodyproc_urlencoded) }}" setvar:tx.crs_enforce_bodyproc_urlencoded={{ site.crs_enforce_bodyproc_urlencoded | default(caddy_sites_defaults.crs_enforce_bodyproc_urlencoded) }}"
## Anomaly Scoring Mode Severity Levels ## Anomaly Scoring Mode Severity Levels
SecAction \ SecAction \
@@ -45,11 +45,11 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.critical_anomaly_score={{ site.critical_anomaly_score | default(caddy_waf_defaults.critical_anomaly_score) }},\ setvar:tx.crs_critical_anomaly_score={{ site.crs_critical_anomaly_score | default(caddy_sites_defaults.crs_critical_anomaly_score) }},\
setvar:tx.error_anomaly_score={{ site.error_anomaly_score | default(caddy_waf_defaults.error_anomaly_score) }},\ setvar:tx.crs_error_anomaly_score={{ site.crs_error_anomaly_score | default(caddy_sites_defaults.crs_error_anomaly_score) }},\
setvar:tx.warning_anomaly_score={{ site.warning_anomaly_score | default(caddy_waf_defaults.warning_anomaly_score) }},\ setvar:tx.crs_warning_anomaly_score={{ site.crs_warning_anomaly_score | default(caddy_sites_defaults.crs_warning_anomaly_score) }},\
setvar:tx.notice_anomaly_score={{ site.notice_anomaly_score | default(caddy_waf_defaults.notice_anomaly_score) }}" setvar:tx.crs_notice_anomaly_score={{ site.crs_notice_anomaly_score | default(caddy_sites_defaults.crs_notice_anomaly_score) }}"
## Anomaly Scoring Mode Blocking Threshold Levels ## Anomaly Scoring Mode Blocking Threshold Levels
SecAction \ SecAction \
@@ -59,9 +59,9 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.inbound_anomaly_score_threshold={% if site.log_only | default(caddy_waf_defaults.log_only) %}1000{% else %}{{ site.inbound_anomaly_score_threshold | default(caddy_waf_defaults.inbound_anomaly_score_threshold) }}{% endif %},\ setvar:tx.crs_inbound_anomaly_score_threshold={% if site.crs_log_only | default(caddy_sites_defaults.crs_log_only) %}1000{% else %}{{ site.crs_inbound_anomaly_score_threshold | default(caddy_sites_defaults.crs_inbound_anomaly_score_threshold) }}{% endif %},\
setvar:tx.outbound_anomaly_score_threshold={% if site.log_only | default(caddy_waf_defaults.log_only) %}1000{% else %}{{ site.outbound_anomaly_score_threshold | default(caddy_waf_defaults.outbound_anomaly_score_threshold) }}{% endif %}" setvar:tx.crs_outbound_anomaly_score_threshold={% if site.crs_log_only | default(caddy_sites_defaults.crs_log_only) %}1000{% else %}{{ site.crs_outbound_anomaly_score_threshold | default(caddy_sites_defaults.crs_outbound_anomaly_score_threshold) }}{% endif %}"
## Application Specific Rule Exclusions ## Application Specific Rule Exclusions
# FIXME # FIXME
@@ -87,8 +87,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.reporting_level={{ site.reporting_level | default(caddy_waf_defaults.reporting_level) }}" setvar:tx.crs_reporting_level={{ site.crs_reporting_level | default(caddy_sites_defaults.crs_reporting_level) }}"
## Early Anomaly Scoring Mode Blocking ## Early Anomaly Scoring Mode Blocking
SecAction \ SecAction \
@@ -98,7 +98,7 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.early_blocking=0" setvar:tx.early_blocking=0"
## Initialize Default Collections ## Initialize Default Collections
@@ -109,7 +109,7 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.enable_default_collections=1" setvar:tx.enable_default_collections=1"
## HTTP Policy Settings ## HTTP Policy Settings
@@ -120,8 +120,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:'tx.allowed_methods={{ site.allowed_methods | default(caddy_waf_defaults.allowed_methods) | join(" ") }}'" setvar:'tx.crs_allowed_methods={{ site.crs_allowed_methods | default(caddy_sites_defaults.crs_allowed_methods) | join(" ") }}'"
## Content-Types that a client is allowed to send in a request ## Content-Types that a client is allowed to send in a request
SecAction \ SecAction \
@@ -131,8 +131,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:'tx.allowed_request_content_type={{ site.allowed_request_content_type | default(caddy_waf_defaults.allowed_request_content_type) | join(" ") }}'" setvar:'tx.crs_allowed_request_content_type={{ site.crs_allowed_request_content_type | default(caddy_sites_defaults.crs_allowed_request_content_type) | join(" ") }}'"
## Allowed HTTP versions ## Allowed HTTP versions
SecAction \ SecAction \
@@ -142,8 +142,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:'tx.allowed_http_versions={{ site.allowed_http_versions | default(caddy_waf_defaults.allowed_http_versions) | join(" ") }}'" setvar:'tx.crs_allowed_http_versions={{ site.crs_allowed_http_versions | default(caddy_sites_defaults.crs_allowed_http_versions) | join(" ") }}'"
## Forbidden file extensions ## Forbidden file extensions
SecAction \ SecAction \
@@ -153,8 +153,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:'tx.restricted_extensions={{ site.restricted_extensions | default(caddy_waf_defaults.restricted_extensions) | join(" ") }}'" setvar:'tx.crs_restricted_extensions={{ site.crs_restricted_extensions | default(caddy_sites_defaults.crs_restricted_extensions) | join(" ") }}'"
## Restricted request headers ## Restricted request headers
SecAction \ SecAction \
@@ -164,8 +164,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:'tx.restricted_headers_basic={{ site.restricted_headers_basic | default(caddy_waf_defaults.restricted_headers_basic) | join(" ") }}'" setvar:'tx.crs_restricted_headers_basic={{ site.crs_restricted_headers_basic | default(caddy_sites_defaults.crs_restricted_headers_basic) | join(" ") }}'"
## Extended restricted request headers (forbidden at a higher paranoia level) ## Extended restricted request headers (forbidden at a higher paranoia level)
SecAction \ SecAction \
@@ -175,8 +175,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:'tx.restricted_headers_extended={{ site.restricted_headers_extended | default(caddy_waf_defaults.restricted_headers_extended) | join(" ") }}'" setvar:'tx.crs_restricted_headers_extended={{ site.crs_restricted_headers_extended | default(caddy_sites_defaults.crs_restricted_headers_extended) | join(" ") }}'"
## Content-Types charsets that a client is allowed to send in a request ## Content-Types charsets that a client is allowed to send in a request
SecAction \ SecAction \
@@ -186,8 +186,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:'tx.allowed_request_content_type_charset={{ caddy_waf_defaults.allowed_request_content_type_charset | default(caddy_waf_defaults.allowed_request_content_type_charset) | join(" ") }}'" setvar:'tx.crs_allowed_request_content_type_charset={{ caddy_sites_defaults.crs_allowed_request_content_type_charset | default(caddy_sites_defaults.crs_allowed_request_content_type_charset) | join(" ") }}'"
## Block request if number of arguments is too high ## Block request if number of arguments is too high
SecAction \ SecAction \
@@ -197,8 +197,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.max_num_args={{ site.max_num_args | default(caddy_waf_defaults.max_num_args) }}" setvar:tx.crs_max_num_args={{ site.crs_max_num_args | default(caddy_sites_defaults.crs_max_num_args) }}"
## Block request if the length of any argument name is too high ## Block request if the length of any argument name is too high
SecAction \ SecAction \
@@ -208,8 +208,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.arg_name_length={{ site.arg_name_length | default(caddy_waf_defaults.arg_name_length) }}" setvar:tx.crs_arg_name_length={{ site.crs_arg_name_length | default(caddy_sites_defaults.crs_arg_name_length) }}"
## Block request if the length of any argument value is too high ## Block request if the length of any argument value is too high
SecAction \ SecAction \
@@ -219,8 +219,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.arg_length={{ site.arg_length | default(caddy_waf_defaults.arg_length) }}" setvar:tx.crs_arg_length={{ site.crs_arg_length | default(caddy_sites_defaults.crs_arg_length) }}"
## Block request if the total length of all combined arguments is too high ## Block request if the total length of all combined arguments is too high
SecAction \ SecAction \
@@ -230,8 +230,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.total_arg_length={{ site.total_arg_length | default(caddy_waf_defaults.total_arg_length) }}" setvar:tx.crs_total_arg_length={{ site.crs_total_arg_length | default(caddy_sites_defaults.crs_total_arg_length) }}"
## Block request if the file size of any individual uploaded file is too high ## Block request if the file size of any individual uploaded file is too high
SecAction \ SecAction \
@@ -241,8 +241,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.max_file_size={{ site.max_file_size | default(caddy_waf_defaults.max_file_size) }}" setvar:tx.crs_max_file_size={{ site.crs_max_file_size | default(caddy_sites_defaults.crs_max_file_size) }}"
## Block request if the total size of all combined uploaded files is too high ## Block request if the total size of all combined uploaded files is too high
SecAction \ SecAction \
@@ -252,8 +252,8 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.combined_file_sizes={{ site.combined_file_sizes | default(caddy_waf_defaults.combined_file_sizes) }}" setvar:tx.crs_combined_file_sizes={{ site.crs_combined_file_sizes | default(caddy_sites_defaults.crs_combined_file_sizes) }}"
## Easing In / Sampling Percentage ## Easing In / Sampling Percentage
SecAction \ SecAction \
@@ -262,8 +262,8 @@ SecAction \
pass,\ pass,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.sampling_percentage={{ site.sampling_percentage | default(caddy_waf_defaults.sampling_percentage) }}" setvar:tx.crs_sampling_percentage={{ site.crs_sampling_percentage | default(caddy_sites_defaults.crs_sampling_percentage) }}"
## Check UTF-8 encoding ## Check UTF-8 encoding
SecAction \ SecAction \
@@ -273,7 +273,7 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.crs_validate_utf8_encoding=1" setvar:tx.crs_validate_utf8_encoding=1"
## Skip Checking Responses ## Skip Checking Responses
@@ -290,7 +290,7 @@ SecAction \
# t:none,\ # t:none,\
# nolog,\ # nolog,\
# tag:'OWASP_CRS',\ # tag:'OWASP_CRS',\
# ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ # ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
# setvar:tx.crs_skip_response_analysis=1" # setvar:tx.crs_skip_response_analysis=1"
## End of setup ## End of setup
@@ -301,5 +301,5 @@ SecAction \
t:none,\ t:none,\
nolog,\ nolog,\
tag:'OWASP_CRS',\ tag:'OWASP_CRS',\
ver:'OWASP_CRS/{{ caddy_owasp_crs_version }}',\ ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
setvar:tx.crs_setup_version={{ caddy_owasp_crs_version | regex_replace('\.', '') }}" setvar:tx.crs_setup_version={{ site.crs_version | default(caddy_sites_defaults.crs_version) | regex_replace('\.', '') }}"

View File

@@ -1,3 +1,3 @@
{% for exclusion in site.crs_exceptions.before_request | default([]) %} {% for exclusion in site.crs_exceptions.before_request | default(caddy_sites_defaults.crs_exceptions.before_request) %}
{{ exclusion }} {{ exclusion }}
{% endfor %} {% endfor %}

View File

@@ -1,3 +1,3 @@
{% for exclusion in site.crs_exceptions.after_response | default([]) %} {% for exclusion in site.crs_exceptions.after_response | default(caddy_sites_defaults.crs_exceptions.after_response) %}
{{ exclusion }} {{ exclusion }}
{% endfor %} {% endfor %}

View File

@@ -1 +1,387 @@
caddy_xcaddy_download: "https://github.com/caddyserver/xcaddy/releases/download" # Sites default parameter values
caddy_global_sites_defaults:
# Site settings
site_aliases: []
site_redirect_from_aliases: true
# Proxy settings
proxy_lb_policy: "ip_hash" # random
# random_choose <n>
# first
# round_robin
# weighted_round_robin <weights...>
# least_conn
# ip_hash
# client_ip_hash
# uri_hash
# query [key]
# header [field]
# cookie [<name> [<secret>]]
# Custom TLS certificate
custom_cert: false
custom_cert_file: ""
custom_cert_key_file: ""
# Filters
filter_whitelist: ["127.0.0.1"]
filter_blacklist: [] # Superseeds filter_whitelist
# Security headers
header_content_security_policy:
# https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html#detailed-csp-directives
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy#directives
## Fetch directives
child-src: "'self'"
connect-src: "'self'"
font-src: "'self'"
img-src: "'self'"
manifest-src: "'self'"
media-src: "'self'"
# Deprecated: prefetch-src: "'self'"
object-src: "'none'"
script-src: "'none'"
script-src-attr: "'none'"
script-src-elem: "'none'"
style-src: "'self'"
style-src-attr: "'self'"
style-src-elem: "'self'"
default-src: "'self'"
## Document directives
# base-uri
# plugin-types
# sandbox
## Navigation directives
form-action: "'self'"
frame-ancestors: "'self'"
# https://developer.mozilla.org/fr/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/frame-src
frame-src: "'self'"
# https://developer.mozilla.org/fr/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/worker-src
worker-src: "'self'"
# https://developer.mozilla.org/fr/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/block-all-mixed-content
block-all-mixed-content:
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/fenced-frame-src
fenced-frame-src: "'self'"
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/upgrade-insecure-requests
upgrade-insecure-requests:
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cross-Origin-Embedder-Policy
header_cross_origin_embedder_policy: "require-corp"
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cross-Origin-Opener-Policy
header_cross_origin_opener_policy: "same-origin"
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cross-Origin-Resource-Policy
header_cross_origin_resource_policy: "same-site"
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Permissions-Policy
header_permissions_policy:
accelerometer: "()"
ambient-light-sensor: "()"
aria-notify: "()"
attribution-reporting: "()"
autoplay: "()"
bluetooth: "()"
browsing-topics: "()"
camera: "()"
captured-surface-control: "()"
compute-pressure: "()"
cross-origin-isolated: "()"
deferred-fetch: "()"
deferred-fetch-minimal: "()"
display-capture: "()"
encrypted-media: "()"
fullscreen: "()"
gamepad: "()"
geolocation: "()"
gyroscope: "()"
hid: "()"
identity-credentials-get: "()"
idle-detection: "()"
language-detector: "()"
local-fonts: "()"
magnetometer: "()"
microphone: "()"
midi: "()"
on-device-speech-recognition: "()"
otp-credentials: "()"
payment: "()"
picture-in-picture: "()"
private-state-token-issuance: "()"
private-state-token-redemption: "()"
publickey-credentials-create: "()"
publickey-credentials-get: "()"
screen-wake-lock: "()"
serial: "()"
speaker-selection: "()"
storage-access: "()"
translator: "()"
summarizer: "()"
usb: "()"
web-share: "()"
window-management: "()"
xr-spatial-tracking: "()"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#floc-federated-learning-of-cohorts
interest-cohort: "()"
# ???
battery: "()"
document-domain: "()"
execution-while-not-rendered: "()"
execution-while-out-of-viewport: "()"
navigation-override: "()"
# https://www.geeksforgeeks.org/computer-networks/http-headers-feature-policy/
header_feature_policy:
accelerometer: "'none'"
ambient-light-sensor: "'none'"
autoplay: "'none'"
battery: "'none'"
camera: "'none'"
display-capture: "'none'"
document-domain: "'none'"
encrypted-media: "'none'"
fullscreen: "'none'"
geolocation: "'none'"
gyroscope: "'none'"
layout-animation: "'none'"
legacy-image-formats: "'none'"
magnetometer: "'none'"
microphone: "'none'"
midi: "'none'"
oversized-images: "'none'"
payment: "'none'"
picture-in-picture: "'none'"
publickey-credentials-get: "'none'"
sync-xhr: "'none'"
usb: "'none'"
screen-wake-lock: "'none'"
xr-spatial-tracking: "'none'"
# ???
execution-while-not-rendered: "'none'"
execution-while-out-of-viewport: "'none'"
navigation-override: "'none'"
speaker-selection: "'none'"
unoptimized-images: "'none'"
unsized-media: "'none'"
web-share: "'none'"
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referrer-Policy
header_referrer_policy: "strict-origin-when-cross-origin"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Strict_Transport_Security_Cheat_Sheet.html
header_strict_transport_security: "max-age=2635200; includeSubDomains"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-content-type-options
header_x_content_type_options: "nosniff"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-frame-options
header_x_frame_options: "DENY"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-robots-tag
header_x_robots_tag: "noindex, nofollow"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#content-type
header_default_content_type: "text/html; charset=UTF-8"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#set-cookie
header_cookies_attributes: "SameSite=None; Secure;"
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-dns-prefetch-control
# FIXME
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#server
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-aspnet-version
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-aspnetmvc-version
# https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-powered-by
header_delete:
- "Server"
- "Via"
- "X-AspNet-Version"
- "X-AspNetMvc-Version"
- "X-Powered-By"
header_add:
- name: "X-BYOW"
value: "🍷"
# caddy-ratelimit
rate_limit: true
rate_limit_events: 1000
rate_limit_window: "1m"
# steffenbusch/caddy-bot-barrier
bot_barrier: false
bot_barrier_secret: null # Required
bot_barrier_complexity: 18
bot_barrier_valid_for: "60m"
# corazawaf/coraza-caddy
crs: true
crs_version: "4.22.0"
crs_log_only: false
crs_plugins: []
crs_exceptions:
before_request: []
after_response: []
crs_paranoia_level: 1
crs_detection_paranoia_level: null
crs_enforce_bodyproc_urlencoded: 1
crs_critical_anomaly_score: 5
crs_error_anomaly_score: 4
crs_warning_anomaly_score: 3
crs_notice_anomaly_score: 2
crs_inbound_anomaly_score_threshold: 5
crs_outbound_anomaly_score_threshold: 4
crs_reporting_level: 4
crs_max_num_args: 255
crs_arg_name_length: 100
crs_arg_length: 1000
crs_total_arg_length: 64000
crs_max_file_size: 10485760 # 10 Mo
crs_combined_file_sizes: 20970520 # 20 Mo
crs_sampling_percentage: 100
crs_allowed_methods:
- "GET"
- "HEAD"
- "POST"
- "OPTIONS"
crs_allowed_request_content_type:
- "|application/csp-report|"
- "|application/json|"
- "|application/reports+json|"
- "|application/soap+xml|"
- "|application/x-www-form-urlencoded|"
- "|application/xml|"
- "|multipart/form-data|"
- "|text/xml|"
crs_restricted_extensions:
- ".ani/"
- ".asa/"
- ".asax/"
- ".ascx/"
- ".back/"
- ".backup/"
- ".bak/"
- ".bat/"
- ".bck/"
- ".bk/"
- ".bkp/"
- ".cdx/"
- ".cer/"
- ".cfg/"
- ".cmd/"
- ".cnf/"
- ".com/"
- ".compositefont/"
- ".conf/"
- ".config/"
- ".copy/"
- ".crt/"
- ".cs/"
- ".csproj/"
- ".csr/"
- ".dat/"
- ".db/"
- ".dbf/"
- ".dist/"
- ".dll/"
- ".dos/"
- ".dpkg-dist/"
- ".drv/"
- ".gadget/"
- ".hta/"
- ".htr/"
- ".htw/"
- ".ida/"
- ".idc/"
- ".idq/"
- ".inc/"
- ".inf/"
- ".ini/"
- ".jse/"
- ".key/"
- ".licx/"
- ".lnk/"
- ".log/"
- ".mdb/"
- ".msc/"
- ".ocx/"
- ".old/"
- ".pass/"
- ".pdb/"
- ".pem/"
- ".pfx/"
- ".pif/"
- ".pol/"
- ".prf/"
- ".printer/"
- ".pwd/"
- ".rdb/"
- ".rdp/"
- ".reg/"
- ".resources/"
- ".resx/"
- ".sav/"
- ".save/"
- ".scr/"
- ".sct/"
- ".sh/"
- ".shs/"
- ".sql/"
- ".sqlite/"
- ".sqlite3/"
- ".swp/"
- ".sys/"
- ".temp/"
- ".tlb/"
- ".tmp/"
- ".vb/"
- ".vbe/"
- ".vbproj/"
- ".vbs/"
- ".vsdisco/"
- ".vxd/"
- ".webinfo/"
- ".ws/"
- ".wsc/"
- ".wsf/"
- ".wsh/"
- ".xsd/"
- ".xsx/"
crs_restricted_headers_basic:
- "/content-encoding/"
- "/content-range/"
- "/expect/"
- "/if/"
- "/lock-token/"
- "/proxy/"
- "/x-http-method-override/"
- "/x-http-method/"
- "/x-method-override/"
- "/x-middleware-subrequest/"
crs_restricted_headers_extended:
- "/accept-charset/"
crs_allowed_http_versions:
- "HTTP/1.0"
- "HTTP/1.1"
- "HTTP/2"
- "HTTP/2.0"
- "HTTP/3"
- "HTTP/3.0"
crs_allowed_request_content_type_charset:
- "|utf-8|"
- "|iso-8859-1|"
- "|iso-8859-15|"
- "|windows-1252|"