Code Monkey home page Code Monkey logo

bunkerity / bunkerweb Goto Github PK

View Code? Open in Web Editor NEW
3.5K 46.0 219.0 371.12 MB

πŸ›‘οΈ Make your web services secure by default !

Home Page: https://www.bunkerweb.io

License: GNU Affero General Public License v3.0

Dockerfile 1.66% Shell 19.28% Lua 8.85% Python 41.22% CSS 4.54% JavaScript 12.49% HTML 11.63% HCL 0.32% PHP 0.01%
nginx modsecurity docker security dnsbl reverse-proxy bunkerized-nginx hardening web-security security-tuning

bunkerweb's Introduction

BunkerWeb logo



🌐 Website | 🀝 Panel | πŸ““ Documentation | πŸ‘¨β€πŸ’» Demo | πŸ›‘οΈ Examples | πŸ’¬ Chat | πŸ“ Forum
βš™οΈ Configurator | πŸ—ΊοΈ Threatmap

πŸ›‘οΈ Make security by default great again !

BunkerWeb

Overview banner

BunkerWeb is a next-generation and open-source Web Application Firewall (WAF).

Being a full-featured web server (based on NGINX under the hood), it will protect your web services to make them "secure by default". BunkerWeb integrates seamlessly into your existing environments (Linux, Docker, Swarm, Kubernetes, …) and is fully configurable (don't panic, there is an awesome web UI if you don't like the CLI) to meet your own use-cases . In other words, cybersecurity is no more a hassle.

BunkerWeb contains primary security features as part of the core but can be easily extended with additional ones thanks to a plugin system.

Why BunkerWeb ?

  • Easy integration into existing environments : Seamlessly integrate BunkerWeb into various environments such as Linux, Docker, Swarm, Kubernetes and more. Enjoy a smooth transition and hassle-free implementation.
  • Highly customizable : Tailor BunkerWeb to your specific requirements with ease. Enable, disable, and configure features effortlessly, allowing you to customize the security settings according to your unique use case.
  • Secure by default : BunkerWeb provides out-of-the-box, hassle-free minimal security for your web services. Experience peace of mind and enhanced protection right from the start.
  • Awesome web UI : Take control of BunkerWeb more efficiently with the exceptional web user interface (UI). Navigate settings and configurations effortlessly through a user-friendly graphical interface, eliminating the need for the command-line interface (CLI).
  • Plugin system : Extend the capabilities of BunkerWeb to meet your own use cases. Seamlessly integrate additional security measures and customize the functionality of BunkerWeb according to your specific requirements.
  • Free as in "freedom" : BunkerWeb is licensed under the free AGPLv3 license, embracing the principles of freedom and openness. Enjoy the freedom to use, modify, and distribute the software, backed by a supportive community.
  • Professional services : Get technical support, tailored consulting and custom development directly from the maintainers of BunkerWeb. Visit the Bunker Panel for more information.

Security features

A non-exhaustive list of security features :

  • HTTPS support with transparent Let's Encrypt automation
  • State-of-the-art web security : HTTP security headers, prevent leaks, TLS hardening, ...
  • Integrated ModSecurity WAF with the OWASP Core Rule Set
  • Automatic ban of strange behaviors based on HTTP status code
  • Apply connections and requests limit for clients
  • Block bots by asking them to solve a challenge (e.g. : cookie, javascript, captcha, hCaptcha or reCAPTCHA)
  • Block known bad IPs with external blacklists and DNSBL
  • And much more ...

Learn more about the core security features in the security tuning section of the documentation.

Demo

BunkerWeb demo

A demo website protected with BunkerWeb is available at demo.bunkerweb.io. Feel free to visit it and perform some security tests.

PRO version

When using BunkerWeb you have the choice of the version you want to use : open-source or PRO.

Whether it's enhanced security, an enriched user experience, or technical supervision, the BunkerWeb PRO version will allow you to fully benefit from BunkerWeb and respond to your professional needs.

Be it in the documentation or the user interface, the PRO features are annotated with a crown crow pro icon to distinguish them from those integrated into the open-source version.

You can upgrade from the open-source version to the PRO one easily and at any time you want. The process is pretty straightforward :

Do not hesitate to visit the BunkerWeb panel or contact us if you have any question regarding the PRO version.

Professional services

Get the most of BunkerWeb by getting professional services directly from the maintainers of the project. From technical support to tailored consulting and development, we are here to assist you in the security of your web services.

You will find more information by visiting the BunkerWeb Panel, our dedicated platform for professional services.

Don't hesitate to contact us if you have any question, we will be more than happy to respond to your needs.

Ecosystem, community and resources

Official websites, tools and resources about BunkerWeb :

  • Website : get more information, news and articles about BunkerWeb
  • Panel : dedicated platform to order and manage professional services (e.g. technical support) around BunkerWeb
  • Documentation : technical documentation of the BunkerWeb solution
  • Demo : demonstration website of BunkerWeb, don't hesitate to attempt attacks to test the robustness of the solution
  • Configurator : user-friendly tool to help you configure BunkerWeb
  • Threatmap : live cyber attack blocked by BunkerWeb instances all around the world

Community and social networks :

Concepts

Concepts banner

You will find more information about the key concepts of BunkerWeb in the documentation.

Integrations

The first concept is the integration of BunkerWeb into the target environment. We prefer to use the word "integration" instead of "installation" because one of the goals of BunkerWeb is to integrate seamlessly into existing environments.

The following integrations are officially supported :

Settings

Once BunkerWeb is integrated into your environment, you will need to configure it to serve and protect your web applications.

The configuration of BunkerWeb is done by using what we call the "settings" or "variables". Each setting is identified by a name such as AUTO_LETS_ENCRYPT or USE_ANTIBOT. You can assign values to the settings to configure BunkerWeb.

Here is a dummy example of a BunkerWeb configuration :

SERVER_NAME=www.example.com
AUTO_LETS_ENCRYPT=yes
USE_ANTIBOT=captcha
REFERRER_POLICY=no-referrer
USE_MODSECURITY=no
USE_GZIP=yes
USE_BROTLI=no

You will find an easy to use settings generator at config.bunkerweb.io.

Multisite mode

The multisite mode is a crucial concept to understand when using BunkerWeb. Because the goal is to protect web applications, we intrinsically inherit the concept of "virtual host" or "vhost" (more info here) which makes it possible to serve multiple web applications from a single (or a cluster of) instance.

By default, the multisite mode of BunkerWeb is disabled which means that only one web application will be served and all the settings will be applied to it. The typical use case is when you have a single application to protect : you don't have to worry about the multisite and the default behavior should be the right one for you.

When multisite mode is enabled, BunkerWeb will serve and protect multiple web applications. Each web application is identified by a unique server name and have its own set of settings. The typical use case is when you have multiple applications to protect and you want to use a single (or a cluster depending of the integration) instance of BunkerWeb.

Custom configurations

Because meeting all the use cases only using the settings is not an option (even with external plugins), you can use custom configurations to solve your specific challenges.

Under the hood, BunkerWeb uses the notorious NGINX web server, that's why you can leverage its configuration system for your specific needs. Custom NGINX configurations can be included in different contexts like HTTP or server (all servers and/or specific server block).

Another core component of BunkerWeb is the ModSecurity Web Application Firewall : you can also use custom configurations to fix some false positives or add custom rules for example.

Database

Database model

State of the current configuration of BunkerWeb is stored in a backend database which contains the following data :

  • Settings defined for all the services
  • Custom configurations
  • BunkerWeb instances
  • Metadata about jobs execution
  • Cached files

The following backend database are supported : SQLite, MariaDB, MySQL and PostgreSQL

Scheduler

To make things automagically work together, a dedicated service called the scheduler is in charge of :

  • Storing the settings and custom configurations inside the database
  • Executing various tasks (called jobs)
  • Generating a configuration which is understood by BunkerWeb
  • Being the intermediary for other services (like web UI or autoconf)

In other words, the scheduler is the brain of BunkerWeb.

Setup

Docker

Docker banner

We provide ready to use prebuilt images for x64, x86, armv7 and arm64 platforms on Docker Hub.

Docker integration key concepts are :

  • Environment variables to configure BunkerWeb
  • Scheduler container to store configuration and execute jobs
  • Networks to expose ports for clients and connect to upstream web services

You will find more information in the Docker integration section of the documentation.

Docker autoconf

Docker autoconf banner

The downside of using environment variables is that the container needs to be recreated each time there is an update which is not very convenient. To counter that issue, you can use another image called autoconf which will listen for Docker events and automatically reconfigure BunkerWeb in real-time without recreating the container.

Instead of defining environment variables for the BunkerWeb container, you simply add labels to your web applications containers and the autoconf will "automagically" take care of the rest.

You will find more information in the Docker autoconf section of the documentation.

Swarm

Swarm banner

To automatically configure BunkerWeb instances, a special service, called autoconf will listen for Docker Swarm events like service creation or deletion and automatically configure the BunkerWeb instances in real-time without downtime.

Like the Docker autoconf integration, configuration for web services is defined using labels starting with the special bunkerweb. prefix.

You will find more information in the Swarm section of the documentation.

Kubernetes

Kubernetes banner

The autoconf acts as an Ingress controller and will configure the BunkerWeb instances according to the Ingress resources. It also monitors other Kubernetes objects like ConfigMap for custom configurations.

You will find more information in the Kubernetes section of the documentation.

Linux

Linux banner

List of supported Linux distros :

  • Debian 12 "Bookworm"
  • Ubuntu 22.04 "Jammy"
  • Fedora 39
  • RHEL 8.9
  • RHEL 9.3

Repositories of Linux packages for BunkerWeb are available on PackageCloud, they provide a bash script to automatically add and trust the repository (but you can also follow the manual installation instructions if you prefer).

You will find more information in the Linux section of the documentation.

Ansible

Ansible banner

List of supported Linux distros :

  • Debian 12 "Bookworm"
  • Ubuntu 22.04 "Jammy"
  • Fedora 39
  • RHEL 8.9
  • RHEL 9.3

Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.

A specific BunkerWeb Ansible role is available on Ansible Galaxy (source code is available here).

You will find more information in the Ansible section of the documentation.

Vagrant

We maintain ready to use Vagrant boxes hosted on Vagrant cloud for the following providers :

  • virtualbox
  • libvirt

You will find more information in the Vagrant section of the documentation.

Quickstart guide

Once you have setup BunkerWeb with the integration of your choice, you can follow the quickstart guide that will cover the following common use cases :

  • Protecting a single HTTP application
  • Protecting multiple HTTP application
  • Retrieving the real IP of clients when operating behind a load balancer
  • Adding custom configurations
  • Protecting generic TCP/UDP applications
  • In combination with PHP

Security tuning

BunkerWeb offers many security features that you can configure with settings. Even if the default values of settings ensure a minimal "security by default", we strongly recommend you to tune them. By doing so you will be able to ensure a security level of your choice but also manage false positives.

You will find more information in the security tuning section of the documentation.

Settings

To help you tuning BunkerWeb we have made an easy to use settings generator tool available at config.bunkerweb.io.

As a general rule when multisite mode is enabled, if you want to apply settings with multisite context to a specific server you will need to add the primary (first) server name as a prefix like www.example.com_USE_ANTIBOT=captcha or myapp.example.com_USE_GZIP=yes for example.

When settings are considered as "multiple", it means that you can have multiple groups of settings for the same feature by adding numbers as suffix like REVERSE_PROXY_URL_1=/subdir, REVERSE_PROXY_HOST_1=http://myhost1, REVERSE_PROXY_URL_2=/anotherdir, REVERSE_PROXY_HOST_2=http://myhost2, ... for example.

Check the settings section of the documentation to get the full list.

Web UI

The "Web UI" is a web application that helps you manage your BunkerWeb instance using a user-friendly interface instead of the command-line one.

  • Start, stop, restart and reload your BunkerWeb instance
  • Add, edit and delete settings for your web applications
  • Add, edit and delete custom configurations for NGINX and ModSecurity
  • Install and uninstall external plugins
  • Explore the cached files
  • Monitor jobs execution
  • View the logs and search pattern

You will find more information in the Web UI section of the documentation.

Plugins

BunkerWeb comes with a plugin system to make it possible to easily add new features. Once a plugin is installed, you can manage it using additional settings defined by the plugin.

Here is the list of "official" plugins that we maintain (see the bunkerweb-plugins repository for more information) :

Name Version Description Link
ClamAV 1.4 Automatically scans uploaded files with the ClamAV antivirus engine and denies the request when a file is detected as malicious. bunkerweb-plugins/clamav
Coraza 1.4 Inspect requests using a the Coraza WAF (alternative of ModSecurity). bunkerweb-plugins/coraza
CrowdSec 1.4 CrowdSec bouncer for BunkerWeb. bunkerweb-plugins/crowdsec
Discord 1.4 Send security notifications to a Discord channel using a Webhook. bunkerweb-plugins/discord
Slack 1.4 Send security notifications to a Slack channel using a Webhook. bunkerweb-plugins/slack
VirusTotal 1.4 Automatically scans uploaded files with the VirusTotal API and denies the request when a file is detected as malicious. bunkerweb-plugins/virustotal
WebHook 1.4 Send security notifications to a custom HTTP endpoint using a Webhook. bunkerweb-plugins/slack

You will find more information in the plugins section of the documentation.

