├── CONTRIBUTING.md ├── CONTRIBUTING_fr.md ├── LICENSE ├── README.md ├── nginx.conf └── nginx.conf-debian-extras /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | #Contributing 2 | 3 | ##General Guidelines 4 | Test your patches first. 5 | 6 | As a general rule, if you're replacing lines of code with new lines of code, don't comment them out, just delete them EXCEPT for breaking change. 7 | 8 | 9 | ###Compatibility 10 | The code in the nginx.conf file must work for: 11 | 12 | * Latest NGINX mainline release built against OpenSSL 1.1.0 (or latest OpenSSL stable). 13 | 14 | This is necessary to have latest security and performance improvements like: 15 | 16 | * HTTP2 with ALPN 17 | * Threads AIO 18 | * CHACHA20_POLY1305 19 | * x25519 support 20 | * Multiple ssl_ecdh_curve support 21 | * Dual certificate support for RSA/ECDSA combo 22 | * And much more ... 23 | 24 | 25 | ##Security Goals 26 | 27 | At least, we need the following results on some major test tools available online: 28 | 29 | * **A** on https://securityheaders.io/ 30 | * **A+** on https://tls.imirhil.fr/ 31 | * **A+** on https://www.ssllabs.com/ 32 | 33 | ##Pull requests 34 | Anyone can commit here. 35 | 36 | Just think than your configuration must me compatible with the largest range of apps possible. 37 | -------------------------------------------------------------------------------- /CONTRIBUTING_fr.md: -------------------------------------------------------------------------------- 1 | #contribuer 2 | 3 | ##Directives 4 | Testez vos configurations avant un commit. 5 | 6 | En règle générale, si vous remplacez des lignes, supprimez-les au lieu de les commenter SAUF pour les changements qui cassent la rétrocompatibilité. 7 | 8 | ###Compatibilité 9 | Le fichier de configuration nginx.conf doit fonctionner pour : 10 | 11 | * La dernière mainline de NGINX et OpenSSL 1.1.0 (ou la dernière version stable de OpenSSL). 12 | 13 | C'est nécessaire pour avoir les derniers ajouts en termes de sécurité et de performance comme : 14 | 15 | * HTTP2 with ALPN 16 | * Threads AIO 17 | * CHACHA20_POLY1305 18 | * x25519 support 19 | * Multiple ssl_ecdh_curve support 20 | * Dual certificate support for RSA/ECDSA combo 21 | * And much more ... 22 | 23 | 24 | ##Objectifs au niveau de la sécurité 25 | 26 | Il est nécessaire d'avoir au minimum les résultats suivants sur différents tests en ligne : 27 | 28 | * **A** on https://securityheaders.io/ 29 | * **A+** on https://tls.imirhil.fr/ 30 | * **A+** on https://www.ssllabs.com/ 31 | 32 | ##Pull requests 33 | Tout le monde peut participer. 34 | 35 | Vous devez simplement essayer de trouver le meilleur compromis entre sécurité, performance et compatibilité. 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Nicolas Simond 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Secure Configuration for NGINX 2 | 3 | The goal of this project is to provide the most secure and supported nginx.conf file with support for very latest improvements like: 4 | 5 | * HTTP2 with ALPN 6 | * Threads AIO 7 | * CHACHA20_POLY1305 8 | * x25519 support 9 | * TLS 1.3 support 10 | * Multiple ssl_ecdh_curve support 11 | * 0-RTT support for TLS 1.3 12 | * Crowdsec NGINX bouncer (Don't forget to uncomment the line at the beginning for LUA support) 13 | * And much more ... 14 | 15 | Results : 16 | 17 | * A+ on SSL Labs 18 | * A on Security Headers (.io) 19 | 20 | If you want to use a NGINX release that support every of this, you need to use the package **nginx-extras** on Debian 11 that support every feature listed here. 21 | 22 | -------- 23 | 24 | > :warning: **If you were using custom Nginx and want to go back to nginx-extras package**: Like this one: https://github.com/stylersnico/nginx-openssl-chacha-naxsi 25 | ```bash 26 | #stop nginx 27 | systemctl stop nginx 28 | 29 | #clean old stuff 30 | rm -rf /usr/local/etc/nginx/ 31 | rm /usr/sbin/nginx 32 | rm /etc/nginx/naxsi_core.rules 33 | rm /etc/init.d/nginx && rm /etc/init.d/nginx-debug 34 | rm /lib/systemd/system/nginx.service 35 | 36 | #Install Nginx-extras and overwrite all configs 37 | apt -o Dpkg::Options::="--force-confnew" install nginx-extras -y 38 | 39 | #Grab latest nginx.conf file and restart 40 | cd /etc/nginx/ 41 | rm nginx.conf && wget https://raw.githubusercontent.com/stylersnico/nginx-secure-config/master/nginx.conf 42 | systemctl restart nginx 43 | ``` 44 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | #This config is made for user with the basic "nginx-extras" package available on Debian Buster 2 | 3 | #Uncomment these two lines for Crowdsec support (tested on Debian 11 - NGINX Extras) 4 | #load_module modules/ndk_http_module.so; 5 | #load_module modules/ngx_http_lua_module.so; 6 | 7 | 8 | user www-data; 9 | worker_processes auto; 10 | worker_cpu_affinity auto; 11 | pid /run/nginx.pid; 12 | 13 | load_module modules/ngx_http_headers_more_filter_module.so; 14 | 15 | events { 16 | worker_connections 16384; 17 | multi_accept on; 18 | use epoll; 19 | } 20 | 21 | # worker_rlimit_nofile = (worker_connections * 1) + 500 22 | # worker_rlimit_nofile = (worker_connections * 2) + 500 if you use nginx as reverse proxy 23 | 24 | worker_rlimit_nofile 16884; 25 | 26 | 27 | http { 28 | ## 29 | # Basic Settings 30 | ## 31 | 32 | server_names_hash_bucket_size 64; 33 | # server_name_in_redirect off; 34 | 35 | include /etc/nginx/mime.types; 36 | default_type application/octet-stream; 37 | 38 | ##VirtualHosts and configs includes 39 | include /etc/nginx/conf.d/*.conf; 40 | include /etc/nginx/sites-enabled/*; 41 | 42 | ## 43 | # TLS 44 | ## 45 | 46 | ssl_protocols TLSv1.2 TLSv1.3; 47 | ssl_ecdh_curve X25519:sect571r1:secp521r1:secp384r1; 48 | ssl_session_timeout 1d; 49 | ssl_session_cache shared:SSL:50m; 50 | ssl_session_tickets off; 51 | ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:!AES128'; 52 | ssl_prefer_server_ciphers off; 53 | 54 | 55 | ## 56 | # Headers 57 | # 58 | ##Less Verbose for Nginx headers 59 | server_tokens off; 60 | 61 | ##Common headers for security 62 | ## You need to adapt the configuration to your website need, It may break some shitty content management system or poorly build websites. 63 | more_set_headers "Content-Security-Policy : default-src https: data: 'unsafe-inline' 'unsafe-eval' always"; 64 | more_set_headers "Permissions-Policy: geolocation=();midi=();notifications=();push=();sync-xhr=();microphone=();camera=();magnetometer=();gyroscope=();speaker self;vibrate=();fullscreen self;payment=();;" 65 | more_set_headers "Strict-Transport-Security : max-age=15768000; includeSubDomains; preload"; 66 | more_set_headers "X-Frame-Options : SAMEORIGIN"; 67 | more_set_headers "X-Xss-Protection : 1; mode=block"; 68 | more_set_headers "X-Content-Type-Options : nosniff"; 69 | more_set_headers "Referrer-Policy : strict-origin-when-cross-origin"; 70 | more_set_headers "Server : Follow the white rabbit."; 71 | more_set_headers "Cross-Origin-Opener-Policy : same-origin" 72 | more_set_headers "Cross-Origin-Embedder-Policy : unsafe-none" 73 | more_set_headers "Origin-Agent-Cluster : ?1" 74 | more_set_headers "Permissions-Policy : accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), clipboard-read=(), clipboard-write=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), speaker-selection=(), sync-xhr=(), usb=(), xr-spatial-tracking=()"; 75 | 76 | ##OCSP settings 77 | ssl_stapling on; 78 | ssl_stapling_verify on; 79 | #ssl_trusted_certificate /etc/ssl/private/ocsp-certs.pem; # <- Add signing certs here 80 | resolver 1.0.0.1 8.8.4.4 valid=300s; 81 | resolver_timeout 5s; 82 | 83 | ## 84 | # Logging 85 | ## 86 | 87 | #access_log /var/log/nginx/access.log; #Disabled for performance 88 | 89 | access_log off; 90 | error_log /var/log/nginx/error.log; 91 | 92 | ## 93 | # Gzip 94 | ## 95 | 96 | gzip on; 97 | gzip_disable "msie6"; 98 | gzip_vary on; 99 | gzip_proxied any; 100 | gzip_comp_level 6; 101 | gzip_buffers 16 8k; 102 | gzip_http_version 1.1; 103 | gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; 104 | 105 | 106 | ## 107 | # GeoIP 108 | ## 109 | 110 | #GeoIP (optional) 111 | #geoip_country /usr/local/share/GeoIP/GeoIP.dat; 112 | #geoip_city /usr/local/share/GeoIP/GeoLiteCity.dat; 113 | 114 | 115 | ## 116 | # Performance and Cache 117 | ## 118 | 119 | #See - https://www.nginx.com/blog/thread-pools-boost-performance-9x/ 120 | aio threads; 121 | 122 | #Enable 0-RTT support for TLS 1.3 123 | ssl_early_data on; 124 | proxy_set_header Early-Data $ssl_early_data; 125 | 126 | #Simple DOS mitigation 127 | ##Max c/s by ip 128 | limit_conn_zone $binary_remote_addr zone=limit_per_ip:10m; 129 | limit_conn limit_per_ip 40; 130 | 131 | ##Max rq/s by ip 132 | limit_req_zone $binary_remote_addr zone=allips:10m rate=400r/s; 133 | limit_req zone=allips burst=400 nodelay; 134 | 135 | #PHP 136 | fastcgi_buffers 256 32k; 137 | fastcgi_buffer_size 256k; 138 | fastcgi_connect_timeout 4s; 139 | fastcgi_send_timeout 120s; 140 | fastcgi_read_timeout 120s; 141 | fastcgi_busy_buffers_size 512k; 142 | fastcgi_temp_file_write_size 512K; 143 | reset_timedout_connection on; 144 | 145 | #Others 146 | open_file_cache max=2000 inactive=20s; 147 | open_file_cache_valid 60s; 148 | open_file_cache_min_uses 5; 149 | open_file_cache_errors off; 150 | 151 | client_max_body_size 50M; 152 | client_body_buffer_size 1m; 153 | client_body_timeout 15; 154 | client_header_timeout 15; 155 | keepalive_timeout 65; 156 | send_timeout 15; 157 | sendfile on; 158 | tcp_nopush on; 159 | tcp_nodelay on; 160 | } 161 | -------------------------------------------------------------------------------- /nginx.conf-debian-extras: -------------------------------------------------------------------------------- 1 | #This config is made for user with the basic "nginx-extras" package available on Debian Buster 2 | 3 | #Uncomment these two lines for Crowdsec support (tested on Debian 11 - NGINX Extras) 4 | #load_module modules/ndk_http_module.so; 5 | #load_module modules/ngx_http_lua_module.so; 6 | 7 | 8 | user www-data; 9 | worker_processes auto; 10 | worker_cpu_affinity auto; 11 | pid /run/nginx.pid; 12 | 13 | load_module modules/ngx_http_headers_more_filter_module.so; 14 | 15 | events { 16 | worker_connections 16384; 17 | multi_accept on; 18 | use epoll; 19 | } 20 | 21 | # worker_rlimit_nofile = (worker_connections * 1) + 500 22 | # worker_rlimit_nofile = (worker_connections * 2) + 500 if you use nginx as reverse proxy 23 | 24 | worker_rlimit_nofile 16884; 25 | 26 | 27 | http { 28 | ## 29 | # Basic Settings 30 | ## 31 | 32 | server_names_hash_bucket_size 64; 33 | # server_name_in_redirect off; 34 | 35 | include /etc/nginx/mime.types; 36 | default_type application/octet-stream; 37 | 38 | ##VirtualHosts and configs includes 39 | include /etc/nginx/conf.d/*.conf; 40 | include /etc/nginx/sites-enabled/*; 41 | 42 | ## 43 | # TLS 44 | ## 45 | 46 | ssl_protocols TLSv1.2 TLSv1.3; 47 | ssl_ecdh_curve X25519:sect571r1:secp521r1:secp384r1; 48 | ssl_session_timeout 1d; 49 | ssl_session_cache shared:SSL:50m; 50 | ssl_session_tickets off; 51 | ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:!AES128'; 52 | ssl_prefer_server_ciphers off; 53 | 54 | 55 | ## 56 | # Headers 57 | # 58 | ##Less Verbose for Nginx headers 59 | server_tokens off; 60 | 61 | ##Common headers for security 62 | ## You need to adapt the configuration to your website need, It may break some shitty content management system or poorly build websites. 63 | more_set_headers "Content-Security-Policy : default-src https: data: 'unsafe-inline' 'unsafe-eval' always"; 64 | more_set_headers "Permissions-Policy: geolocation=();midi=();notifications=();push=();sync-xhr=();microphone=();camera=();magnetometer=();gyroscope=();speaker self;vibrate=();fullscreen self;payment=();;" 65 | more_set_headers "Strict-Transport-Security : max-age=15768000; includeSubDomains; preload"; 66 | more_set_headers "X-Frame-Options : SAMEORIGIN"; 67 | more_set_headers "X-Xss-Protection : 1; mode=block"; 68 | more_set_headers "X-Content-Type-Options : nosniff"; 69 | more_set_headers "Referrer-Policy : strict-origin-when-cross-origin"; 70 | more_set_headers "Server : Follow the white rabbit."; 71 | more_set_headers "Cross-Origin-Opener-Policy : same-origin" 72 | more_set_headers "Cross-Origin-Embedder-Policy : unsafe-none" 73 | more_set_headers "Origin-Agent-Cluster : ?1" 74 | more_set_headers "Permissions-Policy : accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), clipboard-read=(), clipboard-write=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), speaker-selection=(), sync-xhr=(), usb=(), xr-spatial-tracking=()"; 75 | 76 | ##OCSP settings 77 | ssl_stapling on; 78 | ssl_stapling_verify on; 79 | #ssl_trusted_certificate /etc/ssl/private/ocsp-certs.pem; # <- Add signing certs here 80 | resolver 1.0.0.1 8.8.4.4 valid=300s; 81 | resolver_timeout 5s; 82 | 83 | ## 84 | # Logging 85 | ## 86 | 87 | #access_log /var/log/nginx/access.log; #Disabled for performance 88 | 89 | access_log off; 90 | error_log /var/log/nginx/error.log; 91 | 92 | ## 93 | # Gzip 94 | ## 95 | 96 | gzip on; 97 | gzip_disable "msie6"; 98 | gzip_vary on; 99 | gzip_proxied any; 100 | gzip_comp_level 6; 101 | gzip_buffers 16 8k; 102 | gzip_http_version 1.1; 103 | gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; 104 | 105 | 106 | ## 107 | # GeoIP 108 | ## 109 | 110 | #GeoIP (optional) 111 | #geoip_country /usr/local/share/GeoIP/GeoIP.dat; 112 | #geoip_city /usr/local/share/GeoIP/GeoLiteCity.dat; 113 | 114 | 115 | ## 116 | # Performance and Cache 117 | ## 118 | 119 | #See - https://www.nginx.com/blog/thread-pools-boost-performance-9x/ 120 | aio threads; 121 | 122 | #Enable 0-RTT support for TLS 1.3 123 | ssl_early_data on; 124 | proxy_set_header Early-Data $ssl_early_data; 125 | 126 | #Simple DOS mitigation 127 | ##Max c/s by ip 128 | limit_conn_zone $binary_remote_addr zone=limit_per_ip:10m; 129 | limit_conn limit_per_ip 40; 130 | 131 | ##Max rq/s by ip 132 | limit_req_zone $binary_remote_addr zone=allips:10m rate=400r/s; 133 | limit_req zone=allips burst=400 nodelay; 134 | 135 | #PHP 136 | fastcgi_buffers 256 32k; 137 | fastcgi_buffer_size 256k; 138 | fastcgi_connect_timeout 4s; 139 | fastcgi_send_timeout 120s; 140 | fastcgi_read_timeout 120s; 141 | fastcgi_busy_buffers_size 512k; 142 | fastcgi_temp_file_write_size 512K; 143 | reset_timedout_connection on; 144 | 145 | #Others 146 | open_file_cache max=2000 inactive=20s; 147 | open_file_cache_valid 60s; 148 | open_file_cache_min_uses 5; 149 | open_file_cache_errors off; 150 | 151 | client_max_body_size 50M; 152 | client_body_buffer_size 1m; 153 | client_body_timeout 15; 154 | client_header_timeout 15; 155 | keepalive_timeout 65; 156 | send_timeout 15; 157 | sendfile on; 158 | tcp_nopush on; 159 | tcp_nodelay on; 160 | } 161 | --------------------------------------------------------------------------------