feat: standardize whitespace in conditional statements across configuration files

This commit is contained in:
Théophile Diot 2024-11-18 17:50:27 +01:00
parent 9806f0fc72
commit 2dbd99a181
No known key found for this signature in database
GPG key ID: FA995104A0BA376A
33 changed files with 307 additions and 326 deletions

View file

@ -1,3 +1,3 @@
{% if USE_ANTIBOT != "no" +%}
{%+ if USE_ANTIBOT != "no" -%}
SecRule REQUEST_FILENAME "@rx ^{{ ANTIBOT_URI }}$" "nolog,phase:4,allow,id:1010"
{% endif %}
{%- endif %}

View file

@ -1,4 +1,4 @@
{% if USE_ANTIBOT != "no" +%}
{%+ if USE_ANTIBOT != "no" -%}
location {{ ANTIBOT_URI }} {
default_type 'text/html';
root /usr/share/bunkerweb/core/antibot/files;
@ -31,4 +31,4 @@ location {{ ANTIBOT_URI }} {
save_ctx(ctx)
}
}
{% endif %}
{%- endif %}

View file

@ -1,11 +1,11 @@
{% if USE_AUTH_BASIC == "yes" +%}
{% if AUTH_BASIC_LOCATION == "sitewide" %}
{%+ if USE_AUTH_BASIC == "yes" -%}
{%- if AUTH_BASIC_LOCATION == "sitewide" -%}
auth_basic "{{ AUTH_BASIC_TEXT }}";
auth_basic_user_file {{ NGINX_PREFIX }}server-http/htpasswd;
{% else %}
{%- else -%}
location {{ AUTH_BASIC_LOCATION }} {
auth_basic "{{ AUTH_BASIC_TEXT }}";
auth_basic_user_file {{ NGINX_PREFIX }}server-http/htpasswd;
auth_basic "{{ AUTH_BASIC_TEXT }}";
auth_basic_user_file {{ NGINX_PREFIX }}server-http/htpasswd;
}
{% endif %}
{% endif %}
{%- endif %}
{%- endif %}

View file

@ -1,4 +1,4 @@
{% if USE_AUTH_BASIC == "yes" %}
{% set passlib_hash = import('passlib.hash') %}
{%- if USE_AUTH_BASIC == "yes" -%}
{%- set passlib_hash = import('passlib.hash') -%}
{{ AUTH_BASIC_USER }}:{{ passlib_hash.sha512_crypt.hash(AUTH_BASIC_PASSWORD) }}
{% endif %}
{%- endif %}

View file

@ -1,6 +1,6 @@
{% if USE_BROTLI == "yes" +%}
{%+ if USE_BROTLI == "yes" -%}
brotli on;
brotli_types {{ BROTLI_TYPES }};
brotli_comp_level {{ BROTLI_COMP_LEVEL }};
brotli_min_length {{ BROTLI_MIN_LENGTH }};
{% endif %}
{%- endif %}

View file

@ -1,8 +1,8 @@
{% if USE_CLIENT_CACHE == "yes" +%}
{%+ if USE_CLIENT_CACHE == "yes" -%}
add_header Cache-Control $cache_control;
{% if CLIENT_CACHE_ETAG == "yes" and SERVE_FILES == "yes" and USE_REVERSE_PROXY == "no" +%}
{% if CLIENT_CACHE_ETAG == "yes" and SERVE_FILES == "yes" and USE_REVERSE_PROXY == "no" %}
etag on;
{% else +%}
{% else %}
etag off;
{% endif +%}
{% endif %}
{% endif %}
{%- endif %}

View file

@ -1,10 +1,9 @@
{% for intercepted_error_code in "400 401 403 404 405 413 429 500 501 502 503 504".split(" ") %}
{% if intercepted_error_code == "400" %}
{%- for intercepted_error_code in "400 401 403 404 405 413 429 500 501 502 503 504".split(" ") %}
{% if intercepted_error_code == "400" -%}
error_page 400 /bwerror400;
{% else %}
{%- else -%}
error_page {{ intercepted_error_code }} @bwerror{{ intercepted_error_code }};
{% endif %}
{%- endif %}
location {% if intercepted_error_code == "400" %}= /{% else %} @{% endif %}bwerror{{ intercepted_error_code }} {
auth_basic off;
@ -19,4 +18,5 @@ location {% if intercepted_error_code == "400" %}= /{% else %} @{% endif %}bwerr
errors:render_template(tostring(ngx.status))
}
}
{% endfor %}
{%+ endfor -%}

View file