Support

Professional

Get technical support directly from the BunkerWeb maintainers. You will find more information by visiting the BunkerWeb Panel, our dedicated platform for professional services.

Don't hesitate to contact us if you have any question, we will be more than happy to respond to your needs.

Community

To get free community support you can use the following media :

Please don't use GitHub issues to ask for help, use it only for bug reports and feature requests.

License

This project is licensed under the terms of the GNU Affero General Public License (AGPL) version 3.

Contribute

If you would like to contribute to the plugins you can read the contributing guidelines to get started.

Security policy

We take security bugs as serious issues and encourage responsible disclosure, see our security policy for more information.

Stargazers over time

Stargazers over time

bunkerweb's People

Contributors

adren avatar ajarmoszuk avatar axyfr avatar brawdunoir avatar crazy3lf avatar dependabot[bot] avatar facundoacevedo avatar ff6347 avatar fl0ppy-d1sk avatar gin-gitaxias avatar hado-k3n avatar mromanelli9 avatar myzel394 avatar nakinox avatar peterkimzz avatar pizmovc avatar syrk4web avatar thelittlefireman avatar theophilediot avatar vepito avatar zilosoft avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bunkerweb's Issues

compile.sh is insecure

The download of the nginx source with wget isn't being verified against a known checksum. Also, all of the public git repos are being checked out without verifying their content. If one of the repos was compromised, or worse someone compromised the DNS server that your docker build server uses the image would be PWNed.

Ingress controller

Can this be used as k8s ingress controller?

I'm thinking the value of this amazing project falls down once it's actually used for anything serious, as nobody is serving webpages using plain docker.

Link open graph metadata preview doesn't work when paste website link

image

As you can see when I paste link in Slack chat, Google open graph metadata preview works well, but live demo link and also my website don't.

I wanted to see nginx log when I pasted link in Slack chat, but I couldn't see any logging.

Access to my website using a browser is working good, and there is no problem with my open graph HTML tags. (HTTP redirect status code also looks good)

All of 3rd party security service are off like this.

Same reason I tried to submit my /sitemap.xml file to any search engine except Google, they doesn't read the file.

docker-compose.yml

version: "3.8"

services:
  myreverse:
    image: bunkerity/bunkerized-nginx
    restart: always
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./letsencrypt:/etc/letsencrypt
      - ./nginx/http-configs:/http-confs
      - ./nginx/server-configs:/server-confs
    environment:
      - SERVER_NAME=www.example.com
      - SERVE_FILES=no
      - DISABLE_DEFAULT_SERVER=yes
      - REDIRECT_HTTP_TO_HTTPS=yes
      - AUTO_LETS_ENCRYPT=yes
      - X_FRAME_OPTIONS=SAMEORIGIN
      - USE_DNSBL=no
      - USE_FAIL2BAN=no
      - USE_MODSECURITY=no
      - USE_MODSECURITY_CRS=no
      - USE_CLAMAV_UPLOAD=no
      - USE_CLAMAV_SCAN=no
      - CLAMAV_SCAN_REMOVE=no
      - BLOCK_USER_AGENT=no
      - BLOCK_PROXIES=no
      - BLOCK_ABUSERS=no

Multisite basic auth

Hey guys, I am facing an issue setting up basic auth for multisite. Checking inside the container I can see an .htpasswd file is created for each server name in the related folder. Navigating to any of the server names and inserting correct credentials I get 403 forbidden and from logs I can see the error saying .htpasswd not found because it looks for the file in /etc/nginx/.htpasswd, while the file is in /etc/nginx/server_name/.htpasswd. Have you already face or are you aware of this?

[bug] Fail2ban can ban local subnet

Could it be possible to add a config options to setup non-blocking/ignoring network on fail2ban conf ?

like this :
FAIL2BAN_IGNOREIP=127.0.0.1/8 192.168.0.0/16 172.16.0.0/16

ignoreip = 127.0.0.1/8 192.168.0.0/16 172.16.0.0/16

nginx-jail.local

[nginx-filter]
bantime = %FAIL2BAN_BANTIME%
findtime = %FAIL2BAN_FINDTIME%
maxretry = %FAIL2BAN_MAXRETRY%
ignoreip = %FAIL2BAN_IGNOREIP%
enabled = true
action = nginx-action
logpath = /var/log/access.log

log :

2020-12-29 03:29:39,083 fail2ban.actions        [423]: NOTICE  [nginx-filter] 192.168.0.254 already banned
2020-12-29 03:29:39,638 fail2ban.filter         [423]: INFO    [nginx-filter] Found 192.168.0.254 - 2020-12-29 03:29:39
2020-12-29 03:29:39,839 fail2ban.filter         [423]: INFO    [nginx-filter] Found 192.168.0.254 - 2020-12-29 03:29:39
2020-12-29 03:29:41,041 fail2ban.filter         [423]: INFO    [nginx-filter] Found 192.168.0.254 - 2020-12-29 03:29:40
2020-12-29 03:29:41,642 fail2ban.filter         [423]: INFO    [nginx-filter] Found 192.168.0.254 - 2020-12-29 03:29:41

[bug] reverse-proxy-headers.conf is nerver used

hi,
In multisite with reverseproxy, the file confs/site/reverse-proxy.conf seems to never be included in the config.
grep -ril "reverse-proxy-headers.conf" ./

this lead to some errors where websockets don't work.

moreover this proxy header files is missing some mandatory header :

        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;

getting 403 error

I'd like to set custom nginx block upstream for load balancing and app version rolling update, but nginx throws error below.

nginx: [emerg] "upstream" directive is not allowed here in /server-confs/default.conf:1

Here are my codes.

docker-compose.yml

version: "3.8"

services:
  nginx:
    image: bunkerity/bunkerized-nginx
    volumes:
      - ./nginx/config:/server-confs
      - ./letsencrypt:/etc/letsencrypt
    ports:
      - 80:80
    environment:
      - SERVER_NAME=example.com
      - SERVE_FILES=no
      - DISABLE_DEFAULT_SERVER=yes
      - REDIRECT_HTTP_TO_HTTPS=yes
      - AUTO_LETS_ENCRYPT=yes

  blue:
    build:
      context: app

  green:
    build:
      context: app

default.conf

upstream proxy {
    server blue:3000;
    server green:3000;
}

proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

location / {
    proxy_pass http://proxy;
}

Nginx not starting

Hi, not sure how it started (a docker stack up updating it i think) but i can't get it working anymore :'(

Symptom: can't reach the gateway (ERR_CONNECTION_REFUSED).

Possible cause: [emerg] 17264#17264: open() "/var/log/nginx/error.log" failed (13: Permission denied)

Note that the /var/log/nginx/error.log path is not in a volume.

Log

[*] Starting bunkerized-nginx ...
[*] Configuring bunkerized-nginx ...
[*] Downloading bad user-agent list (in background) ...
[*] Downloading bad referrer list (in background) ...
[*] Downloading tor exit nodes list (in background) ...
[*] Downloading proxies list (in background) ...
[*] Downloading abusers list (in background) ...
[*] Updating clamav (in background) ...
[*] Single site - ************** configuration done 
[*] Running nginx ...
nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied)
2020/12/15 22:08:34 [notice] 17264#17264: ModSecurity-nginx v1.0.1 (rules loaded inline/local/remote: 0/0/0)
2020/12/15 22:08:34 [emerg] 17264#17264: open() "/var/log/nginx/error.log" failed (13: Permission denied)
==> /var/log/access.log <== 
2020-12-15T22:08:34.641385817Z
==> /var/log/error.log <==     

Config:

waf:
   image: bunkerity/bunkerized-nginx
   ports:
     - 80:8080
     - 443:8443
   volumes:
     - /*******/certificates/letsencrypt:/etc/letsencrypt
     - /*******/certificates:/certs
     - /*******/config/waf:/server-confs
     - /*******/config/waf/http:/http-confs
     - /*******/config/waf/modsec:/modsec-confs
     - /*******/config/waf/modsec-crs:/modsec-crs-confs
   environment:
     PROXY_REAL_IP: "yes"
     SERVER_NAME: "*********"
     #USE_CUSTOM_HTTPS: "yes"
     #CUSTOM_HTTPS_CERT: "/certs/certificate.crt"
     #CUSTOM_HTTPS_KEY: "/certs/certificate.key"
     AUTO_LETS_ENCRYPT: "yes"
     EMAIL_LETS_ENCRYPT: "************"
     REDIRECT_HTTP_TO_HTTPS: "yes"
     LISTEN_HTTP: "yes"
     SERVE_FILES: "no"
     DISABLE_DEFAULT_SERVER: "yes"
     MAX_CLIENT_SIZE: "32M"
     ALLOWED_METHODS: "GET|POST|PUT|DELETE|HEAD|PATCH"
     DNS_RESOLVERS: "127.0.0.11 8.8.8.8"
     USE_LIMIT_REQ: "80r/s"
     LIMIT_REQ_BURST: "50"
     LOGROTATE_MAXAGE: "30"
     USE_PHP: "no"
     FEATURE_POLICY: "accelerometer 'none'; autoplay 'none'; document-domain 'none'; encrypted-media 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; sync-xhr 'none'; usb 'none'"
     X_FRAME_OPTIONS: "sameorigin"
     CONTENT_SECURITY_POLICY: "frame-src 'self'; form-action 'self'" # form-action 'self'; block-all-mixed-content; base-uri 'self'; frame-src 'self'     sandbox allow-forms allow-same-origin allow-scripts; 
     USE_MODSECURITY_CRS: "no"
     USE_FAIL2BAN: "no"
     USE_MODSECURITY: "no"
     REFERRER_POLICY: "strict-origin-when-cross-origin"
   restart: always
   networks:
     - *******rk
   logging:
       options:
         max-size: "10m"
         max-file: "10"

error in documentation

you have an error in the multisite section. the documentation says to use the following settings:

      -e app1.domain.com_PROXY_URL=/ \
       -e app1.domain.com_PROXY_HOST=http://myapp1:8000 \
       -e app2.domain.com_PROXY_URL=/\
       -e app2.domain.com_PROXY_HOST=http://myapp2:8000

but it doesn't work.
I was only able to set it up after I changed these lines to the following:

       -e app1.domain.com_PROXY_URL=/ \
       -e app1.domain.com_REVERSE_PROXY_HOST=http://myapp1:8000 \
       -e app2.domain.com_PROXY_URL=/\
       -e app2.domain.com_REVERSE_PROXY_HOST=http://myapp2:8000

Please check this and correct it.

proxies.sh cpu usage

It seems overkill that for every restart the proxies.sh downloads and process the whole file... it takes a while and it consumes a lot of CPU. I guess it would be better to cache it somewhere in a volume or something else to speed things up.

Owasp CRS - TX:OUTBOUND_ANOMALY_SCORE - Prestashop

Hi @bunkerity ,

Hope you are still all well :-) !

I am trying to create a dockerized stack with all bunkerity services for a secured prestashop deploy.
It is almost done but I have some issues that I do not understand fully or maybe it is inherent to Prestashop's coding flaws ^^.

Randomly, I have this error message by ModSecurity when browsing the frontend or the backend.

nginx-bunkerized | 2020/11/30 05:53:03 
[error] 21820#21820: *1 
[client 78.244.147.20] ModSecurity: Access denied with code 403 (phase 4). Matched "Operator `Ge' with parameter `4' against variable `TX:OUTBOUND_ANOMALY_SCORE' (Value: `4' ) 
[file "/etc/nginx/owasp-crs/RESPONSE-959-BLOCKING-EVALUATION.conf"] 
[line "68"] 
[id "959100"] 
[rev ""] 
[msg "Outbound Anomaly Score Exceeded (Total Score: 4)"] 
[data ""] 
[severity "0"] 
[ver "OWASP_CRS/3.3.0"] 
[maturity "0"] 
[accuracy "0"] 
[tag "anomaly-evaluation"] 
[hostname "172.18.0.11"] 
[uri "/your-admin/index.php/common/notifications"] 
[unique_id "160671558369.757397"] 
[ref ""] while sending to client, client: X.X.X.X, server: your-domain.com, request: "GET /your-admin/index.php/common/notifications?_token=Zin_r3vpLV3aTIWgrEn6r7J58XLNt8fIn-_3jm0YGpo&rand=1606715538307 HTTP/2.0", upstream: "fastcgi://172.18.0.10:9000", host: "your-domain.com"

Ps. I changed de IP, domain and url values for generic values on purpose.

Do you know why ? Is there a way to tweak the TX:OUTBOUND_ANOMALY_SCORE ?

Thanks for any insights or inputs on that issue.

Cheers,
Luc

nginx fall down into container without error message

Nginx fall down into container without error message. Just in one moment my web application become not available.

image = "bunkerity/bunkerized-nginx:1.1.2"

my options

        "SERVE_FILES" = "no"
        "HTTP_PORT" = "80"
        "HTTPS_PORT" = "443"
        "USE_LIMIT_REQ" = "no"
        "LIMIT_REQ_BURST" = "1000"
        "USE_MODSECURITY" = "no"
        "USE_MODSECURITY_CRS" = "no"
        "AUTH_BASIC_LOCATION" = "sitewide"
        "REDIRECT_HTTP_TO_HTTPS" = "yes"
        "AUTO_LETS_ENCRYPT" = "yes"
        "DISABLE_DEFAULT_SERVER" = "yes"
        "USE_AUTH_BASIC" = "yes"
        "SERVER_NAME" = "my_sites"
        "AUTH_BASIC_USER" = "{{ auth_basic_user }}"
        "AUTH_BASIC_PASSWORD" =  "{{ auth_basic_password }}"
        "USE_DNSBL" = "no"

