Sign inSign up

vlche/nginx-waf

By vlche

•Updated over 4 years ago

Nginx with ModSecurity3 (preconfigured OWASP CRS), Brotli compression and SSL auto-renewal (certbot)

Image
2

100K+

vlche/nginx-waf repository overview

⁠vlche/nginx-waf

Docker alpine based container providing nginx⁠ with modsecurity3⁠, brotli⁠ compression and certbot for Let's Encrypt⁠'s SSL certificates auto-renewal. You can use it as all-in-one service, or as a SSL/Load-Balancer frontend and WAF backend/backends. Additionally preconfigured options are:

SSL/TLS⁠ Optimized intermediate ssl settings. General-purpose servers with a variety of clients, recommended for almost all systems by Mozilla. Certificates are from Lets's encrypt, generated by certbot, auto renewed by separate container, hooks are preconfigured to reload nginx-waf container

brotli⁠ Default preconfigured options for Brotli are: dynamic compression, level 6

Security Headers⁠ Preconfigured optimized http headers are included and enabled, but you should certainly know what you are doing!

lua⁠

Docker Automated build Docker Build Status GitHub issues GitHub license Docker Pulls MicroBadger Size

Launch nginx-waf using the default config:

docker run --name nginx-waf \
  --restart=always \
  --net=host \
  -e TZ=Europe/Berlin \
  -e WORKERS=5 \
  -v /data/nginx/conf.d:/etc/nginx/conf.d:rw \
  -v /data/letsencrypt:/etc/letsencrypt:rw \
  -v /data/www:/www:rw \
  -p 80:80 -p 443:443 -d \
  vlche/nginx-waf
  • Env variable CRON starts cron embedded.
  • Env variable TZ sets your timezone.
  • Env variable WAF_INSTANCE points cron notify target to WAF instance
  • Env variable WORKERS sets nginx's worker_processes to your value.

Certbot's autoupdater can be run as an embedded cron daemon or as a separate cron container. To run it embedded just set CRON variable:

docker run --name nginx-waf \
...
  -e CRON=1 \
...
  vlche/nginx-waf

or To run certbot's cron updater as a separate container set WAF_INSTANCE variable to match your nginx-waf instance:

docker run --name nginx-waf-cron \
  --restart=always \
  -e TZ=Europe/Berlin \
  -e WAF_INSTANCE=nginx-waf \
  -v /data/nginx/conf.d:/etc/nginx/conf.d:rw \
  -v /data/letsencrypt:/etc/letsencrypt:rw \
  -v /data/www:/www:rw \
  -v /run/docker.sock:/run/docker.sock \
  vlche/nginx-waf
  /cron.sh

⁠ModSecurity

Pre-configured with rules from OWASP CRS on my default. If you want to disable it for a particular location simply set it to off

upstream backend {
    server 127.0.0.1:9000;
}

server {
    listen       80;
    #listen       [::]80;
    server_name  insecure.example.com;
    #listen 443 ssl http2;
    #listen [::]:443 ssl http2;

    #ssl_certificate /etc/letsencrypt/live/insecure.example.com/fullchain.pem; # managed by Certbot
    #ssl_certificate_key /etc/letsencrypt/live/insecure.example.com/privkey.pem; # managed by Certbot
    #ssl_trusted_certificate /etc/letsencrypt/live/insecure.example.com/chain.pem; # managed by Certbot
    #ssl_stapling on; # managed by Certbot
    #ssl_stapling_verify on; # managed by Certbot

    #access_log  /var/log/nginx/host.access.log  main;

    # modsec has already been enabled globally in 01-local.conf
    #
    #modsecurity on;
    #modsecurity_rules_file /etc/nginx/modsec/main.conf;

    # include letsencrypt endpoints to bypass proxy and be able to autoupdate:
    include snippets/letsencrypt.conf;
    # add some CSRF headers:
    include snippets/policy_headers.conf;

    location / {
        root   /usr/share/nginx/html;
    }

    # serve static files with modsecurity disabled
    #
    #location /static/ {
    #    modsecurity off;
    #    root   /usr/share/nginx/html;
    #}

    # disable SecRule # 949110 for /api/ route:
    #
    #location /api/ {
    # set proxy headers: X-Forwarded-Proto, Host, X-Forwarded-Host, X-Forwarded-For, X-Real-IP for upstreams:
    #    include snippets/proxy_headers.conf;
    #    proxy_pass $backend;
    #    modsecurity_rules "SecRuleRemoveById 949110";
    #}

    # proxy requests to remote WebSockets backends for /ws/ route:
    #
    #location /ws/ {
    # set proxy headers: X-Forwarded-Proto, Host, X-Forwarded-Host, X-Forwarded-For, X-Real-IP for upstreams,
    # enable connection upgrade:
    #    include snippets/proxy_headers_ws.conf;
    #    proxy_pass $backend;
    #}

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    # set proxy headers: X-Forwarded-Proto, Host, X-Forwarded-Host, X-Forwarded-For, X-Real-IP for upstreams:
    #    include snippets/proxy_headers.conf;
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}

}

If you have multiple server blocks, it is recommended to load ModSecurity rules file in http context, and then customize SecRules per endpoints, to ruduce memory footprint. Example of /etc/nginx/conf.d/00-local.conf:

# modsec is enabled for every server context.
# If you want to enable it on a per server basis, please disable it here!
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;

# you should use reachable resolver for ssl stapling
# this one is generated from /etc/resolv.conf's first nameserver
include snippets/resolver.conf;
# this one is whatever you say
#resolver 8.8.8.8;

include snippets/log.conf;
include snippets/ssl.conf;
include snippets/brotli.conf;
# increased for nextcloud like apps
client_max_body_size        512m;

# define indexes here to reduce per vhost complexity
index  index.html index.htm;

# map to proxify WebSockets
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

⁠Certbot

Easily add SSL security to your nginx hosts with certbot. docker exec -it nginx-waf /bin/sh will bring up a prompt at which time you can certbot to your hearts content.

or

docker exec -it nginx-waf certbot --no-redirect --must-staple -d example.com

It even auto-renew's for you every day!

Tag summary

Content type

Image

Digest

Size

34.1 MB

Last updated

over 4 years ago

docker pull vlche/nginx-waf