@ -1,41 +1,41 @@
{% if ERRORS != "" %}
{% for element in ERRORS.split(" ") %}
{% set code = element.split("=")[0] %}
{% set page = element.split("=")[1] %}
{%- if ERRORS != "" -%}
{%- for element in ERRORS.split(" ") -%}
{%- set code = element.split("=")[0] -%}
{%- set page = element.split("=")[1] -%}
error_page {{ code }} {{ page }};
location = {{ page }} {
root {% if ROOT_FOLDER == "" %}/var/www/html/{% if MULTISITE == "yes" %}{{ SERVER_NAME.split(" ")[0] }}{% endif %}{% else %}{{ ROOT_FOLDER }}{% endif %};
modsecurity off;
internal;
auth_basic off;
}
{% endfor %}
{% endif %}
{% if INTERCEPTED_ERROR_CODES != "" %}
{% for intercepted_error_code in INTERCEPTED_ERROR_CODES.split(" ") %}
{% if not intercepted_error_code + "=" in ERRORS +%}
{% if intercepted_error_code == "400" %}
error_page 400 /bwerror400;
{% else %}
error_page {{ intercepted_error_code }} @bwerror{{ intercepted_error_code }};
{% endif %}
{% endfor %}
{%- endif %}
location {% if intercepted_error_code == "400" %}= /{% else %} @{% endif %}bwerror{{ intercepted_error_code }} {
auth_basic off;
internal;
modsecurity off;
default_type 'text/html';
root /usr/share/bunkerweb/core/errors/files;
content_by_lua_block {
local logger = require "bunkerweb.logger"
local cerrors = require "errors.errors"
local errors = cerrors:new()
errors:render_template(tostring(ngx.status))
}
{%- if INTERCEPTED_ERROR_CODES != "" -%}
{%- for intercepted_error_code in INTERCEPTED_ERROR_CODES.split(" ") %}
{%- if not intercepted_error_code + "=" in ERRORS -%}
{%- if intercepted_error_code == "400" -%}
error_page 400 /bwerror400;
{%- else -%}
error_page {{ intercepted_error_code }} @bwerror{{ intercepted_error_code }};
{%- endif %}
location {% if intercepted_error_code == "400" %}= /{% else %} @{% endif %}bwerror{{ intercepted_error_code }} {
auth_basic off;
internal;
modsecurity off;
default_type 'text/html';
root /usr/share/bunkerweb/core/errors/files;
content_by_lua_block {
local logger = require "bunkerweb.logger"
local cerrors = require "errors.errors"
local errors = cerrors:new()
errors:render_template(tostring(ngx.status))
}
}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{%- endfor %}
{%- endif %}

View file

@ -1,7 +1,7 @@
{% if USE_GZIP == "yes" +%}
{%- if USE_GZIP == "yes" -%}
gzip on;
gzip_types {{ GZIP_TYPES }};
gzip_comp_level {{ GZIP_COMP_LEVEL }};
gzip_min_length {{ GZIP_MIN_LENGTH }};
gzip_proxied {{ GZIP_PROXIED }};
{% endif %}
{%- endif %}

View file

@ -1,5 +1,5 @@
{% for k, v in all.items() %}
{% if k.startswith("COOKIE_FLAGS") and v != "" +%}
set_cookie_flag {{ v }};
{% endif +%}
{% endfor %}
{%- for k, v in all.items() %}
{%- if k.startswith("COOKIE_FLAGS") and v != "" %}
set_cookie_flag {{ v }};
{% endif %}
{%- endfor %}

View file

@ -1,6 +1,6 @@
{% if INJECT_BODY != "" +%}
{%- if INJECT_BODY != "" -%}
sub_filter '</body>' '{{ INJECT_BODY }}</body>';
{% endif %}
{% if INJECT_HEAD != "" +%}
{% if INJECT_HEAD != "" -%}
sub_filter '</head>' '{{ INJECT_HEAD }}</head>';
{% endif %}
{%- endif %}

View file

@ -1,4 +1,4 @@
{% if has_variable(all, "USE_LIMIT_CONN", "yes") +%}
{%- if has_variable(all, "USE_LIMIT_CONN", "yes") -%}
map $http2 $v1ip {
default "";
@ -23,4 +23,4 @@ limit_conn_log_level warn;
limit_conn_status 429;
{% endif %}
{%- endif %}

View file

@ -1,7 +1,5 @@
{% if USE_LIMIT_CONN == "yes" +%}
{%- if USE_LIMIT_CONN == "yes" -%}
limit_conn v1ips {{ LIMIT_CONN_MAX_HTTP1 }};
limit_conn v2ips {{ LIMIT_CONN_MAX_HTTP2 }};
limit_conn v3ips {{ LIMIT_CONN_MAX_HTTP3 }};
{% endif %}
{%- endif %}

View file

@ -1,5 +1,3 @@
{% if USE_LIMIT_CONN == "yes" +%}
{%- if USE_LIMIT_CONN == "yes" -%}
limit_conn sips {{ LIMIT_CONN_MAX_STREAM }};
{% endif %}
{%- endif %}

View file

@ -1,6 +1,4 @@
{% if has_variable(all, "USE_LIMIT_CONN", "yes") +%}
{%- if has_variable(all, "USE_LIMIT_CONN", "yes") -%}
limit_conn_zone $binary_remote_addr zone=sips:10m;
limit_conn_log_level warn;
{% endif %}
{%- endif %}

View file

@ -1,11 +1,12 @@
{% if DISABLE_DEFAULT_SERVER == "yes" +%}
{%- if DISABLE_DEFAULT_SERVER == "yes" -%}
location / {
set $reason "default";
set $reason_data "";
return {{ DENY_HTTP_STATUS }};
set $reason "default";
set $reason_data "";
return {{ DENY_HTTP_STATUS }};
}
{% endif %}
{% if DISABLE_DEFAULT_SERVER_STRICT_SNI == "yes" +%}
{%- if DISABLE_DEFAULT_SERVER_STRICT_SNI == "yes" -%}
ssl_client_hello_by_lua_block {
local ssl_clt = require "ngx.ssl.clienthello"
local utils = require "bunkerweb.utils"
@ -60,4 +61,4 @@ ssl_client_hello_by_lua_block {
logger:log(WARN, "unknown SNI host " .. host .. ", denying access")
exit(ERROR)
}
{% endif %}
{%- endif %}

View file

@ -1,4 +1,4 @@
{% if IS_LOADING != "yes" and DISABLE_DEFAULT_SERVER == "no" +%}
{%- if IS_LOADING != "yes" and DISABLE_DEFAULT_SERVER == "no" -%}
location / {
etag off;
add_header Last-Modified "";
@ -44,4 +44,4 @@ location / {
})
}
}
{% endif %}
{%- endif %}

View file

@ -1,6 +1,6 @@
{% if USE_OPEN_FILE_CACHE == "yes" +%}
{%- if USE_OPEN_FILE_CACHE == "yes" -%}
open_file_cache {{ OPEN_FILE_CACHE }};
open_file_cache_errors {% if OPEN_FILE_CACHE_ERRORS == "yes" +%} on {% else +%} off {% endif +%};
open_file_cache_errors {% if OPEN_FILE_CACHE_ERRORS == "yes" %}on{% else %}off{% endif %};
open_file_cache_min_uses {{ OPEN_FILE_CACHE_MIN_USES }};
open_file_cache_valid {{ OPEN_FILE_CACHE_VALID }};
{% endif +%}
{%- endif %}

View file

@ -1,6 +1,6 @@
{% if SERVE_FILES == "yes" +%}
root {% if ROOT_FOLDER == "" %}/var/www/html/{% if MULTISITE == "yes" %}{{ SERVER_NAME.split(" ")[0] }}{% endif %}{% else %}{{ ROOT_FOLDER }}{% endif %};
try_files $uri $uri/ =404;
{% else +%}
root /nowhere;
{% endif %}
{%- if SERVE_FILES == "yes" -%}
root {% if ROOT_FOLDER == "" %}/var/www/html/{% if MULTISITE == "yes" %}{{ SERVER_NAME.split(" ")[0] }}{% endif %}{% else %}{{ ROOT_FOLDER }}{% endif %};
try_files $uri $uri/ =404;
{%- else -%}
root /nowhere;
{%- endif %}

View file

@ -1,9 +1,9 @@
{% if USE_MODSECURITY == "yes" and MODSECURITY_CRS_VERSION == "3" and HTTP3 == "yes" +%}
{%- if USE_MODSECURITY == "yes" and MODSECURITY_CRS_VERSION == "3" and HTTP3 == "yes" -%}
SecAction \
"id:900230,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0'"
{% endif %}
phase:1,\
nolog,\
pass,\
t:none,\
setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0'"
{%- endif %}

View file

@ -1,141 +1,144 @@
{% set pathlib = import("pathlib") %}
{% set json = import("json") %}
{% set service_id = SERVER_NAME.split(" ")[0] %}
# process rules with disruptive actions
{% if SECURITY_MODE == "block" %}
{%- set pathlib = import("pathlib") -%}
{%- set json = import("json") -%}
{%- set service_id = SERVER_NAME.split(" ")[0] -%}
# Process rules with disruptive actions
{% if SECURITY_MODE == "block" -%}
SecRuleEngine {{ MODSECURITY_SEC_RULE_ENGINE }}
{% else %}
{% else -%}
SecRuleEngine DetectionOnly
{% endif %}
# allow body checks
# Allow body checks
SecRequestBodyAccess On
# enable XML parsing
# Enable XML parsing
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
"id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
"id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
# enable JSON parsing
# Enable JSON parsing
SecRule REQUEST_HEADERS:Content-Type "application/json" \
"id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
"id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
# maximum data size
{% if MAX_CLIENT_SIZE.endswith("k") or MAX_CLIENT_SIZE.endswith("K") %}
# Maximum data size (Generated from MAX_CLIENT_SIZE)
{% if MAX_CLIENT_SIZE.endswith("k") or MAX_CLIENT_SIZE.endswith("K") -%}
SecRequestBodyLimit {{ MAX_CLIENT_SIZE[:-1] | int * 1024 }}
{% elif MAX_CLIENT_SIZE.endswith("m") or MAX_CLIENT_SIZE.endswith("M") %}
{% elif MAX_CLIENT_SIZE.endswith("m") or MAX_CLIENT_SIZE.endswith("M") -%}
SecRequestBodyLimit {{ MAX_CLIENT_SIZE[:-1] | int * 1024 * 1024 }}
{% elif MAX_CLIENT_SIZE.endswith("g") or MAX_CLIENT_SIZE.endswith("G") %}
{% elif MAX_CLIENT_SIZE.endswith("g") or MAX_CLIENT_SIZE.endswith("G") -%}
SecRequestBodyLimit {{ MAX_CLIENT_SIZE[:-1] | int * 1024 * 1024 * 1024 }}
{% elif MAX_CLIENT_SIZE.isdigit() %}
{% elif MAX_CLIENT_SIZE.isdigit() -%}
SecRequestBodyLimit {{ MAX_CLIENT_SIZE }}
{% else %}
{% else -%}
SecRequestBodyLimit 13107200
{% endif %}
# Maximum data size for requests without files
SecRequestBodyNoFilesLimit 131072
# reject requests if bigger than max data size
# Reject requests if bigger than max data size
SecRequestBodyLimitAction Reject
# reject if we can't process the body
# Reject if we can't process the body
SecRule REQBODY_ERROR "!@eq 0" \
"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
# be strict with multipart/form-data body
# Be strict with multipart/form-data body
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
"id:'200003',phase:2,t:none,log,deny,status:400, \
msg:'Multipart request body failed strict validation: \
PE %{REQBODY_PROCESSOR_ERROR}, \
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
DB %{MULTIPART_DATA_BEFORE}, \
DA %{MULTIPART_DATA_AFTER}, \
HF %{MULTIPART_HEADER_FOLDING}, \
LF %{MULTIPART_LF_LINE}, \
SM %{MULTIPART_MISSING_SEMICOLON}, \
IQ %{MULTIPART_INVALID_QUOTING}, \
IP %{MULTIPART_INVALID_PART}, \
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
"id:'200003',phase:2,t:none,log,deny,status:400, \
msg:'Multipart request body failed strict validation: \
PE %{REQBODY_PROCESSOR_ERROR}, \
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
DB %{MULTIPART_DATA_BEFORE}, \
DA %{MULTIPART_DATA_AFTER}, \
HF %{MULTIPART_HEADER_FOLDING}, \
LF %{MULTIPART_LF_LINE}, \
SM %{MULTIPART_MISSING_SEMICOLON}, \
IQ %{MULTIPART_INVALID_QUOTING}, \
IP %{MULTIPART_INVALID_PART}, \
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
SecRule MULTIPART_UNMATCHED_BOUNDARY "@eq 1" \
"id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
"id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
# enable response body checks
# Enable response body checks
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml application/json
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
# log usefull stuff
# Log useful stuff
SecAuditEngine {{ MODSECURITY_SEC_AUDIT_ENGINE }}
SecAuditLogParts {{ MODSECURITY_SEC_AUDIT_LOG_PARTS }}
SecAuditLogType Serial
SecAuditLog /var/log/bunkerweb/modsec_audit.log
{% if USE_MODSECURITY_CRS == "yes" +%}
{% if USE_MODSECURITY_CRS == "yes" -%}
# include OWASP CRS configurations
{% if MODSECURITY_CRS_VERSION == "nightly" %}
{% if pathlib.Path("/var/cache/bunkerweb/modsecurity/crs/nightly/crs-setup-nightly.conf").is_file() %}
{% if MODSECURITY_CRS_VERSION == "nightly" %}
{%- if pathlib.Path("/var/cache/bunkerweb/modsecurity/crs/nightly/crs-setup-nightly.conf").is_file() %}
include /var/cache/bunkerweb/modsecurity/crs/nightly/crs-setup-nightly.conf
{% else %}
{%- else %}
# fallback to the default CRS setup as the nightly one is not available
include /usr/share/bunkerweb/core/modsecurity/files/crs-setup-v4.conf
{% endif %}
{% else %}
{%- endif %}
{% else %}
include /usr/share/bunkerweb/core/modsecurity/files/crs-setup-v{{ MODSECURITY_CRS_VERSION }}.conf
{% endif %}
{% endif %}
{% if USE_MODSECURITY_CRS_PLUGINS == "yes" and MODSECURITY_CRS_VERSION != "3" %}
{% if USE_MODSECURITY_CRS_PLUGINS == "yes" and MODSECURITY_CRS_VERSION != "3" -%}
# custom CRS plugins configurations before loading plugins
{% if is_custom_conf("/etc/bunkerweb/configs/crs-plugins-before") %}
{% if is_custom_conf("/etc/bunkerweb/configs/crs-plugins-before") %}
include /etc/bunkerweb/configs/crs-plugins-before/*.conf
{% endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/bunkerweb/configs/crs-plugins-before/" + service_id) %}
{% endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/bunkerweb/configs/crs-plugins-before/" + service_id) %}
include /etc/bunkerweb/configs/crs-plugins-before/{{ service_id }}/*.conf
{% endif %}
{% if is_custom_conf("/etc/nginx/crs-plugins-before") %}
{% endif %}
{% if is_custom_conf("/etc/nginx/crs-plugins-before") %}
include /etc/nginx/crs-plugins-before/*.conf
{% endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/nginx/" + service_id + "/crs-plugins-before/") %}
{% endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/nginx/" + service_id + "/crs-plugins-before/") %}
include /etc/nginx/{{ service_id }}/crs-plugins-before/*.conf
{% endif %}
{% endif %}
{% with plugins_path = pathlib.Path("/var/cache/bunkerweb/modsecurity/crs/plugins") %}
{% with plugins_file = pathlib.Path("/var/cache/bunkerweb/modsecurity/crs-plugins.json") %}
{% if plugins_path.is_dir() and plugins_file.is_file() %}
{% with service_plugins = json.loads(plugins_file.read_text()) %}
{% with plugins_path = pathlib.Path("/var/cache/bunkerweb/modsecurity/crs/plugins") %}
{% with plugins_file = pathlib.Path("/var/cache/bunkerweb/modsecurity/crs-plugins.json") %}
{% if plugins_path.is_dir() and plugins_file.is_file() %}
{% with service_plugins = json.loads(plugins_file.read_text()) %}
# include downloaded CRS plugins configurations and before rules
{% for plugin_id in service_plugins.get(service_id, []) %}
{% if plugins_path.joinpath(plugin_id).is_dir() %}
{% for plugin_id in service_plugins.get(service_id, []) %}
{% if plugins_path.joinpath(plugin_id).is_dir() %}
include /var/cache/bunkerweb/modsecurity/crs/plugins/{{ plugin_id }}/*-config.conf
{% if plugins_path.joinpath(plugin_id).glob("*-before.conf") | list %}
{% if plugins_path.joinpath(plugin_id).glob("*-before.conf") | list %}
include /var/cache/bunkerweb/modsecurity/crs/plugins/{{ plugin_id }}/*-before.conf
{% endif %}
{% endif %}
{% endfor %}
{% endwith %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endwith %}
{% endwith %}
{% endif %}
{% endif %}
{% endwith %}
{% endwith %}
{% endif %}
# custom CRS configurations before loading rules (e.g. exclusions)
{% if is_custom_conf("/etc/bunkerweb/configs/modsec-crs") %}
{% if is_custom_conf("/etc/bunkerweb/configs/modsec-crs") %}
include /etc/bunkerweb/configs/modsec-crs/*.conf
{% endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/bunkerweb/configs/modsec-crs/" + service_id) %}
{% endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/bunkerweb/configs/modsec-crs/" + service_id) %}
include /etc/bunkerweb/configs/modsec-crs/{{ service_id }}/*.conf
{% endif %}
{% if is_custom_conf("/etc/nginx/modsec-crs") %}
{% endif %}
{% if is_custom_conf("/etc/nginx/modsec-crs") %}
include /etc/nginx/modsec-crs/*.conf
{% endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/nginx/" + service_id + "/modsec-crs/") %}
{% endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/nginx/" + service_id + "/modsec-crs/") %}
include /etc/nginx/{{ service_id }}/modsec-crs/*.conf
{% endif %}
{% endif %}
# unset REASON env var
SecAction "nolog,phase:1,setenv:REASON=none"
# Auto update allowed methods
# Auto update allowed methods (Generated from ALLOWED_METHODS)
SecAction \
"id:900200,\
phase:1,\
@ -144,53 +147,53 @@ SecAction \
t:none,\
setvar:'tx.allowed_methods={{ ALLOWED_METHODS.replace("|", " ") }}'"
{% if USE_WHITELIST == "yes" -%}
# Check if client is whitelisted
{% if USE_WHITELIST == "yes" +%}
SecRule ENV:is_whitelisted "yes" "id:1000,phase:1,allow,nolog,ctl:ruleEngine=Off"
{% endif +%}
{% endif -%}
# include OWASP CRS rules
{% if MODSECURITY_CRS_VERSION == "nightly" %}
{% if pathlib.Path("/var/cache/bunkerweb/modsecurity/crs/nightly/crs-nightly/rules").is_dir() %}
{% if MODSECURITY_CRS_VERSION == "nightly" %}
{%- if pathlib.Path("/var/cache/bunkerweb/modsecurity/crs/nightly/crs-nightly/rules").is_dir() %}
include /var/cache/bunkerweb/modsecurity/crs/nightly/crs-nightly/rules/*.conf
{% else %}
{%- else %}
# fallback to the default CRS setup as the nightly one is not available
include /usr/share/bunkerweb/core/modsecurity/files/coreruleset-v4/rules/*.conf
{% endif %}
{% else %}
{%- endif %}
{% else %}
include /usr/share/bunkerweb/core/modsecurity/files/coreruleset-v{{ MODSECURITY_CRS_VERSION }}/rules/*.conf
{% endif %}
{% endif %}
{% if USE_MODSECURITY_CRS_PLUGINS == "yes" and MODSECURITY_CRS_VERSION != "3" %}
{% if USE_MODSECURITY_CRS_PLUGINS == "yes" and MODSECURITY_CRS_VERSION != "3" %}
# custom CRS plugins configurations after loading plugins
{% if is_custom_conf("/etc/bunkerweb/configs/crs-plugins-after") %}
{%- if is_custom_conf("/etc/bunkerweb/configs/crs-plugins-after") %}
include /etc/bunkerweb/configs/crs-plugins-after/*.conf
{% endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/bunkerweb/configs/crs-plugins-after/" + service_id) %}
{%- endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/bunkerweb/configs/crs-plugins-after/" + service_id) %}
include /etc/bunkerweb/configs/crs-plugins-after/{{ service_id }}/*.conf
{% endif %}
{% if is_custom_conf("/etc/nginx/crs-plugins-after") %}
{% endif %}
{% if is_custom_conf("/etc/nginx/crs-plugins-after") %}
include /etc/nginx/crs-plugins-after/*.conf
{% endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/nginx/" + service_id + "/crs-plugins-after/") %}
{% endif %}
{% if MULTISITE == "yes" and is_custom_conf("/etc/nginx/" + service_id + "/crs-plugins-after/") %}
include /etc/nginx/{{ service_id }}/crs-plugins-after/*.conf
{% endif %}
{% endif %}
{% with plugins_path = pathlib.Path("/var/cache/bunkerweb/modsecurity/crs/plugins") %}
{% with plugins_file = pathlib.Path("/var/cache/bunkerweb/modsecurity/crs-plugins.json") %}
{% if plugins_path.is_dir() and plugins_file.is_file() %}
{% with service_plugins = json.loads(plugins_file.read_text()) %}
{% with plugins_path = pathlib.Path("/var/cache/bunkerweb/modsecurity/crs/plugins") %}
{% with plugins_file = pathlib.Path("/var/cache/bunkerweb/modsecurity/crs-plugins.json") %}
{% if plugins_path.is_dir() and plugins_file.is_file() %}
# include downloaded CRS plugins after rules
{% for plugin_id in service_plugins.get(service_id, []) %}
{% if plugins_path.joinpath(plugin_id).is_dir() and plugins_path.joinpath(plugin_id).glob("*-after.conf") | list %}
{% with service_plugins = json.loads(plugins_file.read_text()) %}
{% for plugin_id in service_plugins.get(service_id, []) %}
{% if plugins_path.joinpath(plugin_id).is_dir() and plugins_path.joinpath(plugin_id).glob("*-after.conf") | list %}
include /var/cache/bunkerweb/modsecurity/crs/plugins/{{ plugin_id }}/*-after.conf
{% endif %}
{% endfor %}
{% endwith %}
{% endif %}
{% endif %}
{% endfor %}
{% endwith %}
{% endwith %}
{% endif %}
{% endif %}
{% endwith %}
{% endwith %}
{% endif %}
{% endif +%}
# custom rules after loading the CRS
@ -207,14 +210,11 @@ include /etc/nginx/modsec/*.conf
include /etc/nginx/{{ service_id }}/modsec/*.conf
{% endif %}
{% if USE_MODSECURITY_CRS == "yes" %}
{% if USE_MODSECURITY_CRS == "yes" -%}
# set REASON env var
SecRuleUpdateActionById 949110 "t:none,deny,status:{{ DENY_HTTP_STATUS }},setenv:REASON=modsecurity"
SecRuleUpdateActionById 959100 "t:none,deny,status:{{ DENY_HTTP_STATUS }},setenv:REASON=modsecurity"
# let BW manage when method is not allowed (and save up some computing)
SecRuleUpdateActionById 911100 "t:none,allow,nolog"
{% endif %}
{%- endif %}

View file

@ -1,4 +1,4 @@
{% if USE_MODSECURITY == "yes" +%}
{%- if USE_MODSECURITY == "yes" -%}
modsecurity on;
modsecurity_rules_file {{ NGINX_PREFIX }}server-http/modsecurity-rules.conf.modsec;
{% endif %}
{%- endif %}

View file

@ -1,16 +1,12 @@
{% if USE_REAL_IP == "yes" +%}
{% for element in read_lines("/var/cache/bunkerweb/realip/combined.list") +%}
{%- if USE_REAL_IP == "yes" -%}
{% for element in read_lines("/var/cache/bunkerweb/realip/combined.list") %}
set_real_ip_from {{ element }};
{% endfor +%}
{% endfor %}
{% if REAL_IP_FROM != "" %}
{% for element in REAL_IP_FROM.split(" ") +%}
{% for element in REAL_IP_FROM.split(" ") %}
set_real_ip_from {{ element }};
{% endfor %}
{% endif %}
real_ip_header {{ REAL_IP_HEADER }};
{% if REAL_IP_RECURSIVE == "yes" +%}
real_ip_recursive on;
{% else +%}
real_ip_recursive off;
{% endif +%}
{% endif %}
real_ip_recursive {% if REAL_IP_RECURSIVE == "yes" %}on{% else %}off{% endif %};
{%- endif %}

View file

@ -1,16 +1,12 @@
{% if USE_REAL_IP == "yes" +%}
{% for element in read_lines("/var/cache/bunkerweb/realip/combined.list") +%}
{%- if USE_REAL_IP == "yes" -%}
{% for element in read_lines("/var/cache/bunkerweb/realip/combined.list") %}
set_real_ip_from {{ element }};
{% endfor +%}
{% endfor %}
{% if REAL_IP_FROM != "" %}
{% for element in REAL_IP_FROM.split(" ") +%}
{% for element in REAL_IP_FROM.split(" ") %}
set_real_ip_from {{ element }};
{% endfor %}
{% endif %}
real_ip_header {{ REAL_IP_HEADER }};
{% if REAL_IP_RECURSIVE == "yes" +%}
real_ip_recursive on;
{% else +%}
real_ip_recursive off;
{% endif +%}
{% endif %}
real_ip_recursive {% if REAL_IP_RECURSIVE == "yes" %}on{% else %}off{% endif %};
{%- endif %}

View file

@ -1,10 +1,10 @@
{% if USE_REAL_IP == "yes" +%}
{% for element in read_lines("/var/cache/bunkerweb/realip/combined.list") +%}
{%- if USE_REAL_IP == "yes" -%}
{% for element in read_lines("/var/cache/bunkerweb/realip/combined.list") %}
set_real_ip_from {{ element }};
{% endfor +%}
{% endfor %}
{% if REAL_IP_FROM != "" %}
{% for element in REAL_IP_FROM.split(" ") +%}
{% for element in REAL_IP_FROM.split(" ") %}
set_real_ip_from {{ element }};
{% endfor %}
{% endif %}
{% endif %}
{%- endif %}

View file

@ -1,9 +1,9 @@
{% if REDIRECT_TO != "" +%}
location / {
{% if REDIRECT_TO_REQUEST_URI == "yes" +%}
return {{ REDIRECT_TO_STATUS_CODE }} {{ REDIRECT_TO }}$request_uri;
{% else +%}
return {{ REDIRECT_TO_STATUS_CODE }} {{ REDIRECT_TO }};
{% endif %}
}
{% endif %}
{%- if REDIRECT_TO != "" -%}
location / {
{% if REDIRECT_TO_REQUEST_URI == "yes" %}
return {{ REDIRECT_TO_STATUS_CODE }} {{ REDIRECT_TO }}$request_uri;
{% else %}
return {{ REDIRECT_TO_STATUS_CODE }} {{ REDIRECT_TO }};
{% endif %}
}
{%- endif %}

View file

@ -1,8 +1,8 @@
{% if has_variable(all, "USE_PROXY_CACHE", "yes") +%}
{%- if has_variable(all, "USE_PROXY_CACHE", "yes") -%}
proxy_cache_path /var/tmp/bunkerweb/proxy_cache levels={{ PROXY_CACHE_PATH_LEVELS }} keys_zone=proxycache:{{ PROXY_CACHE_PATH_ZONE_SIZE }} {{ PROXY_CACHE_PATH_PARAMS }};
{% endif %}
{% endif %}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
default upgrade;
'' close;
}

View file

@ -1,39 +1,38 @@
{% if USE_REVERSE_PROXY == "yes" +%}
{%- if USE_REVERSE_PROXY == "yes" -%}
{% if REVERSE_PROXY_SSL_SNI == "yes" +%}
{%- if REVERSE_PROXY_SSL_SNI == "yes" -%}
proxy_ssl_server_name on;
{% if REVERSE_PROXY_SSL_SNI_NAME != "" +%}
{% if REVERSE_PROXY_SSL_SNI_NAME != "" %}
proxy_ssl_name {{ REVERSE_PROXY_SSL_SNI_NAME }};
{% endif +%}
{% else +%}
{% endif %}
{%- else -%}
proxy_ssl_server_name off;
{% endif +%}
{%- endif %}
{% if REVERSE_PROXY_INTERCEPT_ERRORS == "yes" +%}
{% if REVERSE_PROXY_INTERCEPT_ERRORS == "yes" %}
proxy_intercept_errors on;
{% else +%}
{% else %}
proxy_intercept_errors off;
{% endif +%}
{% endif %}
{% if USE_PROXY_CACHE == "yes" +%}
{% if USE_PROXY_CACHE == "yes" %}
proxy_cache proxycache;
proxy_cache_methods {{ PROXY_CACHE_METHODS }};
proxy_cache_min_uses {{ PROXY_CACHE_MIN_USES }};
proxy_cache_key {{ PROXY_CACHE_KEY }};
proxy_no_cache {{ PROXY_NO_CACHE }};
proxy_cache_bypass {{ PROXY_CACHE_BYPASS }};
{% if PROXY_CACHE_VALID != "" +%}
{% for element in PROXY_CACHE_VALID.split(" ") +%}
{% if PROXY_CACHE_VALID != "" %}
{% for element in PROXY_CACHE_VALID.split(" ") %}
proxy_cache_valid {{ element.split("=")[0] }} {{ element.split("=")[1] }};
{% endfor %}
add_header X-Proxy-Cache $upstream_cache_status;
{% endif %}
{% endif %}
{% set counter = namespace(value=1) %}
{% for k, v in all.items() %}
{% if k.startswith("REVERSE_PROXY_HOST") and v != "" +%}
{% if k.startswith("REVERSE_PROXY_HOST") and v != "" -%}
{% set host = v %}
{% set url = all[k.replace("HOST", "URL")] if k.replace("HOST", "URL") in all else "/" %}
{% set ws = all[k.replace("HOST", "WS")] if k.replace("HOST", "WS") in all else "" %}
@ -49,7 +48,7 @@ add_header X-Proxy-Cache $upstream_cache_status;
{% set send_timeout = all[k.replace("HOST", "SEND_TIMEOUT")] if k.replace("HOST", "SEND_TIMEOUT") in all else "60s" %}
{% set includes = all[k.replace("HOST", "INCLUDES")] if k.replace("HOST", "INCLUDES") in all else "" %}
{% set pass_request_body = all[k.replace("HOST", "PASS_REQUEST_BODY")] if k.replace("HOST", "PASS_REQUEST_BODY") in all else "" %}
location {{ url }} {% raw %}{{% endraw +%}
location {{ url }} {
etag off;
set $backend{{ counter.value }} "{{ host }}";
proxy_pass $backend{{ counter.value }};
@ -59,56 +58,53 @@ location {{ url }} {% raw %}{{% endraw +%}
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host {% if REVERSE_PROXY_CUSTOM_HOST != "" %}"{{ REVERSE_PROXY_CUSTOM_HOST }}"{% else %}$http_host{% endif %};
{% if url.startswith("/") +%}
{% if url.startswith("/") %}
proxy_set_header X-Forwarded-Prefix "{{ url }}";
{% endif %}
{% if buffering == "yes" +%}
proxy_buffering on;
{% else +%}
proxy_buffering off;
{% endif %}
{% if ws == "yes" +%}
{% endif %}
proxy_buffering {% if buffering == "yes" %}on{% else %}off{% endif %};
{% if ws == "yes" %}
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
{% elif keepalive == "yes" +%}
{% elif keepalive == "yes" %}
proxy_http_version 1.1;
proxy_set_header Connection "";
{% endif %}
{% if auth_request != "" +%}
{% endif %}
{% if auth_request != "" %}
auth_request {{ auth_request }};
{% endif +%}
{% if auth_request_signin_url != "" +%}
{% endif %}
{% if auth_request_signin_url != "" %}
error_page 401 =302 {{ auth_request_signin_url }};
{% endif +%}
{% if auth_request_sets != "" +%}
{% for auth_request_set in auth_request_sets.split(";") +%}
{% endif %}
{% if auth_request_sets != "" %}
{% for auth_request_set in auth_request_sets.split(";") %}
auth_request_set {{ auth_request_set }};
{% endfor +%}
{% endif +%}
{% if headers != "" +%}
{% for header in headers.split(";") +%}
{% endfor %}
{% endif %}
{% if headers != "" %}
{% for header in headers.split(";") %}
proxy_set_header {{ header }};
{% endfor +%}
{% endif +%}
{% if headers_client != "" +%}
{% for header_client in headers_client.split(";") +%}
{% endfor %}
{% endif %}
{% if headers_client != "" %}
{% for header_client in headers_client.split(";") %}
add_header {{ header_client }};
{% endfor +%}
{% endif +%}
{% endfor %}
{% endif %}
proxy_connect_timeout {{ connect_timeout }};
proxy_read_timeout {{ read_timeout }};
proxy_send_timeout {{ send_timeout }};
{% if includes != "" +%}
{% for include in includes.split(" ") +%}
{% if includes != "" %}
{% for include in includes.split(" ") %}
include {{ include }};
{% endfor +%}
{% endif +%}
{% if pass_request_body == "no" +%}
{% endfor %}
{% endif %}
{% if pass_request_body == "no" %}
proxy_pass_request_body off;
{% endif +%}
{% raw %}}{% endraw %}
{% endif %}
{% endif %}
}
{% set counter.value = counter.value + 1 %}
{% endif %}
{% endfor %}
{% endif %}
{%- endif %}

View file

@ -1,20 +1,19 @@
{% if USE_REVERSE_PROXY == "yes" and REVERSE_PROXY_HOST != "" +%}
{% if REVERSE_PROXY_SSL_SNI == "yes" +%}
{%- if USE_REVERSE_PROXY == "yes" and REVERSE_PROXY_HOST != "" -%}
{%- if REVERSE_PROXY_SSL_SNI == "yes" -%}
proxy_ssl_server_name on;
{% if REVERSE_PROXY_SSL_SNI_NAME != "" +%}
{% if REVERSE_PROXY_SSL_SNI_NAME != "" %}
proxy_ssl_name {{ REVERSE_PROXY_SSL_SNI_NAME }};
{% endif +%}
{% else +%}
{% endif %}
{%- else %}
proxy_ssl_server_name off;
{% endif +%}
{%- endif %}
# TODO : more settings specific to stream
{% if REVERSE_PROXY_STREAM_PROXY_PROTOCOL == "yes" +%}
# TODO: Add more settings specific to stream
{% if REVERSE_PROXY_STREAM_PROXY_PROTOCOL == "yes" %}
proxy_protocol on;
{% endif +%}
{% endif %}
set $backend "{{ SERVER_NAME.split(" ")[0] }}";
proxy_pass $backend;
{% endif %}
{%- endif %}

View file

@ -1,4 +1,4 @@
{% if USE_SECURITYTXT == "yes" and SECURITYTXT_CONTACT != "" +%}
{%- if USE_SECURITYTXT == "yes" and SECURITYTXT_CONTACT != "" -%}
location = {{ SECURITYTXT_URI }} {
default_type 'text/plain; charset=utf-8';
root /usr/share/bunkerweb/core/securitytxt/files;
@ -35,4 +35,4 @@ location = {{ SECURITYTXT_URI }} {
location = /security.txt {
return 301 {{ SECURITYTXT_URI }};
}
{% endif %}
{%- endif %}

View file

@ -1,4 +1,4 @@
{% if UI_HOST != "" and not has_variable(all, "USE_UI", "yes") +%}
{%- if UI_HOST != "" and not has_variable(all, "USE_UI", "yes") -%}
access_by_lua_block {
local ngx_var = ngx.var
local scheme = ngx_var.scheme
@ -123,5 +123,4 @@ location /setup/check {
end
}
}
{% endif +%}
{%- endif %}

View file

@ -1,5 +1,5 @@
{% if USE_UI == "yes" +%}
{%- if USE_UI == "yes" -%}
SecRule REQUEST_FILENAME "@rx /(global-config|services/.+)$" "id:7771,ctl:ruleRemoveById=932235,nolog"
SecRule REQUEST_FILENAME "@rx /(services|cache)/.+$" "id:7772,ctl:ruleRemoveById=920440,nolog"
SecRule REQUEST_FILENAME "@endsWith /logs" "id:7773,ctl:ruleRemoveById=953100,nolog"
{% endif +%}
{%- endif %}

View file

@ -1,4 +1,4 @@
SecRuleRemoveById 930120
{% if USE_UI == "yes" and "TLSv1.3" in SSL_PROTOCOLS and HTTP3 == "yes" +%}
{% if USE_UI == "yes" and "TLSv1.3" in SSL_PROTOCOLS and HTTP3 == "yes" %}
SecRuleRemoveById 920280
{% endif +%}
{% endif %}