Double / in config multisite

hi,
When i use multisite, nginx modsecurity config path contains a double / :

/etc/nginx/nextcloud.mydomain # cat modsecurity.conf
modsecurity on;
modsecurity_rules_file /etc/nginx/nextcloud.mydomain//modsecurity-rules.conf;
/etc/nginx/nextcloud.mydomain # cat ../syno.mydomain/modsecurity.conf 
modsecurity on;
modsecurity_rules_file /etc/nginx/syno.mydomain//modsecurity-rules.conf;
/etc/nginx/nextcloud.mydomain # cat ../syno.mydomain/modsecurity-rules.conf 
# process rules with disruptive actions

Thanks

custom modsecurity conf by site when MULTISITE=yes doesn't work in dev branch

hi,
custom mod security by site doesn't work any more on Dev branch.

docker-compose

version: '3.5'

services: 
  nginx_test:
    image: bunkerity/bunkerized-nginx:latest
    container_name: nginx_test
    restart: always
    network_mode: "host"
    ports:
      - 10080
      - 10443
    volumes:
      - ./nginx_test/www:/www
      - ./nginx_test/letsencrypt:/etc/letsencrypt
      - ./nginx_test/server-confs:/server-confs # custom nginx confs at server context to make Nextcloud working
      - ./nginx_test/modsec-crs-confs:/modsec-crs-confs # custom Core Rule Set confs to add Nextcloud exclusions
      - ./nginx_test/modsec-confs:/modsec-confs # disable some false positive
      - ./nginx_test/cache:/cache # blacklist geoip
      # /etc/nginx/fail2ban-ip.conf
      # Set timezone
      - "/etc/TZ:/etc/timezone:ro"
      - "/etc/localtime:/etc/localtime:ro"
    environment:
      - MULTISITE=yes
      - AUTO_LETS_ENCRYPT=yes
      - EMAIL_LETS_ENCRYPT=admin@mydomain
      - SERVER_NAME=syno.mydomain nextcloud.mydomain bitwarden.mydomain portainer.mydomain # replace with your domain
      - SERVE_FILES=yes #allow serving single file on wwww
      - HTTP_PORT=10080
      - HTTPS_PORT=10443
      - HTTP2=yes
      - HTTPS_PROTOCOLS=TLSv1.2 TLSv1.3
      
      - USE_GZIP=yes
      - GZIP_COMP_LEVEL=7
      - GZIP_MIN_LENGTH=20
      - USE_BRTOLI=yes
      - BROTLI_COMP_LEVEL=7
      - BROTLI_MIN_LENGTH=20
      
      - FAIL2BAN_STATUS_CODE=400|401|403|405|444 #remove 404 ==> need to test
      - PROXY_REAL_IP=yes
      - PROXY_REAL_IP_HEADER=X-Forwarded-For
      - PROXY_REAL_IP_RECURSIVE=on
      - PROXY_REAL_IP_FROM=192.168.0.0/16 172.16.0.0/12 10.0.0.0/8
      - USE_REVERSE_PROXY=yes
      
[...]
      
      - nextcloud.mydomain_REVERSE_PROXY_URL=/
      - nextcloud.mydomain_REVERSE_PROXY_HOST=http://localhost:32680/
      - nextcloud.mydomain_REVERSE_PROXY_WS=yes
      - nextcloud.mydomain_ALLOWED_METHODS=GET|POST|HEAD|PROPFIND|DELETE|PUT|MKCOL|MOVE|COPY|PROPPATCH|REPORT
      - nextcloud.mydomain_MAX_CLIENT_SIZE=0
      
[...]
      
      #TODO librephotos
      - USE_DNSBL=yes #check if mail.mydomain is not blocked ...
     #- DNSBL_LIST=bl.blocklist.de problems.dnsbl.sorbs.net sbl.spamhaus.org xbl.spamhaus.org
      - USE_MODSECURITY=yes
      - USE_MODSECURITY_CRS=yes
      - USE_CROWDSEC=yes
      - BLOCK_USER_AGENT=yes
      - BLOCK_TOR_EXIT_NODE=yes
      - BLOCK_PROXIES=yes
      - BLOCK_ABUSERS=yes
      - USE_WHITELIST_REVERSE=no # default is true TODO custom whitelist
      - USE_BLACKLIST_REVERSE=yes
      - REDIRECT_HTTP_TO_HTTPS=yes
      - DISABLE_DEFAULT_SERVER=yes
      
      - USE_LIMIT_REQ=yes
      - LIMIT_REQ_RATE=40r/s
      - LIMIT_REQ_BURST=60
      - LIMIT_REQ_CACHE=50m
      - BLOCK_COUNTRY=cn ru
      - USE_CLAMAV_UPLOAD=yes
      - USE_CLAMAV_SCAN=yes
      - CLAMAV_SCAN_REMOVE=yes
      
      - USE_OPEN_FILE_CACHE=yes
      - OPEN_FILE_CACHE=max=1000 inactive=20s
      - OPEN_FILE_CACHE_ERRORS=on
      - OPEN_FILE_CACHE_MIN_USES=2
      - OPEN_FILE_CACHE_VALID=30s

/modsec-confs/nextcloud.mydomain/custom.conf

#45

SecRuleEngine DetectionOnly

SecRequestBodyLimit 512107200

### TEMP FIX BEFORE CRS 3.4 !!! ###

# Fix for Nextcloud Desktop Client
SecRule REQUEST_METHOD "@streq PROPFIND" \
    "id:9003108,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ver:'OWASP_CRS/3.3.0',\
    chain"
    SecRule REQUEST_FILENAME "@contains /remote.php/webdav" \
        "t:none,\
        ctl:ruleRemoveById=921110"

/modsec-crs-confs/nextcloud.mydomain/custom.conf

SecAction \
 "id:900130,\
  phase:1,\
  nolog,\
  pass,\
  t:none,\
  setvar:tx.crs_exclusions_nextcloud=1" # enable the nextcloud exclusion rules
  
SecAction \
 "id:900200,\
  phase:1,\
  nolog,\
  pass,\
  t:none,\
  setvar:'tx.allowed_methods=GET HEAD POST PROPFIND DELETE PUT MKCOL MOVE COPY PROPPATCH REPORT'"

result :

/etc/nginx/nextcloud.berlioz.me # cat modsecurity-rules.conf
# process rules with disruptive actions
SecRuleEngine On

# allow body checks
SecRequestBodyAccess On

# 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"

# enable JSON parsing
SecRule REQUEST_HEADERS:Content-Type "application/json" \
     "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"

# maximum data size
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072

# reject requests if bigger than max data size
SecRequestBodyLimitAction Reject

# 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"

# 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}'"
SecRule MULTIPART_UNMATCHED_BOUNDARY "@eq 1" \
    "id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"

# enable response body checks
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml application/json
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial

# log usefull stuff
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogType Serial
SecAuditLog /var/log/nginx/modsec_audit.log

# scan uploaded files with clamv
include /etc/nginx/nextcloud.berlioz.me/modsecurity-clamav.conf

# include OWASP CRS rules
include /etc/nginx/owasp-crs.conf
**### MISSING MODSECURITY LINE CUSTOM HERE ###**
include /etc/nginx/owasp-crs/*.conf

# include custom rules

Thanks

Bug with block contry

hi,

With the following configuration i've got this error :

[*] Starting bunkerized-nginx ...
sed: unmatched '/'
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Unable to register an account with ACME server
[*] Updating clamav (in background) ...
time="2020-11-11T20:21:03+01:00" level=info msg="api load configuration: configuration loaded successfully (base:https://tmsov6x2n9.execute-api.eu-west-1.amazonaws.com/v1/)"
time="2020-11-11T20:21:12+01:00" level=info msg="api load configuration: configuration loaded successfully (base:https://tmsov6x2n9.execute-api.eu-west-1.amazonaws.com/v1/)"
time="2020-11-11T20:21:12+01:00" level=info msg="dependency issue crowdsecurity/nginx : missing parsers crowdsecurity/nginx-logs, tainted."
time="2020-11-11T20:21:13+01:00" level=info msg="api signin: signed in successfuly"
time="2020-11-11T20:21:15+01:00" level=warning msg="api pull returned 100 entries"
time="2020-11-11T20:21:26+01:00" level=info msg="Wrote 100 bans from api to database."
[*] Running nginx ...
nginx: [emerg] unexpected "}" in /etc/nginx/geoip.conf:10
==> /var/log/access.log <==

==> /var/log/error.log <==

==> /var/log/fail2ban.log <==
2020-11-11 20:21:26,822 fail2ban.filter         [12799]: INFO      maxRetry: 15
2020-11-11 20:21:26,822 fail2ban.filter         [12799]: INFO      findtime: 60
2020-11-11 20:21:26,823 fail2ban.actions        [12799]: INFO      banTime: 3600
2020-11-11 20:21:26,823 fail2ban.filter         [12799]: INFO      encoding: UTF-8
2020-11-11 20:21:26,823 fail2ban.filter         [12799]: INFO    Added logfile: '/var/log/access.log' (pos = 0, hash = da39a3ee5e6b4b0d3255bfef95601890afd80709)
2020-11-11 20:21:26,825 fail2ban.jail           [12799]: INFO    Jail 'nginx-filter' started
2020-11-11 20:21:26,881 fail2ban.utils          [12799]: #39-Lev. 7fa7c0bfac30 -- exec: echo "" > /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload
2020-11-11 20:21:26,881 fail2ban.utils          [12799]: ERROR   7fa7c0bfac30 -- stderr: 'nginx: [emerg] unexpected "}" in /etc/nginx/geoip.conf:10'
2020-11-11 20:21:26,881 fail2ban.utils          [12799]: ERROR   7fa7c0bfac30 -- returned 1
2020-11-11 20:21:26,882 fail2ban.actions        [12799]: ERROR   Failed to start jail 'nginx-filter' action 'nginx-action': Error starting action Jail('nginx-filter')/nginx-action
^C

version: '3.5'

services: 
  nginx_test:
    image: bunkerity/bunkerized-nginx
    container_name: nginx_test
    restart: always
    network_mode: "host"
    ports:
      - 10080
      - 10443
    volumes:
      - ./nginx_test/www:/www
      - ./nginx_test/letsencrypt:/etc/letsencrypt
      - ./nginx_test/server-confs:/server-confs         # custom nginx confs at server context to make Nextcloud working
      - ./nginx_test/modsec-crs-confs:/modsec-crs-confs # custom Core Rule Set confs to add Nextcloud exclusions
      - ./nginx_test/modsec-confs:/modsec-confs         # disable some false positive
      # Set timezone
      - "/etc/TZ:/etc/timezone:ro"
      - "/etc/localtime:/etc/localtime:ro"
    environment:
      - SERVER_NAME="*REDACTED"          # replace with your domain
      - SERVE_FILES=yes
      - HTTP_PORT=10080
      - HTTPS_PORT=10443
      - PROXY_REAL_IP=yes
      - PROXY_REAL_IP_HEADER=X-Forwarded-For
      - PROXY_REAL_IP_RECURSIVE
      - USE_CROWDSEC=yes
      - AUTO_LETS_ENCRYPT=yes
      - REDIRECT_HTTP_TO_HTTPS=yes
      - DISABLE_DEFAULT_SERVER=yes
      - MAX_CLIENT_SIZE=10G
      - LIMIT_REQ_RATE=40r/s
      - LIMIT_REQ_BURST=60
      - LIMIT_REQ_CACHE=50m
      - BLOCK_COUNTRY="cn ru"
      - ALLOWED_METHODS=GET|POST|HEAD|PROPFIND|DELETE|PUT|MKCOL|MOVE|COPY|PROPPATCH|REPORT
      - X_FRAME_OPTIONS=SAMEORIGIN
     

DNS issues with reverse_proxy

Using reverse_proxy, error.log is full of lua udp socket read timed out even with upstream server with IP and no dns name.
Any idea?

Add socket capability to reverse proxy

Hi,
Could it be possible to configure reverse proxy as a websocket ?

proxy_set_header        Upgrade           $http_upgrade;
proxy_set_header        Connection        "upgrade";

I know it could be done by a custom nginx conf in /server-confs but an env variable would be great app.site_REVERSE_PROXY_WS=yes
Thanks for all :)

howto listen custom ports inside server context

Hello,

I'm using today the official nginx docker image and I'm using different ports for my differents apps on my NAS.
As an example

`server {

    listen 4000 ssl http2;
    server_name some_url.net;
    location / {
                proxy_pass https://insidemylan:2000;
    }

}`

I have multiple server entries in my nginx.conf file, how to achive this in your docker image ?
When I'm trying this it say that the server context is wrong here :(

Many thanks.
Rgds.

X-Frame-Options requires "SAMEORIGIN" for nextcloud for an A+ rating

Crowdsec can't parse the logs

hi,
It seems to have an issue with crowdsec
find this in logs :
time="2020-12-18T23:56:12+01:00" level=info msg="dependency issue crowdsecurity/nginx : missing parsers crowdsecurity/nginx-logs, tainted."

Thanks

Reverse Proxy : Upstream Servers error.

Trying to see if we can add multiple upstream load balancing servers.

upstream.conf

upstream xss-app {
least_conn;
server docker_xss-app_1:4001;
server docker_xss-app_2:4001;
server docker_xss-app_3:4001;
}

with reverse_proxy.conf referring to

proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

location / {
proxy_pass http://xss-app$request_uri;
}

Logs show the following error
nginx: [emerg] "upstream" directive is not allowed here in /server-confs/upstream.conf:1

Letencrypt challenge fail

Hello,

I am struggling with the AUTO_LETS_ENCRYPT feature,
i can't figure out how to get it working.

My compose config:

 waf:
    image: bunkerity/bunkerized-nginx
    ports:
      - 80:8080
      - 443:8443
    volumes:
      - /***/data/certificates/letsencrypt:/etc/letsencrypt
      - /***/data/certificates:/certs
      - /***/data/config/waf:/server-confs
      - /***/data/config/waf/www:/www
    environment:
      # PROXY_REAL_IP : "yes"
      SERVER_NAME: "*************************
      # USE_CUSTOM_HTTPS: "no"
      # CUSTOM_HTTPS_CERT: "/certs/certificate.crt"
      # CUSTOM_HTTPS_KEY: "/certs/certificate.key"
      AUTO_LETS_ENCRYPT: "yes"
      REDIRECT_HTTP_TO_HTTPS: "yes"
      # SERVE_FILES: "no"
      DISABLE_DEFAULT_SERVER: "yes"
      MAX_CLIENT_SIZE: "128M"
      ALLOWED_METHODS: "GET|POST|PUT|DELETE|OPTIONS"
      DNS_RESOLVERS: "127.0.0.11 1.1.1.1"
      USE_LIMIT_REQ: "30r/s"
      LIMIT_REQ_BURST: "50"
      LOGROTATE_MAXAGE: "30"
    user: "0:0"
    restart: always
    networks:
      - ****network
    logging:
        options:
          max-size: "10m"
          max-file: "3"

Server-conf:

large_client_header_buffers 4 32k;

proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

location / {

    proxy_buffer_size          128k;
    proxy_buffers              4 256k;
    proxy_busy_buffers_size    256k;
	
	if ($host = **************) {
		proxy_pass https://gateway$request_uri;
	}
}

iptables -S

(...)
-A DOCKER-INGRESS -p tcp -m tcp --dport 443 -j ACCEPT
-A DOCKER-INGRESS -p tcp -m state --state RELATED,ESTABLISHED -m tcp --sport 443 -j ACCEPT
-A DOCKER-INGRESS -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-INGRESS -p tcp -m state --state RELATED,ESTABLISHED -m tcp --sport 80 -j ACCEPT
(...)

Result:

[*] Starting bunkerized-nginx ...
   Saving debug log to /var/log/letsencrypt/letsencrypt.log
   Plugins selected: Authenticator standalone, Installer None
   Obtaining a new certificate
   Performing the following challenges: 
   http-01 challenge for ***************************
   Waiting for verification...
   Challenge failed for domain ***************************   
   http-01 challenge for ***************************

   Cleaning up challenges
   Some challenges have failed. 
   IMPORTANT NOTES:
    - The following errors were reported by the server:
   2020-10-29T23:28:40.928975608Z
      Domain: ***************************
      Type:   connection
      Detail: Fetching
      http://***************************/.well-known/acme-challenge/0XfBpKVTZVVwJxfOTTnEec3-T6It4f_uPKG0F0htzAY:
      Timeout during connect (likely firewall problem)
   2020-10-29T23:28:40.929022712Z
      To fix these errors, please make sure that your domain name was
      entered correctly and the DNS A/AAAA record(s) for that domain 
      contain(s) the right IP address. Additionally, please check that    
      your computer has a publicly routable IP address and that no
      firewalls are preventing the server from communicating with the
      client. If you're using the webroot plugin, you should also verify  
      that you are serving files from the webroot path you provided. 
   [*] Updating clamav (in background) ...
   [*] Running nginx ...
   nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/***************************/fullchain.pem": BIO_new_file() failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/etc/letsencrypt/live/***************************/ful   
   lchain.pem','r') error:2006D080:BIO routines:BIO_new_file:no such file)
   ==> /var/log/access.log <==
   2020-10-29T23:28:44.035917038Z
   ==> /var/log/error.log <==
   2020-10-29T23:28:44.035926738Z
   ==> /var/log/fail2ban.log <==

The A record is correct & the DNS propagation completed weeks ago (http & https working fine with a custom cert).

I am really stuck, any idea ?

[Bug or miss configuration] Header is not being passed

Hi, I've configured bunkerized-nginx as reverse proxy to serve Passbolt, it goes pretty well except for some actions like creating a new user or deactivating notifications, I don't know if this a miss configuration done by myself or some default config of ngnix.

What I get is that the CSRF token is not being passed.

This is how docker-compose.yml is running:

  nginx_reverse:
    image: bunkerity/bunkerized-nginx:1.0.0
    restart: always
    ports:
      - 80:80
      - 443:443
    volumes:
      - letsencrypt:/etc/letsencrypt:z
      - ./nginx-confs:/server-confs:ro,Z
    environment:
      - PROXY_REAL_IP=yes
      - DISABLE_DEFAULT_SERVER=yes
      - ALLOWED_METHODS=GET|POST|HEAD|PUT|DELETE
      - USE_MODSECURITY=no
      - REDIRECT_HTTP_TO_HTTPS=yes
      - AUTO_LETS_ENCRYPT=yes
    env_file:
      - env/nginx.env
    networks:
      - frontend

ModSecurity is disabled because some rules break the app.

This request is made with Bunkerized-nginx as reverse proxy, pay special attention to x-csrf-token that has a null value:

{
  "log": {
    "version": "2.2",
    "creator": {
      "name": "WebInspector",
      "version": "537.36"
    },
    "pages": [],
    "entries": [
      {
        "_initiator": {
          "type": "script",
          "stack": {
            "callFrames": [
              {
                "functionName": "n.exports.o.ajax",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 269136
              },
              {
                "functionName": "request",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 392049
              },
              {
                "functionName": "request",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 638917
              },
              {
                "functionName": "eval",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 412279
              },
              {
                "functionName": "updateData",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 913028
              },
              {
                "functionName": "t.<computed>",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 649431
              },
              {
                "functionName": "t.<computed>",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 651392
              },
              {
                "functionName": "save",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 654672
              },
              {
                "functionName": "save",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 659029
              },
              {
                "functionName": "eval",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 660245
              },
              {
                "functionName": "{window} #js_wsp_primary_menu_wrapper #js-email-notification-settings-save-button click",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 947680
              },
              {
                "functionName": "eval",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 408006
              },
              {
                "functionName": "eval",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 192637
              },
              {
                "functionName": "eval",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 192615
              },
              {
                "functionName": "eval",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 149887
              },
              {
                "functionName": "eachListLike",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 149650
              },
              {
                "functionName": "eachIndex",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 149279
              },
              {
                "functionName": "eachKey",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 149836
              },
              {
                "functionName": "each",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 149208
              },
              {
                "functionName": "n.delegated.<computed>",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 192484
              }
            ]
          }
        },
        "_priority": "High",
        "_resourceType": "xhr",
        "cache": {},
        "connection": "233806",
        "request": {
          "method": "POST",
          "url": "https://subdomain.domain.net/settings/emails/notifications.json?api-version=v2",
          "httpVersion": "http/2.0",
          "headers": [
            {
              "name": ":method",
              "value": "POST"
            },
            {
              "name": ":authority",
              "value": "subdomain.domain.net"
            },
            {
              "name": ":scheme",
              "value": "https"
            },
            {
              "name": ":path",
              "value": "/settings/emails/notifications.json?api-version=v2"
            },
            {
              "name": "content-length",
              "value": "583"
            },
            {
              "name": "x-csrf-token",
              "value": "null"
            },
            {
              "name": "x-requested-with",
              "value": "XMLHttpRequest"
            },
            {
              "name": "user-agent",
              "value": "Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"
            },
            {
              "name": "content-type",
              "value": "application/json"
            },
            {
              "name": "accept",
              "value": "*/*"
            },
            {
              "name": "origin",
              "value": "https://subdomain.domain.net"
            },
            {
              "name": "sec-fetch-site",
              "value": "same-origin"
            },
            {
              "name": "sec-fetch-mode",
              "value": "cors"
            },
            {
              "name": "sec-fetch-dest",
              "value": "empty"
            },
            {
              "name": "accept-encoding",
              "value": "gzip, deflate, br"
            },
            {
              "name": "accept-language",
              "value": "en-US,en;q=0.9,es-AR;q=0.8,es;q=0.7"
            },
            {
              "name": "cookie",
              "value": "experimentation_subject_id=ImEwN2NjNDhkLWZkMmYtNDY1NS1iMjFhLTE4NjM0YzZhZDkyOCI%3D--0e8341d10ce7540e63924a8efe750756a92585bd; csrfToken=94fc08e4fcf2a9c3bfe8f0c557487654188d9a7eddb8441fa64fdfc86d6be1cc36f10ef8b1f2bf8c9183146c8ce996bb3e34e0e64271ee1f500d3bf849735f83; CAKEPHP=etcdi31ncb43mpqjsrsr1f3q6b"
            }
          ],
          "queryString": [
            {
              "name": "api-version",
              "value": "v2"
            }
          ],
          "cookies": [
            {
              "name": "experimentation_subject_id",
              "value": "ImEwN2NjNDhkLWZkMmYtNDY1NS1iMjFhLTE4NjM0YzZhZDkyOCI%3D--0e8341d10ce7540e63924a8efe750756a92585bd",
              "expires": null,
              "httpOnly": false,
              "secure": false
            },
            {
              "name": "csrfToken",
              "value": "94fc08e4fcf2a9c3bfe8f0c557487654188d9a7eddb8441fa64fdfc86d6be1cc36f10ef8b1f2bf8c9183146c8ce996bb3e34e0e64271ee1f500d3bf849735f83",
              "expires": null,
              "httpOnly": false,
              "secure": false
            },
            {
              "name": "CAKEPHP",
              "value": "etcdi31ncb43mpqjsrsr1f3q6b",
              "expires": null,
              "httpOnly": false,
              "secure": false
            }
          ],
          "headersSize": -1,
          "bodySize": 583,
          "postData": {
            "mimeType": "application/json",
            "text": "{\"id\":\"327c9dcb-168e-4c4b-b487-eba30770601a\",\"show_comment\":true,\"show_description\":true,\"show_secret\":true,\"show_uri\":true,\"show_username\":true,\"send_comment_add\":false,\"send_password_create\":false,\"send_password_share\":true,\"send_password_update\":true,\"send_password_delete\":true,\"send_user_create\":true,\"send_user_recover\":true,\"send_group_delete\":true,\"send_group_user_add\":true,\"send_group_user_delete\":true,\"send_group_user_update\":true,\"send_group_manager_update\":true,\"purify_subject\":false,\"send_admin_user_setup_completed\":true,\"sources_database\":true,\"sources_file\":false}"
          }
        },
        "response": {
          "status": 403,
          "statusText": "",
          "httpVersion": "http/2.0",
          "headers": [
            {
              "name": "status",
              "value": "403"
            },
            {
              "name": "date",
              "value": "Mon, 02 Nov 2020 18:20:49 GMT"
            },
            {
              "name": "content-type",
              "value": "text/html; charset=UTF-8"
            },
            {
              "name": "expires",
              "value": "Thu, 19 Nov 1981 08:52:00 GMT"
            },
            {
              "name": "cache-control",
              "value": "no-store, no-cache, must-revalidate"
            },
            {
              "name": "pragma",
              "value": "no-cache"
            },
            {
              "name": "strict-transport-security",
              "value": "max-age=31536000"
            },
            {
              "name": "x-frame-options",
              "value": "DENY"
            },
            {
              "name": "x-xss-protection",
              "value": "1; mode=block"
            },
            {
              "name": "x-content-type-options",
              "value": "nosniff"
            },
            {
              "name": "content-security-policy",
              "value": "object-src 'none'; frame-ancestors 'self'; form-action 'self'; block-all-mixed-content; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';"
            },
            {
              "name": "referrer-policy",
              "value": "no-referrer"
            },
            {
              "name": "feature-policy",
              "value": "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vibrate 'none'; vr 'none'"
            }
          ],
          "cookies": [],
          "content": {
            "size": 4004,
            "mimeType": "text/html"
          },
          "redirectURL": "",
          "headersSize": -1,
          "bodySize": -1,
          "_transferSize": 4730,
          "_error": null
        },
        "serverIPAddress": "10.241.0.169",
        "startedDateTime": "2020-11-02T18:20:49.243Z",
        "time": 88.90899999823887,
        "timings": {
          "blocked": 4.649000003159046,
          "dns": -1,
          "ssl": -1,
          "connect": -1,
          "send": 0.4159999999999999,
          "wait": 82.3459999972703,
          "receive": 1.4979999978095293,
          "_blocked_queueing": 3.792000003159046
        }
      },
      {
        "_initiator": {
          "type": "script",
          "stack": {
            "callFrames": [
              {
                "functionName": "n.exports.o.ajax",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 269136
              },
              {
                "functionName": "request",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 392049
              },
              {
                "functionName": "request",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 638917
              },
              {
                "functionName": "eval",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 412279
              },
              {
                "functionName": "getData",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 912896
              },
              {
                "functionName": "t.<computed>",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 649431
              },
              {
                "functionName": "t.<computed>",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 651392
              },
              {
                "functionName": "get",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 653905
              },
              {
                "functionName": "eval",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 659945
              },
              {
                "functionName": "_initForm",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 946570
              },
              {
                "functionName": "afterStart",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 945748
              },
              {
                "functionName": "refresh",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 620285
              },
              {
                "functionName": "eval",
                "scriptId": "36",
                "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 947800
              }
            ],
            "parent": {
              "description": "Promise.catch",
              "callFrames": [
                {
                  "functionName": "{window} #js_wsp_primary_menu_wrapper #js-email-notification-settings-save-button click",
                  "scriptId": "36",
                  "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                  "lineNumber": 2,
                  "columnNumber": 947753
                },
                {
                  "functionName": "eval",
                  "scriptId": "36",
                  "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                  "lineNumber": 2,
                  "columnNumber": 408006
                },
                {
                  "functionName": "eval",
                  "scriptId": "36",
                  "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                  "lineNumber": 2,
                  "columnNumber": 192637
                },
                {
                  "functionName": "eval",
                  "scriptId": "36",
                  "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                  "lineNumber": 2,
                  "columnNumber": 192615
                },
                {
                  "functionName": "eval",
                  "scriptId": "36",
                  "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                  "lineNumber": 2,
                  "columnNumber": 149887
                },
                {
                  "functionName": "eachListLike",
                  "scriptId": "36",
                  "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                  "lineNumber": 2,
                  "columnNumber": 149650
                },
                {
                  "functionName": "eachIndex",
                  "scriptId": "36",
                  "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                  "lineNumber": 2,
                  "columnNumber": 149279
                },
                {
                  "functionName": "eachKey",
                  "scriptId": "36",
                  "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                  "lineNumber": 2,
                  "columnNumber": 149836
                },
                {
                  "functionName": "each",
                  "scriptId": "36",
                  "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                  "lineNumber": 2,
                  "columnNumber": 149208
                },
                {
                  "functionName": "n.delegated.<computed>",
                  "scriptId": "36",
                  "url": "https://subdomain.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                  "lineNumber": 2,
                  "columnNumber": 192484
                }
              ]
            }
          }
        },
        "_priority": "High",
        "_resourceType": "xhr",
        "cache": {},
        "connection": "233806",
        "request": {
          "method": "GET",
          "url": "https://subdomain.domain.net/settings/emails/notifications.json?api-version=v2",
          "httpVersion": "http/2.0",
          "headers": [
            {
              "name": ":method",
              "value": "GET"
            },
            {
              "name": ":authority",
              "value": "subdomain.domain.net"
            },
            {
              "name": ":scheme",
              "value": "https"
            },
            {
              "name": ":path",
              "value": "/settings/emails/notifications.json?api-version=v2"
            },
            {
              "name": "x-csrf-token",
              "value": "null"
            },
            {
              "name": "x-requested-with",
              "value": "XMLHttpRequest"
            },
            {
              "name": "user-agent",
              "value": "Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"
            },
            {
              "name": "content-type",
              "value": "application/x-www-form-urlencoded"
            },
            {
              "name": "accept",
              "value": "*/*"
            },
            {
              "name": "sec-fetch-site",
              "value": "same-origin"
            },
            {
              "name": "sec-fetch-mode",
              "value": "cors"
            },
            {
              "name": "sec-fetch-dest",
              "value": "empty"
            },
            {
              "name": "accept-encoding",
              "value": "gzip, deflate, br"
            },
            {
              "name": "accept-language",
              "value": "en-US,en;q=0.9,es-AR;q=0.8,es;q=0.7"
            },
            {
              "name": "cookie",
              "value": "experimentation_subject_id=ImEwN2NjNDhkLWZkMmYtNDY1NS1iMjFhLTE4NjM0YzZhZDkyOCI%3D--0e8341d10ce7540e63924a8efe750756a92585bd; csrfToken=94fc08e4fcf2a9c3bfe8f0c557487654188d9a7eddb8441fa64fdfc86d6be1cc36f10ef8b1f2bf8c9183146c8ce996bb3e34e0e64271ee1f500d3bf849735f83; CAKEPHP=etcdi31ncb43mpqjsrsr1f3q6b"
            }
          ],
          "queryString": [
            {
              "name": "api-version",
              "value": "v2"
            }
          ],
          "cookies": [
            {
              "name": "experimentation_subject_id",
              "value": "ImEwN2NjNDhkLWZkMmYtNDY1NS1iMjFhLTE4NjM0YzZhZDkyOCI%3D--0e8341d10ce7540e63924a8efe750756a92585bd",
              "expires": null,
              "httpOnly": false,
              "secure": false
            },
            {
              "name": "csrfToken",
              "value": "94fc08e4fcf2a9c3bfe8f0c557487654188d9a7eddb8441fa64fdfc86d6be1cc36f10ef8b1f2bf8c9183146c8ce996bb3e34e0e64271ee1f500d3bf849735f83",
              "expires": null,
              "httpOnly": false,
              "secure": false
            },
            {
              "name": "CAKEPHP",
              "value": "etcdi31ncb43mpqjsrsr1f3q6b",
              "expires": null,
              "httpOnly": false,
              "secure": false
            }
          ],
          "headersSize": -1,
          "bodySize": 0
        },
        "response": {
          "status": 200,
          "statusText": "",
          "httpVersion": "http/2.0",
          "headers": [
            {
              "name": "status",
              "value": "200"
            },
            {
              "name": "date",
              "value": "Mon, 02 Nov 2020 18:20:49 GMT"
            },
            {
              "name": "content-type",
              "value": "application/json"
            },
            {
              "name": "expires",
              "value": "Thu, 19 Nov 1981 08:52:00 GMT"
            },
            {
              "name": "cache-control",
              "value": "no-store, no-cache, must-revalidate"
            },
            {
              "name": "pragma",
              "value": "no-cache"
            },
            {
              "name": "content-security-policy",
              "value": "object-src 'none'; frame-ancestors 'self'; form-action 'self'; block-all-mixed-content; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';"
            },
            {
              "name": "x-permitted-cross-domain-policies",
              "value": "all"
            },
            {
              "name": "referrer-policy",
              "value": "no-referrer"
            },
            {
              "name": "x-frame-options",
              "value": "DENY"
            },
            {
              "name": "x-xss-protection",
              "value": "1; mode=block"
            },
            {
              "name": "x-download-options",
              "value": "noopen"
            },
            {
              "name": "x-content-type-options",
              "value": "nosniff"
            },
            {
              "name": "x-gpgauth-version",
              "value": "1.3.0"
            },
            {
              "name": "x-gpgauth-login-url",
              "value": "/auth/login"
            },
            {
              "name": "x-gpgauth-logout-url",
              "value": "/auth/logout"
            },
            {
              "name": "x-gpgauth-verify-url",
              "value": "/auth/verify"
            },
            {
              "name": "x-gpgauth-pubkey-url",
              "value": "/auth/verify.json"
            },
            {
              "name": "access-control-expose-headers",
              "value": "X-GPGAuth-Verify-Response, X-GPGAuth-Progress, X-GPGAuth-User-Auth-Token, X-GPGAuth-Authenticated, X-GPGAuth-Refer, X-GPGAuth-Debug, X-GPGAuth-Error, X-GPGAuth-Pubkey, X-GPGAuth-Logout-Url, X-GPGAuth-Version"
            },
            {
              "name": "strict-transport-security",
              "value": "max-age=31536000"
            },
            {
              "name": "feature-policy",
              "value": "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vibrate 'none'; vr 'none'"
            }
          ],
          "cookies": [],
          "content": {
            "size": 858,
            "mimeType": "application/json"
          },
          "redirectURL": "",
          "headersSize": -1,
          "bodySize": -1,
          "_transferSize": 1928,
          "_error": null
        },
        "serverIPAddress": "10.10.10.11",
        "startedDateTime": "2020-11-02T18:20:49.425Z",
        "time": 64.80399999418296,
        "timings": {
          "blocked": 4.338999991961755,
          "dns": -1,
          "ssl": -1,
          "connect": -1,
          "send": 0.2659999999999999,
          "wait": 58.77799999409914,
          "receive": 1.4210000081220642,
          "_blocked_queueing": 3.543999991961755
        }
      }
    ]
  }
}

This request is made using a vanilla nginx, x-csrf-token has a valid value:

  "log": {
    "version": "1.2",
    "creator": {
      "name": "WebInspector",
      "version": "537.36"
    },
    "pages": [
      {
        "startedDateTime": "2020-11-02T18:18:09.534Z",
        "id": "page_4",
        "title": "https://subdomain-dev.domain.net/",
        "pageTimings": {
          "onContentLoad": 293.0249999917578,
          "onLoad": 318.6520000017481
        }
      }
    ],
    "entries": [
      {
        "_initiator": {
          "type": "script",
          "stack": {
            "callFrames": [
              {
                "functionName": "n.exports.o.ajax",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 269136
              },
              {
                "functionName": "request",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 392049
              },
              {
                "functionName": "request",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 638917
              },
              {
                "functionName": "eval",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 412279
              },
              {
                "functionName": "updateData",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 913028
              },
              {
                "functionName": "t.<computed>",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 649431
              },
              {
                "functionName": "t.<computed>",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 651392
              },
              {
                "functionName": "save",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 654672
              },
              {
                "functionName": "save",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 659029
              },
              {
                "functionName": "eval",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 660245
              },
              {
                "functionName": "{window} #js_wsp_primary_menu_wrapper #js-email-notification-settings-save-button click",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 947680
              },
              {
                "functionName": "eval",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 408006
              },
              {
                "functionName": "eval",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 192637
              },
              {
                "functionName": "eval",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 192615
              },
              {
                "functionName": "eval",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 149887
              },
              {
                "functionName": "eachListLike",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 149650
              },
              {
                "functionName": "eachIndex",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 149279
              },
              {
                "functionName": "eachKey",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 149836
              },
              {
                "functionName": "each",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 149208
              },
              {
                "functionName": "n.delegated.<computed>",
                "scriptId": "122",
                "url": "https://subdomain-dev.domain.net/js/app/bundles/passbolt-appjs/passbolt.js",
                "lineNumber": 2,
                "columnNumber": 192484
              }
            ]
          }
        },
        "_priority": "High",
        "_resourceType": "xhr",
        "cache": {},
        "connection": "8485",
        "pageref": "page_4",
        "request": {
          "method": "POST",
          "url": "https://subdomain-dev.domain.net//settings/emails/notifications.json?api-version=v2",
          "httpVersion": "HTTP/1.1",
          "headers": [
            {
              "name": "Host",
              "value": "subdomain-dev.domain.net"
            },
            {
              "name": "Connection",
              "value": "keep-alive"
            },
            {
              "name": "Content-Length",
              "value": "583"
            },
            {
              "name": "X-CSRF-Token",
              "value": "365fa77d1598dcda191d8336a11900c91f861005fa2ac6e6e7509ad7892e1dddd776673bcf117231058eedf5ad8d19cf27060973bd1c91ce028beb5f294fb371"
            },
            {
              "name": "X-Requested-With",
              "value": "XMLHttpRequest"
            },
            {
              "name": "User-Agent",
              "value": "Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Accept",
              "value": "*/*"
            },
            {
              "name": "Origin",
              "value": "https://subdomain-dev.domain.net"
            },
            {
              "name": "Sec-Fetch-Site",
              "value": "same-origin"
            },
            {
              "name": "Sec-Fetch-Mode",
              "value": "cors"
            },
            {
              "name": "Sec-Fetch-Dest",
              "value": "empty"
            },
            {
              "name": "Referer",
              "value": "https://subdomain-dev.domain.net/"
            },
            {
              "name": "Accept-Encoding",
              "value": "gzip, deflate, br"
            },
            {
              "name": "Accept-Language",
              "value": "en-US,en;q=0.9"
            },
            {
              "name": "Cookie",
              "value": "csrfToken=365fa77d1598dcda191d8336a11900c91f861005fa2ac6e6e7509ad7892e1dddd776673bcf117231058eedf5ad8d19cf27060973bd1c91ce028beb5f294fb371; CAKEPHP=tikolcvn0g8l456gbes24rsb94"
            }
          ],
          "queryString": [
            {
              "name": "api-version",
              "value": "v2"
            }
          ],
          "cookies": [
            {
              "name": "csrfToken",
              "value": "365fa77d1598dcda191d8336a11900c91f861005fa2ac6e6e7509ad7892e1dddd776673bcf117231058eedf5ad8d19cf27060973bd1c91ce028beb5f294fb371",
              "expires": null,
              "httpOnly": false,
              "secure": false
            },
            {
              "name": "CAKEPHP",
              "value": "tikolcvn0g8l456gbes24rsb94",
              "expires": null,
              "httpOnly": false,
              "secure": false
            }
          ],
          "headersSize": 922,
          "bodySize": 583,
          "postData": {
            "mimeType": "application/json",
            "text": "{\"id\":\"46c2b106-6ce6-41a0-a05c-9e20f8241a3d\",\"show_comment\":true,\"show_description\":true,\"show_secret\":true,\"show_uri\":true,\"show_username\":true,\"send_comment_add\":false,\"send_password_create\":false,\"send_password_share\":true,\"send_password_update\":true,\"send_password_delete\":true,\"send_user_create\":true,\"send_user_recover\":true,\"send_group_delete\":true,\"send_group_user_add\":true,\"send_group_user_delete\":true,\"send_group_user_update\":true,\"send_group_manager_update\":true,\"purify_subject\":false,\"send_admin_user_setup_completed\":true,\"sources_database\":true,\"sources_file\":false}"
          }
        },
        "response": {
          "status": 200,
          "statusText": "OK",
          "httpVersion": "HTTP/1.1",
          "headers": [
            {
              "name": "Server",
              "value": "nginx/1.19.2"
            },
            {
              "name": "Date",
              "value": "Mon, 02 Nov 2020 18:18:38 GMT"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Transfer-Encoding",
              "value": "chunked"
            },
            {
              "name": "Connection",
              "value": "keep-alive"
            },
            {
              "name": "Expires",
              "value": "Thu, 19 Nov 1981 08:52:00 GMT"
            },
            {
              "name": "Cache-Control",
              "value": "no-store, no-cache, must-revalidate"
            },
            {
              "name": "Pragma",
              "value": "no-cache"
            },
            {
              "name": "Content-Security-Policy",
              "value": "default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self';frame-src 'self';"
            },
            {
              "name": "x-permitted-cross-domain-policies",
              "value": "all"
            },
            {
              "name": "referrer-policy",
              "value": "same-origin"
            },
            {
              "name": "x-frame-options",
              "value": "sameorigin"
            },
            {
              "name": "x-xss-protection",
              "value": "1; mode=block"
            },
            {
              "name": "x-download-options",
              "value": "noopen"
            },
            {
              "name": "x-content-type-options",
              "value": "nosniff"
            },
            {
              "name": "X-GPGAuth-Version",
              "value": "1.3.0"
            },
            {
              "name": "X-GPGAuth-Login-URL",
              "value": "/auth/login"
            },
            {
              "name": "X-GPGAuth-Logout-URL",
              "value": "/auth/logout"
            },
            {
              "name": "X-GPGAuth-Verify-URL",
              "value": "/auth/verify"
            },
            {
              "name": "X-GPGAuth-Pubkey-URL",
              "value": "/auth/verify.json"
            },
            {
              "name": "Access-Control-Expose-Headers",
              "value": "X-GPGAuth-Verify-Response, X-GPGAuth-Progress, X-GPGAuth-User-Auth-Token, X-GPGAuth-Authenticated, X-GPGAuth-Refer, X-GPGAuth-Debug, X-GPGAuth-Error, X-GPGAuth-Pubkey, X-GPGAuth-Logout-Url, X-GPGAuth-Version"
            }
          ],
          "cookies": [],
          "content": {
            "size": 891,
            "mimeType": "application/json",
            "compression": -12
          },
          "redirectURL": "",
          "headersSize": 1024,
          "bodySize": 903,
          "_transferSize": 1927,
          "_error": null
        },
        "serverIPAddress": "10.10.10.10",
        "startedDateTime": "2020-11-02T18:18:38.691Z",
        "time": 91.96499999961816,
        "timings": {
          "blocked": 4.45400000465940710.10.10.10,
          "dns": -1,
          "ssl": -1,
          "connect": -1,
          "send": 0.2250000000000001,
          "wait": 85.54699999559764,
          "receive": 1.7389999993611127,
          "_blocked_queueing": 3.603000004659407
        }
      }
    ]
  }
}

Thanks in advance :D

Releases & Tags

It's very useful to use tags in docker-hub and Releases here in github so we can pin a specific version to avoid surprises when using latest :P

nginx doesn't start

Whe I launched nginx with parameters:

        "SERVE_FILES" = "no"
        "DISABLE_DEFAULT_SERVER" = "yes"
        "USE_AUTH_BASIC" = "yes"
        "SERVER_NAME" = "elk-nomad-pro elk-nomad"
        "DISABLE_DEFAULT_SERVER" = "yes"
        "AUTH_BASIC_USER" = "nomad"
        "AUTH_BASIC_PASSWORD" = "mimimi"
        "AUTH_BASIC_TEXT" = "This is a nomad WebUI. elk-nomad-pro - is default UI, elk-nomad - is modern "
        "USE_MODSECURITY" = "yes"

and proxypass config

location / {
	if ($host = elk-nomad-pro) {
      proxy_pass http://nomad-ws$request_uri;
	}

	if ($host = elk-nomad) {
	  proxy_pass http://10.222.100.1:3000$request_uri;
	}

      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_read_timeout 310s;
      proxy_buffering off;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Origin "${scheme}://${proxy_host}";

}

after start container I get error message

nginx: [emerg] duplicate location "/" in /etc/nginx/auth-basic.conf:1

/etc/nginx # cat /etc/nginx/auth-basic.conf
location / {
	auth_basic "This is a nomad WebUI. elk-nomad-pro - is default UI, elk-nomad - is modern ";
	auth_basic_user_file /etc/nginx/.htpasswd;
}

my goal is it secur access to webui by password.

403 code on DELETE method

Nginx used as the reverse-proxy to other application.

I allow DELETE method by environment:
ALLOWED_METHODS=GET|POST|PUT|DELETE

But other applications don`t receive requests with DELETE method from Nginx, which always respond 403 to the browser. Another operation works correctly.

P.S I found root of the problem in mod_security. REQUEST-949-BLOCKING-EVALUATION.conf

Can I enabe auth_basic only for any server names?

Hi @bunkerity
I have server config

location ^~ /.well-known/acme-challenge/ {
    auth_basic off;
}

location / {
	if ($host = elk-nomad) {
      proxy_pass http://nomad-ws;
	}

	if ($host = elk-nomad-pro) {
	  proxy_pass http://nomad-ws-pro;
	}

    if ($host = logs) {
      proxy_pass http://kibana;
    }

      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_read_timeout 310s;
      proxy_buffering off;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Origin "${scheme}://${proxy_host}";

}

I have options

"AUTH_BASIC_LOCATION" = "sitewide"
"USE_AUTH_BASIC" = "yes"

and my goal it is auth_basic for elk-nomad and elk-nomad-pro. But for host = logs must be off.
I tried play with locations but it bad idea, becouse some locations is mixed beetween host names.

Now I seems like I have ony one solutions, it is two separate nginx - first with auth and secondary without + useing not 443 port for https.

Letsencrypt wildcard

hi,

is there a way for using or register a wildcard domain name in bunkerized-nginx ?
I now how to generate a wildcard certificate on certbot command line but could it be possible to add this feature in bunkerized-nginx ?

wildcard certificate in certbot sudo certbot certonly --manual -d *.mydomaine.net --agree-tos --no-bootstrap

the config I test : - SERVER_NAME="*.mydomaine.me nextcloud.mydomaine.me syno.mydomaine.me"

[*] Starting bunkerized-nginx ...
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Unable to register an account with ACME server
[*] Updating clamav (in background) ...
time="2020-11-11T20:29:22+01:00" level=info msg="api load configuration: configuration loaded successfully (base:https://tmsov6x2n9.execute-api.eu-west-1.amazonaws.com/v1/)"
time="2020-11-11T20:29:25+01:00" level=info msg="api load configuration: configuration loaded successfully (base:https://tmsov6x2n9.execute-api.eu-west-1.amazonaws.com/v1/)"
time="2020-11-11T20:29:25+01:00" level=info msg="dependency issue crowdsecurity/nginx : missing parsers crowdsecurity/nginx-logs, tainted."
time="2020-11-11T20:29:27+01:00" level=info msg="api signin: signed in successfuly"
time="2020-11-11T20:29:30+01:00" level=warning msg="api pull returned 100 entries"
time="2020-11-11T20:29:41+01:00" level=info msg="Wrote 100 bans from api to database."
[*] Running nginx ...
nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/"*.mydomaine.me/fullchain.pem": BIO_new_file() failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/etc/letsencrypt/live/"*.mydomaine.me/fullchain.pem','r') error:2006D080:BIO routines:BIO_new_file:no such file)
==> /var/log/access.log <==

==> /var/log/error.log <==

==> /var/log/fail2ban.log <==
2020-11-11 20:29:41,811 fail2ban.filter         [13030]: INFO      findtime: 60
2020-11-11 20:29:41,811 fail2ban.actions        [13030]: INFO      banTime: 3600
2020-11-11 20:29:41,812 fail2ban.filter         [13030]: INFO    Added logfile: '/var/log/access.log' (pos = 0, hash = da39a3ee5e6b4b0d3255bfef95601890afd80709)
2020-11-11 20:29:41,813 fail2ban.jail           [13030]: INFO    Jail 'nginx-filter' started
2020-11-11 20:29:41,960 fail2ban.utils          [13030]: #39-Lev. 7fbd51475c30 -- exec: echo "" > /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload
2020-11-11 20:29:41,960 fail2ban.utils          [13030]: ERROR   7fbd51475c30 -- stderr: 'nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/"*.mydomaine.me/fullchain.pem": BIO_new_file() failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen(\'/etc/letsencrypt/live/"*.mydomaine.me/fullchain.pem\',\'r\') error:2006D080:BIO routines:BIO_new_file:no such file)'
2020-11-11 20:29:41,960 fail2ban.utils          [13030]: ERROR   7fbd51475c30 -- returned 1
2020-11-11 20:29:41,960 fail2ban.actions        [13030]: ERROR   Failed to start jail 'nginx-filter' action 'nginx-action': Error starting action Jail('nginx-filter')/nginx-action

Thanks :)

Thanks

custom nginx config for prestashop

Hi guys, @bunkerity ,

Hope you are all well !

I was wondering how I could load custom nginx rules like url rewriting for prestashop with bunkerized-nginx:

Ref. https://github.com/lucmichalski/prestadock/tree/master/.docker/web/config/prestashop

worker_processes 2;
user web prestashop;

events {
    worker_connections 1024;
}

http {
    include mime.types;
    index index.php index.html;

    # server {
    #     listen 80 default_server;
    #     server_name localhost;
    #     return 301 https://$server_name$request_uri;
    # }

    server {
        set $admin_dir /admin-dummy;

        listen 80 default_server;
        server_name yourdomain;
        root /app;

        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;

        client_max_body_size 50M;

        # rewrite_log on;
        # error_log /dev/stderr notice;

        include prestashop/gzip.conf;

        location ~ /favicon.ico {
            log_not_found off;
            access_log off;
        }

        location = /robots.txt {
            auth_basic off;
            allow all;
            log_not_found off;
            access_log off;
        }

        location = /fpm-status {
            fastcgi_pass prestashop:9000;
        }
        location = /fpm-ping {
            fastcgi_pass prestashop:9000;
        }

        include prestashop/security.conf;
        include prestashop/friendly-urls.conf;

        location ~ \.php$ {
        try_files $uri =404;
            fastcgi_pass prestashop:9000;
        }
    }

    # server {
    #     listen 443 ssl;
    #     server_name localhost;
    #     ssl_certificate ;
    #     ssl_certificate_key ;
    #
    #     location / {
    #         alias /app;
    #     }
    # }

}

and how to setup the user user web prestashop ?

Thanks for any insights or inputs on that issues.

Cheers,
Luc

[bug] Crowdsec crash if nginx log contains IPv6

Hi,
On last dev version the lua script crash due to the fact that nginx log contains an ipv6 :

crowdsecurity/lua-cs-bouncer#7

2020/12/28 21:59:25 [error] 9518#9518: *80 lua entry thread aborted: runtime error: /usr/local/lib/lua/crowdsec/CrowdSec.lua:18: attempt to perform arithmetic on local 'o1' (a nil value)#012stack traceback:#012coroutine 0:#012#011/usr/local/lib/lua/crowdsec/CrowdSec.lua: in function 'ipToInt'#012#011/usr/local/lib/lua/crowdsec/CrowdSec.lua:70: in function 'allowIp'#012#011access_by_lua(main-lua.conf:166):105: in main chunk, client: 2a01:e0a:169:7f90::d73a:9b9d, server: nextcloud.mydomain, request: "PROPFIND /remote.php/dav/files/user/ HTTP/1.1", host: "nextcloud.mydomain"

original nginx log :

==> /var/log/access.log <==
2a01:e0a:169:7f90::d73a:9b9d - user nextcloud.mydomain [28/Dec/2020:21:59:25 +0100] "PROPFIND /remote.php/dav/files/user/ HTTP/1.1" 500 170 "-" "Mozilla/5.0 (Linux) mirall/3.1.1-20201225.075704.75c329f4f-1.0~groovy1 (Nextcloud)"

Should we wait lua script to be updated or do you need some help to make a quick bugfix ?

Nginx cannot resolve the host, occasional 502 bad gateway

Hey, thanks for you huge work here!

I'm facing an annoying behavior from nginx. I configured it as a simple reverse proxy passing traffic to my application (a ruby app). Sometimes the response is 502 Bad Gateway, but refreshing the page the app is correctly served. It seems this happens with all new users. As far as I understood here, this is due to nginx not able to resolve the host inside the docker network.

Below you can fin my logs when this happens the show exactly how nginx is not able to resolve the host:

95.232.164.161 - - [28/Nov/2020:18:57:38 +0000] "GET / HTTP/2.0" 502 150 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0"

==> /var/log/error.log <==
2020/11/28 18:57:38 [error] 987273#987273: *221 decidim could not be resolved (3: Host not found), client: 95.232.164.161, server: lombardia.amicidiazione.it, request: "GET / HTTP/2.0", host: "staging.amicidiazione.it"

Someone advised to specify the resolver in the http in order to make it resolve correctly, but is doesn't seem to work. I also tried to force an upstream binding the http-confs folder as you advised here, but I always get 502 because it says again it cannot resolve the host, but this time with the upstream name.

Do you know how this can be limited?

[enhancement] User-agent blocking per site

Hi,
Could it be possible to add a witelist per site of user-agent ? because i facing some blocking issue for exemple with wordpresscron
or okhttp who are legite request and i then i should disable the entire "user agent" blocking system (wordpress.mydomain_BLOCK_USER_AGENT=no).

It would be wonderfull if we could define some user agent exception.

thanks

Vulnerabilities scan with Trivy

0/ I ran a scan over this particular version: bunkerity/bunkerized-nginx:1.1.2 and got this:

bunkerity/bunkerized-nginx:1.1.2 (alpine 3.11.6)
================================================
Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0)
+----------+------------------+----------+-------------------+---------------+--------------------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION | TITLE |
+----------+------------------+----------+-------------------+---------------+--------------------------------+
| freetype | CVE-2020-15999 | MEDIUM | 2.10.1-r0 | 2.10.1-r1 | freetype: Heap-based buffer overflow due to integer
truncation in Load_SBit_Png
+----------+------------------+----------+-------------------+---------------+--------------------------------+

Idk if its exploitable in any ways.
Trivi Can be used with github actions and/or TravisCI, maybe it's a nice idea to integrate it or an other scanner like this to the workflow

seems fail2ban in multisite mode have a bug

Hi, first of all, thank you for the awesome project and new releases (the last one with reverse proxy multisite is cool).

But, seems fail2ban save banned ips to /etc/nginx/fail2ban-ip.conf and it not applying anywhere. If I right understand it will work if banned IP will set to /etc/nginx/ {server_name }/fail2ban-ip.conf in the site folder.

Add VTS module

Hi!

Could you add VTS module and add in the entrypoint a section to expose the metrics enabling them with a variable?

Thanks!!

docker-compose boilerplate with bunkerized stack

Hi @bunkerity ,

Hope you are all well !

Is it possible to create a demo repository with the current bunkerized docker images for a demo with Wordpress or Prestashop ?

That would be awesome for setting up real-world use cases.

I started 11 months ago a project call prestadock but my approach is not as good as yours :-)

I just added docker-sync files as extra feature.

Ps. It would be also interesting to add secured backup strategies with Percona toolkits.

Thanks for any inputs or insights about these questions.

Cheers,
X

[enhancement] Modsecurity logs are not easy to read

Hi,
I'm wondering why bunkerized-nginx modesecurity log is not verbose as usual modsecurity ?

(---H--- section is never redacted)

it's only apear when SecRuleEngine DetectionOnly is placed in modsec-confs of a site.

Bunkerized modsecurity audit log, most of the time i don't know why the request have been blocked by modesecurity

---tlWGFxtQ---A--
[29/Dec/2020:00:00:14 +0100] 160919641435.018878 82.64.132.39 0 192.168.0.150 10443
---tlWGFxtQ---B--
POST /api/v4/jobs/request HTTP/1.1
User-Agent: gitlab-runner 13.7.0 (13-7-stable; go1.13.8; linux/amd64)
X-Forwarded-Proto: https
CF-Visitor: {"scheme":"https"}
Content-Length: 592
X-Forwarded-For: 82.64.132.39
Accept: application/json
CF-RAY: 608ee5758e1eee0b-CDG
CF-IPCountry: FR
Host: gitlab.mydomain
Accept-Encoding: gzip
Connection: Keep-Alive
CDN-Loop: cloudflare
Content-Type: application/json
CF-Request-ID: 074d2dbd790000ee0bfc29b000000001
CF-Connecting-IP: 82.64.132.39

---tlWGFxtQ---C--
{"info":{"name":"gitlab-runner","version":"13.7.0","revision":"943fc252","platform":"linux","architecture":"amd64","executor":"docker","shell":"bash","features":{"variables":true,"image":true,"services":true,"artifacts":true,"cache":true,"shared":false,"upload_multiple_artifacts":true,"upload_raw_artifacts":true,"session":true,"terminal":true,"refspecs":true,"masking":true,"proxy":false,"raw_variables":true,"artifacts_exclude":true,"multi_build_steps":true,"trace_reset":true,"trace_checksum":true,"trace_size":true,"vault_secrets":true,"cancelable":true}},"token":"XXXXXXXX"}

---tlWGFxtQ---F--
HTTP/1.1 502
X-Frame-Options: DENY
X-Powered-By: 
Connection: keep-alive
Strict-Transport-Security: max-age=31536000
Content-Type: text/html
Content-Length: 150
X-AspNet-Version: 
Date: Mon, 28 Dec 2020 23:00:14 GMT
Feature-Policy: accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vibrate 'none'; vr 'none'
X-AspNetMvc-Version: 
Server: 
Server: 
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: object-src 'none'; frame-ancestors 'self'; form-action 'self'; block-all-mixed-content; sandbox allow-forms allow-same-origin allow-scripts allow-popups; base-uri 'self';
Referrer-Policy: no-referrer
Permissions-Policy: accelerometer=(), ambient-light-sensor=(), autoplay=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), speaker=(), sync-xhr=(), usb=(), vibrate=(), vr=()

---tlWGFxtQ---H--

---tlWGFxtQ---Z--

---Mn93sDoA---A--
[29/Dec/2020:00:00:36 +0100] 160919643652.345588 82.64.132.39 0 192.168.0.150 10443
---Mn93sDoA---B--
POST /api/v4/jobs/request HTTP/1.1
User-Agent: gitlab-runner 13.7.0 (13-7-stable; go1.13.8; linux/amd64)
X-Forwarded-Proto: https
CF-Visitor: {"scheme":"https"}
Content-Length: 592
X-Forwarded-For: 82.64.132.39
Accept: application/json
CF-RAY: 608ee5ffc884ee0b-CDG
CF-IPCountry: FR
Host: gitlab.mydomain
Accept-Encoding: gzip
Connection: Keep-Alive
CDN-Loop: cloudflare
Content-Type: application/json
CF-Request-ID: 074d2e13dc0000ee0b199ef000000001
CF-Connecting-IP: 82.64.132.39

---Mn93sDoA---C--
{"info":{"name":"gitlab-runner","version":"13.7.0","revision":"943fc252","platform":"linux","architecture":"amd64","executor":"docker","shell":"bash","features":{"variables":true,"image":true,"services":true,"artifacts":true,"cache":true,"shared":false,"upload_multiple_artifacts":true,"upload_raw_artifacts":true,"session":true,"terminal":true,"refspecs":true,"masking":true,"proxy":false,"raw_variables":true,"artifacts_exclude":true,"multi_build_steps":true,"trace_reset":true,"trace_checksum":true,"trace_size":true,"vault_secrets":true,"cancelable":true}},"token":"XXXXXXX"}

---Mn93sDoA---F--
HTTP/1.1 502
X-Frame-Options: DENY
X-Powered-By: 
Connection: keep-alive
Strict-Transport-Security: max-age=31536000
Content-Type: text/html
Content-Length: 150
X-AspNet-Version: 
Date: Mon, 28 Dec 2020 23:00:36 GMT
Feature-Policy: accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vibrate 'none'; vr 'none'
X-AspNetMvc-Version: 
Server: 
Server: 
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: object-src 'none'; frame-ancestors 'self'; form-action 'self'; block-all-mixed-content; sandbox allow-forms allow-same-origin allow-scripts allow-popups; base-uri 'self';
Referrer-Policy: no-referrer
Permissions-Policy: accelerometer=(), ambient-light-sensor=(), autoplay=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), speaker=(), sync-xhr=(), usb=(), vibrate=(), vr=()

---Mn93sDoA---H--

---Mn93sDoA---Z--

---q7WspInc---A--
[29/Dec/2020:00:00:22 +0100] 160919642218.006842 2a01:e0a:169:7f90::d73a:9b9d 0 192.168.0.150 10443
---q7WspInc---B--
PROPFIND /remote.php/dav/files/thelittlefireman/ HTTP/1.1
CF-Visitor: {"scheme":"https"}
Content-Length: 105
X-Forwarded-For: 2a01:e0a:169:7f90::d73a:9b9d
CF-IPCountry: FR
Host: nextcloud.mydomain
Accept-Encoding: gzip
Cookie: __cfduid=XXXXXXXXX; oc_sessionPassphrase=XXXXXX; __Host-nc_sameSiteCookielax=true; __Host-nc_sameSiteCookiestrict=true; ocyau81zl2y2=XXXX
Depth: 0
X-Forwarded-Proto: https
User-Agent: Mozilla/5.0 (Linux) mirall/3.1.1-20201225.075704.75c329f4f-1.0~groovy1 (Nextcloud)
Connection: Keep-Alive
CDN-Loop: cloudflare
Authorization: Basic XXXXXXXXXXXXXX=
CF-RAY: 608ee5a9ec1c2c92-LHR
Accept: */*
Content-Type: text/xml; charset=utf-8
X-Request-ID: 3f165a19-81e1-4e3c-b14d-2a4a6ea00737
Accept-Language: fr-FR,en,*
CF-Request-ID: 074d2dde3100002c92d1186000000001
CF-Connecting-IP: 2a01:e0a:169:7f90::d73a:9b9d

---q7WspInc---C--
<?xml version="1.0" ?>
<d:propfind xmlns:d="DAV:">
  <d:prop>
    <d:getetag/>
  </d:prop>
</d:propfind>


---q7WspInc---F--
HTTP/1.1 502
X-Frame-Options: DENY
X-Powered-By: 
Connection: keep-alive
Strict-Transport-Security: max-age=31536000
Content-Type: text/html
Content-Length: 150
X-AspNet-Version: 
Date: Mon, 28 Dec 2020 23:00:39 GMT
Feature-Policy: accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vibrate 'none'; vr 'none'
X-AspNetMvc-Version: 
Server: 
Server: 
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: object-src 'none'; frame-ancestors 'self'; form-action 'self'; block-all-mixed-content; sandbox allow-forms allow-same-origin allow-scripts allow-popups; base-uri 'self';
Referrer-Policy: no-referrer
Permissions-Policy: accelerometer=(), ambient-light-sensor=(), autoplay=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), speaker=(), sync-xhr=(), usb=(), vibrate=(), vr=()

---q7WspInc---H--

---q7WspInc---Z--

---tlWGFxtQ---A--
[29/Dec/2020:00:00:22 +0100] 160919642257.459901 2a01:e0a:169:7f90::d73a:9b9d 0 192.168.0.150 10443
---tlWGFxtQ---B--
GET /ocs/v2.php/apps/notifications/api/v2/notifications?format=json HTTP/1.1
If-None-Match: d751713988987e9331980363e24189ce
OCS-APIREQUEST: true
CF-Visitor: {"scheme":"https"}
X-Forwarded-For: 2a01:e0a:169:7f90::d73a:9b9d
CF-IPCountry: FR
Host: nextcloud.mydomain
Accept-Encoding: gzip
Cookie: __cfduid=xxxxxxx; oc_sessionPassphrase=xxxxxxx; __Host-nc_sameSiteCookielax=true; __Host-nc_sameSiteCookiestrict=true; ocyau81zl2y2=xxxxxxx
X-Forwarded-Proto: https
User-Agent: Mozilla/5.0 (Linux) mirall/3.1.1-20201225.075704.75c329f4f-1.0~groovy1 (Nextcloud)
Connection: Keep-Alive
CDN-Loop: cloudflare
Authorization: Basic xxxxxxxx=
CF-RAY: 608ee5a9ed01ce27-LHR
Accept: */*
X-Request-ID: d8076c19-5ae1-4bf4-afcb-18c1740f9b13
Accept-Language: fr-FR,en,*
CF-Request-ID: 074d2dde300000ce2739b81000000001
CF-Connecting-IP: 2a01:e0a:169:7f90::d73a:9b9d

---tlWGFxtQ---F--
HTTP/1.1 502
X-Frame-Options: DENY
X-Powered-By: 
Connection: keep-alive
Strict-Transport-Security: max-age=31536000
Content-Type: text/html
Content-Length: 150
X-AspNet-Version: 
Date: Mon, 28 Dec 2020 23:00:39 GMT
Feature-Policy: accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vibrate 'none'; vr 'none'
X-AspNetMvc-Version: 
Server: 
Server: 
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: object-src 'none'; frame-ancestors 'self'; form-action 'self'; block-all-mixed-content; sandbox allow-forms allow-same-origin allow-scripts allow-popups; base-uri 'self';
Referrer-Policy: no-referrer
Permissions-Policy: accelerometer=(), ambient-light-sensor=(), autoplay=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), speaker=(), sync-xhr=(), usb=(), vibrate=(), vr=()

---tlWGFxtQ---H--

---tlWGFxtQ---Z--

---lTYy9qaE---A--
[29/Dec/2020:00:00:52 +0100] 160919645279.473571 2a01:e0a:169:7f90::d73a:9b9d 0 192.168.0.150 10443
---lTYy9qaE---B--
PROPFIND /remote.php/dav/files/thelittlefireman/ HTTP/1.1
CF-Visitor: {"scheme":"https"}
Content-Length: 105
X-Forwarded-For: 2a01:e0a:169:7f90::d73a:9b9d
CF-IPCountry: FR
Host: nextcloud.mydomain
Accept-Encoding: gzip
Cookie: __cfduid=xxxxxxx; oc_sessionPassphrase=xxxxxx; __Host-nc_sameSiteCookielax=true; __Host-nc_sameSiteCookiestrict=true; ocyau81zl2y2=xxxxxxx; cf_ob_info=502:xxxx:LHR; cf_use_ob=443
Depth: 0
X-Forwarded-Proto: https
User-Agent: Mozilla/5.0 (Linux) mirall/3.1.1-20201225.075704.75c329f4f-1.0~groovy1 (Nextcloud)
Connection: Keep-Alive
CDN-Loop: cloudflare
Authorization: Basic xxxxxxxx=
CF-RAY: 608ee6657dfdce27-LHR
Accept: */*
Content-Type: text/xml; charset=utf-8
X-Request-ID: b7fdc335-f1f0-4ec2-aabf-1c37f4acfd91
Accept-Language: fr-FR,en,*
CF-Request-ID: 074d2e53670000ce27659a8000000001
CF-Connecting-IP: 2a01:e0a:169:7f90::d73a:9b9d

---lTYy9qaE---C--
<?xml version="1.0" ?>
<d:propfind xmlns:d="DAV:">
  <d:prop>
    <d:getetag/>
  </d:prop>
</d:propfind>


---lTYy9qaE---F--
HTTP/1.1 502
X-Frame-Options: DENY
X-Powered-By: 
Connection: keep-alive
Strict-Transport-Security: max-age=31536000
Content-Type: text/html
Content-Length: 150
X-AspNet-Version: 
Date: Mon, 28 Dec 2020 23:00:52 GMT
Feature-Policy: accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vibrate 'none'; vr 'none'
X-AspNetMvc-Version: 
Server: 
Server: 
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: object-src 'none'; frame-ancestors 'self'; form-action 'self'; block-all-mixed-content; sandbox allow-forms allow-same-origin allow-scripts allow-popups; base-uri 'self';
Referrer-Policy: no-referrer
Permissions-Policy: accelerometer=(), ambient-light-sensor=(), autoplay=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), speaker=(), sync-xhr=(), usb=(), vibrate=(), vr=()

---lTYy9qaE---H--

---lTYy9qaE---Z--

---7gPFqyx8---A--
[29/Dec/2020:00:01:36 +0100] 160919649645.400873 82.64.132.39 0 192.168.0.150 10443
---7gPFqyx8---B--
POST /api/v4/jobs/request HTTP/1.1
User-Agent: gitlab-runner 13.7.0 (13-7-stable; go1.13.8; linux/amd64)
X-Forwarded-Proto: https
CF-Visitor: {"scheme":"https"}
Content-Length: 592
X-Forwarded-For: 82.64.132.39
Accept: application/json
CF-RAY: 608ee7773df8ee0b-CDG
CF-IPCountry: FR
Host: gitlab.mydomain
Accept-Encoding: gzip
Connection: Keep-Alive
CDN-Loop: cloudflare
Content-Type: application/json
CF-Request-ID: 074d2efe7f0000ee0be72d9000000001
CF-Connecting-IP: 82.64.132.39

---7gPFqyx8---C--
{"info":{"name":"gitlab-runner","version":"13.7.0","revision":"943fc252","platform":"linux","architecture":"amd64","executor":"docker","shell":"bash","features":{"variables":true,"image":true,"services":true,"artifacts":true,"cache":true,"shared":false,"upload_multiple_artifacts":true,"upload_raw_artifacts":true,"session":true,"terminal":true,"refspecs":true,"masking":true,"proxy":false,"raw_variables":true,"artifacts_exclude":true,"multi_build_steps":true,"trace_reset":true,"trace_checksum":true,"trace_size":true,"vault_secrets":true,"cancelable":true}},"token":"XXXXXX"}

---7gPFqyx8---F--
HTTP/1.1 502
X-Frame-Options: DENY
X-Powered-By: 
Connection: keep-alive
Strict-Transport-Security: max-age=31536000
Content-Type: text/html
Content-Length: 150
X-AspNet-Version: 
Date: Mon, 28 Dec 2020 23:01:36 GMT
Feature-Policy: accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vibrate 'none'; vr 'none'
X-AspNetMvc-Version: 
Server: 
Server: 
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: object-src 'none'; frame-ancestors 'self'; form-action 'self'; block-all-mixed-content; sandbox allow-forms allow-same-origin allow-scripts allow-popups; base-uri 'self';
Referrer-Policy: no-referrer
Permissions-Policy: accelerometer=(), ambient-light-sensor=(), autoplay=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), speaker=(), sync-xhr=(), usb=(), vibrate=(), vr=()

---7gPFqyx8---H--

---7gPFqyx8---Z--

---BPhGQAsZ---A--
[29/Dec/2020:00:01:59 +0100] 160919651932.190637 192.168.0.254 37662 192.168.0.150 10443
---BPhGQAsZ---B--
GET /notifications/hub?access_token=XXXXXXXXX HTTP/1.1
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
Accept-Encoding: gzip, deflate, br
Cookie: experimentation_subject_id=XXXXXXXX
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Origin: chrome-extension://nngceckbapebfimnlniiiahkandclblb
Upgrade: websocket
Cache-Control: no-cache
Pragma: no-cache
Connection: Upgrade
Host: bitwarden.mydomain
Sec-WebSocket-Key: /varXXXXXXXXX
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

---BPhGQAsZ---F--
HTTP/1.1 400
Content-Security-Policy: object-src 'none'; frame-ancestors 'self'; form-action 'self'; block-all-mixed-content; sandbox allow-forms allow-same-origin allow-scripts allow-popups; base-uri 'self';
X-Frame-Options: DENY
Referrer-Policy: no-referrer
Feature-Policy: accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vibrate 'none'; vr 'none'
Date: Mon, 28 Dec 2020 23:01:59 GMT
X-XSS-Protection: 1; mode=block
Connection: keep-alive
X-Powered-By: 
X-Content-Type-Options: nosniff
Content-Type: application/json
Content-Length: 2
Server: 
Server: 
Cache-Control: no-cache, no-store, max-age=0
Strict-Transport-Security: max-age=31536000
Access-Control-Allow-Origin: chrome-extension://nngceckbapebfimnlniiiahkandclblb
X-AspNet-Version: 
X-AspNetMvc-Version: 
Permissions-Policy: accelerometer=(), ambient-light-sensor=(), autoplay=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), speaker=(), sync-xhr=(), usb=(), vibrate=(), vr=()

---BPhGQAsZ---H--

To compare a mod security instance that i plan to replace by bunkerizerd :

---oKQGPk1S---A--
[01/Dec/2020:23:09:25 +0100] 160686056552.374133 82.65.170.30 0 192.168.0.150 8443
---oKQGPk1S---B--
POST /webapi/entry.cgi HTTP/1.1
CF-Connecting-IP: 82.65.170.30
CF-Request-ID: 06c1f38491000068cafe14d000000001
Accept-Encoding: gzip
accept-language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
sec-fetch-site: same-origin
referer: https://syno.mydomain/
sec-fetch-dest: empty
CF-Visitor: {"scheme":"https"}
origin: https://syno.mydomain
x-syno-token: xxxx
accept: */*
CF-RAY: 5fb021e749bb68ca-CDG
sec-fetch-mode: cors
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36
Connection: Keep-Alive
X-Forwarded-For: 82.65.170.30
X-Forwarded-Proto: https
Content-Length: 89
cookie: XXXXXXXXX
Host: syno.mydomain
CF-IPCountry: FR
x-requested-with: XMLHttpRequest
content-type: application/x-www-form-urlencoded; charset=UTF-8
CDN-Loop: cloudflare

---oKQGPk1S---D--

---oKQGPk1S---F--
HTTP/1.1 200
Expires: 0
Vary: Accept-Encoding
Pragma: no-cache
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Strict-Transport-Security: max-age=15768000
X-XSS-Protection: 1; mode=block
X-XSS-Protection: 1; mode=block
Connection: keep-alive
Content-Encoding: gzip
Keep-Alive: timeout=60
X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
Content-Type: application/json; charset="UTF-8"
Date: Tue, 01 Dec 2020 22:09:25 GMT
Server: nginx
Referrer-Policy: same-origin

---oKQGPk1S---H--
ModSecurity: Warning. Matched "Operator `Rx' with parameter `(?i:(?:^[\W\d]+\s*?(?:(?:alter\s*(?:a(?:(?:pplication\s*rol|ggregat)e|s(?:ymmetric\s*ke|sembl)y|u(?:thorization|dit)|vailability\s*group)|c(?:r(?:yptographic\s*provider|edential)|o(?:l(?:latio|um)|nve (1040 characters omitted)' against variable `ARGS:action' (Value: `"load"' ) [file "/usr/local/owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "425"] [id "942360"] [rev ""] [msg "Detects concatenated basic SQL injection and SQLLFI attempts"] [data "Matched Data: "load found within ARGS:action: "load""] [severity "2"] [ver "OWASP_CRS/3.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-sqli"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/248/66"] [tag "PCI/6.5.2"] [hostname "192.168.0.150"] [uri "/webapi/entry.cgi"] [unique_id "160686056552.374133"] [ref "o0,5v1434,6t:urlDecodeUni"]
ModSecurity: Warning. Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `5' ) [file "/usr/local/owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "80"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [data ""] [severity "2"] [ver "OWASP_CRS/3.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "192.168.0.150"] [uri "/webapi/entry.cgi"] [unique_id "160686056552.374133"] [ref ""]

---oKQGPk1S---I--

---oKQGPk1S---J--

---oKQGPk1S---Z--

---VkGO3oYF---A--
[01/Dec/2020:23:09:30 +0100] 160686057044.553456 82.65.170.30 0 192.168.0.150 8443
---VkGO3oYF---B--
POST /webapi/entry.cgi HTTP/1.1
CF-Connecting-IP: 82.65.170.30
CF-Request-ID: 06c1f3989d000068cae039f000000001
Accept-Encoding: gzip
accept-language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
sec-fetch-site: same-origin
referer: https://syno.mydomain/
sec-fetch-dest: empty
CF-Visitor: {"scheme":"https"}
origin: https://syno.mydomain
x-syno-token: xxxxxxx
accept: */*
CF-RAY: 5fb022076e1f68ca-CDG
sec-fetch-mode: cors
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36
Connection: Keep-Alive
X-Forwarded-For: 82.65.170.30
X-Forwarded-Proto: https
Content-Length: 89
cookie: xxxxxxxxx
Host: syno.mydomain
CF-IPCountry: FR
x-requested-with: XMLHttpRequest
content-type: application/x-www-form-urlencoded; charset=UTF-8
CDN-Loop: cloudflare

---VkGO3oYF---D--

---VkGO3oYF---F--
HTTP/1.1 200
Expires: 0
Vary: Accept-Encoding
Pragma: no-cache
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Strict-Transport-Security: max-age=15768000
X-XSS-Protection: 1; mode=block
X-XSS-Protection: 1; mode=block
Connection: keep-alive
Content-Encoding: gzip
Keep-Alive: timeout=60
X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
Content-Type: application/json; charset="UTF-8"
Date: Tue, 01 Dec 2020 22:09:30 GMT
Server: nginx
Referrer-Policy: same-origin

---VkGO3oYF---H--
ModSecurity: Warning. Matched "Operator `Rx' with parameter `(?i:(?:^[\W\d]+\s*?(?:(?:alter\s*(?:a(?:(?:pplication\s*rol|ggregat)e|s(?:ymmetric\s*ke|sembl)y|u(?:thorization|dit)|vailability\s*group)|c(?:r(?:yptographic\s*provider|edential)|o(?:l(?:latio|um)|nve (1040 characters omitted)' against variable `ARGS:action' (Value: `"load"' ) [file "/usr/local/owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "425"] [id "942360"] [rev ""] [msg "Detects concatenated basic SQL injection and SQLLFI attempts"] [data "Matched Data: "load found within ARGS:action: "load""] [severity "2"] [ver "OWASP_CRS/3.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-sqli"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/248/66"] [tag "PCI/6.5.2"] [hostname "192.168.0.150"] [uri "/webapi/entry.cgi"] [unique_id "160686057044.553456"] [ref "o0,5v1434,6t:urlDecodeUni"]
ModSecurity: Warning. Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `5' ) [file "/usr/local/owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "80"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [data ""] [severity "2"] [ver "OWASP_CRS/3.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "192.168.0.150"] [uri "/webapi/entry.cgi"] [unique_id "160686057044.553456"] [ref ""]

Add modsecurity detect only capability

Hi,
Will we are testing a new config we should be able to configure mod security engine in SecRuleEngine DetectionOnly mod
to not be ban directly by fail2ban due to many false positive.

Thanks for all :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.