GitHub - trimstray/nginx-quick-reference: This notes describes how to improve Ng...
source link: https://github.com/trimstray/nginx-quick-reference
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
README.md
Nginx Quick Reference
My notes about Nginx...
Table of Contents
- Introduction
- External Resources
- Helpers
- Base rules
- Performance
- Hardening
- Run as an unprivileged user
- Disable unnecessary modules
- Protect sensitive resources
- Hide Nginx version number
- Hide Nginx server signature
- Hide upstream proxy headers
- Use only 4096-bit private keys
- Keep only TLS 1.2 (+ TLS 1.3)
- Use only strong ciphers
- Use more secure ECDH Curve
- Use strong Key Exchange
- Defend against the BEAST attack
- Disable compression (mitigation of CRIME attack)
- HTTP Strict Transport Security
- Reduce XSS risks (Content-Security-Policy)
- Control the behavior of the Referer header (Referrer-Policy)
- Provide clickjacking protection (X-Frame-Options)
- Prevent some categories of XSS attacks (X-XSS-Protection)
- Prevent Sniff Mimetype middleware (X-Content-Type-Options)
- Deny the use of browser features (Feature-Policy)
- Reject unsafe HTTP methods
- Control Buffer Overflow attacks
- Mitigating Slow HTTP DoS attack (Closing Slow Connections)
Introduction
Before using the Nginx please read Beginner’s Guide.
Nginx (/ˌɛndʒɪnˈɛks/ EN-jin-EKS) is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev. For a long time, it has been running on many heavily loaded Russian sites including Yandex, Mail.Ru, VK, and Rambler.
To increase your knowledge, read Nginx Documentation.
General disclaimer
This is not an official handbook. Many of these rules refer to another resources. It is rather a quick collection of some rules used by me in production environments (not only).
The most important thing:
Do not follow guides just to get 100% of something. Think about what you actually do at your server!
And remember:
These guidelines provides recommendations for very restrictive setup.
SSL Report: blkcipher.info
Many of these recipes have been applied to the configuration of my private website. I finally got all 100%'s on my scores:
Printable high-res hardening checklist
Simple hardening checklist based on this recipes (@ssllabs A+ 100%) - High-Res 5000x7500:
For
*.xcf
and
External Resources
About Nginx
▪️Nginx Project
▪️Nginx official read-only mirror
References
▪️Nginx boilerplate configs
▪️Awesome Nginx configuration template
▪️A collection of resources covering Nginx and more
▪️Nginx Secure Web Server
▪️Emiller’s Guide To Nginx Module Development
Cheatsheets
▪️Nginx Cheatsheet
▪️Nginx Quick Reference
▪️Nginx Cheatsheet by Mijdert Stuij
Performance & Hardening
▪️SSL/TLS Deployment Best Practices
▪️SSL Server Rating Guide
▪️How to Build a Tough NGINX Server in 15 Steps
▪️Top 25 Nginx Web Server Best Security Practices
▪️Strong SSL Security on Nginx
▪️Nginx Tuning For Best Performance by Denji
▪️Enable cross-origin resource sharing (CORS)
▪️TLS has exactly one performance problem: it is not used widely enough
▪️WAF for Nginx
▪️ModSecurity for Nginx
▪️Transport Layer Protection Cheat Sheet
▪️Security/Server Side TLS
▪️SSL and TLS Deployment Best Practices
Config generators
▪️Nginx config generator on steroids.
Static analyzers
Log analyzers
▪️GoAccess
▪️Graylog
▪️Logstash
Performance analyzers
▪️ngxtop
Benchmarking tools
▪️siege
▪️wrk
▪️bombardier
▪️gobench
Online tools
▪️SSL Server Test
▪️SSL/TLS Capabilities of Your Browser
▪️Strong ciphers for Apache, Nginx, Lighttpd and more
▪️Analyse the HTTP response headers by Security Headers
▪️Analyze your website by Mozilla Observatory
▪️Online tool to learn, build, & test Regular Expressions
▪️Online Regex Tester & Debugger
Other stuff
▪️BBC Digital Media Distribution: How we improved throughput by 4x
▪️Web cache server performance benchmark: nuster vs nginx vs varnish vs squid
Helpers
Shell aliases
alias ng.test='nginx -t -c /etc/nginx/nginx.conf' alias ng.stop='ng.test && systemctl stop nginx' alias ng.reload='ng.test && systemctl reload nginx'
Base rules
? Organising Nginx configuration
RationaleWhen your configuration grow, the need for organising your code will also grow. Well organised code is:
- easier to understand
- easier to maintain
- easier to work with
ExampleUse
include
directive to attach your nginx specific code to global config, contexts and other.
# Store this configuration in https-ssl-common.conf listen 10.240.20.2:443 ssl; root /etc/nginx/error-pages/other; ssl_certificate /etc/nginx/domain.com/certs/nginx_domain.com_bundle.crt; ssl_certificate_key /etc/nginx/domain.com/certs/domain.com.key; # And include this file in server section: server { include /etc/nginx/domain.com/commons/https-ssl-common.conf; server_name domain.com www.domain.com; ...
? Separate listen directives for 80 and 443
Rationale...
Example# For http: server { listen 10.240.20.2:80; ... } # For https: server { listen 10.240.20.2:443 ssl; ... }
? Use default_server
directive at the beginning
Rationale
ExampleNginx should prevent processing requests with undefined server names - also traffic on ip address. It also protects against configuration errors and providing incorrect backends.
server { listen 10.240.20.2:443 ssl; # Place it at the beginning of the configuration file. server_name default_server; location / { # serve static file (error page): root /etc/nginx/error-pages/404; # or redirect: # return 301 https://badssl.com; } } server { listen 10.240.20.2:443 ssl; server_name domain.com; ... } server { listen 10.240.20.2:443 ssl; server_name app.domain.com; ... }
? Force all connections over TLS
RationaleExampleYou should always use HTTPS instead of HTTP to protect your website, even if it doesn’t handle sensitive communications.
server { listen 10.240.20.2:80; server_name domain.com; return 301 https://$host$request_uri; } server { listen 10.240.20.2:443 ssl; server_name domain.com; ... }
? Use geo/map modules instead allow/deny
RationaleExampleCreates variables with values depending on the client IP address. Use map or geo modules (one of them) to prevent users abusing your servers.
# Map module: map $remote_addr $globals_internal_map_acl { # Status code: # - 0 = false # - 1 = true default 0; ### INTERNAL ### 10.255.10.0/24 1; 10.255.20.0/24 1; 10.255.30.0/24 1; 192.168.0.0/16 1; } # Geo module: geo $globals_internal_geo_acl { # Status code: # - 0 = false # - 1 = true default 0; ### INTERNAL ### 10.255.10.0/24 1; 10.255.20.0/24 1; 10.255.30.0/24 1; 192.168.0.0/16 1; }
? Map all the things...
RationaleExampleMap module provides a more elegant solution for clearly parsing a big list of regexes, e.g. User-Agents. Manage a large number of redirects with Nginx maps.
map $http_user_agent $device_redirect { default "desktop"; ~(?i)ip(hone|od) "mobile"; ~(?i)android.*(mobile|mini) "mobile"; ~Mobile.+Firefox "mobile"; ~^HTC "mobile"; ~Fennec "mobile"; ~IEMobile "mobile"; ~BB10 "mobile"; ~SymbianOS.*AppleWebKit "mobile"; ~Opera\sMobi "mobile"; } if ($device_redirect = "mobile") { return 301 https://m.domain.com$request_uri; }
? Drop the same root inside location block
RationaleExampleIf you add a root to every location block then a location block that isn’t matched will have no root. Set global
root
inside server directive.
server { server_name domain.com; root /var/www/domain.com/public; location / { ... } location /api { ... } location /static { root /var/www/domain.com/static; ... } }
? Use debug mode for debugging
RationaleExampleThere's probably more detail than you want, but that can sometimes be a lifesaver (but log file growing rapidly).
rewrite_log on; error_log /var/log/nginx/error-debug.log debug;
Performance
? Set manually worker processes
RationaleThe
worker_processes
directive is the sturdy spine of life for Nginx. This directive is responsible for letting our virtual server know many workers to spawn once it has become bound to the proper IP and port(s).
Official Nginx documentation say: "When one is in doubt, setting it to the number of available CPU cores would be a good start (the value "auto" will try to autodetect it)."
ExampleI think for high load proxy servers (also standalone servers) the best value is ALL_CORES - 1 (please test it before used).
# VCPU = 4 , expr $(nproc --all) - 1 worker_processes 3;
? Use HTTP/2
RationaleExampleAll requests are downloaded in parallel, not in a queue, HTTP headers are compressed, pages transfer as a binary, not as a text file, which is more efficient and more.
# For https: server { listen 10.240.20.2:443 ssl http2; ...
? Maintaining SSL Sessions
RationaleThis improves performance from the clients’ perspective, because it eliminates the need for a new (and time-consuming) SSL handshake to be conducted each time a request is made.
ExampleMost servers do not purge sessions or ticket keys, thus increasing the risk that a server compromise would leak data from previous (and future) connections.
ssl_session_cache shared:SSL:10m; ssl_session_timeout 24h; ssl_session_tickets off; ssl_buffer_size 1400;
Hardening
? Run as an unprivileged user
RationaleExampleThere is no real difference in security just by changing the process owner name. On the other hand in security, the principle of least privilege states that an entity should be given no more permission than necessary to accomplish its goals within a given system. This way only master process runs as root.
# Edit nginx.conf: user www-data; # Set owner and group: chown -R www-data:www-data /var/www/domain.com
? Disable unnecessary modules
RationaleExampleIt is recommended to disable any modules which are not required as this will minimize the risk of any potential attacks by limiting the operations allowed by the web server.
# During installation: ./configure --without-http_autoindex_module # Comment modules in the configuration file: # load_module /usr/share/nginx/modules/ndk_http_module.so; # load_module /usr/share/nginx/modules/ngx_http_auth_pam_module.so;
? Protect sensitive resources
RationaleExampleHidden directories and files should never be web accessible.
if ( $request_uri ~ "/\.git" ) { return 403; } # or location ~ /\.git { deny all; } # or all . directories/files in general location ~ /\. { deny all; }
? Hide Nginx version number
RationaleExampleDisclosing the version of nginx running can be undesirable, particularly in environments sensitive to information disclosure.
server_tokens off;
? Hide Nginx server signature
RationaleExampleYou should compile Nginx from sources with
ngx_headers_more
to usedmore_set_headers
directive.
more_set_headers "Server: Unknown";
? Hide upstream proxy headers
RationaleExampleWhen nginx is used to proxy requests from an upstream server (such as a PHP-FPM instance), it can be beneficial to hide certain headers sent in the upstream response (for example, the version of PHP running).
proxy_hide_header X-Powered-By; proxy_hide_header X-AspNetMvc-Version; proxy_hide_header X-AspNet-Version; proxy_hide_header X-Drupal-Cache;
? Use only 4096-bit private keys
RationaleAdvisories recommend 2048 for now. Security experts are projecting that 2048 bits will be sufficient for commercial use until around the year 2030.
If you want to get A+ with 100%s on SSL Lab you should definitely use 4096 bit private key.
The "SSL/TLS Deployment Best Practices" book say: The cryptographic handshake, which is used to establish secure connections, is an operation whose cost is highly influenced by private key size. Using a key that is too short is insecure, but using a key that is too long will result in “too much” security and slow operation. For most web sites, using RSA keys stronger than 2048 bits and ECDSA keys stronger than 256 bits is a waste of CPU power and might impair user experience. Similarly, there is little benefit to increasing the strength of the ephemeral key exchange beyond 2048 bits for DHE and 256 bits for ECDHE.
I always generate 4096 bit keys for low busy sites since the downside is minimal (slightly lower performance) and security is slightly higher (although not as high as one would like).
ExampleUse of alternative solution: ECC Certificate Signing Request (CSR).
### Example (RSA): ( _fd="domain.com.key" ; _len="4096" ; openssl genrsa -out ${_fd} ${_len} ) # Let's Encrypt: certbot certonly -d domain.com -d www.domain.com --rsa-key-size 4096 ### Example (ECC): # _curve: prime256v1, secp521r1, secp384r1 ( _fd="domain.com.key" ; _fd_csr="domain.com.csr" ; _curve="prime256v1" ; openssl ecparam -out ${_fd} -name ${_curve} -genkey ; openssl req -new -key ${_fd} -out ${_fd_csr} -sha256 ) # Let's Encrypt (from above): certbot --csr ${_fd_csr} -[other-args]
For x25519
:
( _fd="private.key" ; _curve="x25519" ; \ openssl genpkey -algorithm ${_curve} -out ${_fd} )
ssllabs score: 100
( _fd="domain.com.key" ; _len="2048" ; openssl genrsa -out ${_fd} ${_len} ) # Let's Encrypt: certbot certonly -d domain.com -d www.domain.com
ssllabs score: 90
External resources? Keep only TLS 1.2 (+ TLS 1.3)
RationaleTLS 1.1 and 1.2 are both without security issues - but only v1.2 provides modern cryptographic algorithms. TLS 1.0 and TLS 1.1 protocols will be removed from browsers at the beginning of 2020.
ExampleIf you use TLS 1.2 or TLS 1.1/1.2 older clients will not able to load your site.
ssl_protocols TLSv1.2;
ssllabs score: 100
ssl_protocols TLSv1.2 TLSv1.1;
ssllabs score: 95
External resources- TLS/SSL Explained – Examples of a TLS Vulnerability and Attack, Final Part
- How to enable TLS 1.3 on Nginx
? Use only strong ciphers
RationaleThis parameter changes quite often, the recommended configuration for today may be out of date tomorrow. For more security use only strong and not vulnerable ciphersuite (but if you use http/2 you can get
Server sent fatal alert: handshake_failure
error).
For backward compatibility software components you should use less restrictive ciphers.
ExampleYou should definitely disable weak ciphers like those with DSS, DSA, DES/3DES, RC4, MD5, SHA1, null, anon in the name.
ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384";
ssllabs score: 100
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256";
ssllabs score: 90
External resources- SSL/TLS: How to choose your cipher suite
- HTTP/2 and ECDSA Cipher Suites
- Which SSL/TLS Protocol Versions and Cipher Suites Should I Use?
? Use more secure ECDH Curve
RationaleX25519 is a more secure but slightly less compatible option. To maximise interoperability with existing browsers and servers, stick to P-256 prime256v1 and P-384 secp384r1 curves.
If you not set
ssh_ecdh_curve
, then the Nginx will use its default settings, e.g. chrome will preferX25519
, but this is not recommended because you can not control the Nginx's default settings (seems to be P-256).
Explicitly set
ssh_ecdh_curve X25519:prime256v1:secp521r1:secp384r1;
- for me it's perfect solution because if web browser support X25519 curves -> use X25519 otherwise try the next curve listed.
ExampleDo not use the secp112r1, secp112r2, secp128r1, secp128r2, secp160k1, secp160r1, secp160r2, secp192k1 curves. They have a too small size for security application according to NIST recommendation.
ssl_ecdh_curve X25519; # Alternative (this one doesn’t affect compatibility, by the way; it’s just a question of the preferred order) ssl_ecdh_curve X25519:prime256v1:secp521r1:secp384r1;
ssllabs score: 100
External resources- SafeCurves: choosing safe curves for elliptic-curve cryptography
- Safe ECC curves for HTTPS are coming sooner than you think
- Cryptographic Key Length Recommendations
- Testing for Weak SSL/TLS Ciphers, Insufficient Transport Layer Protection (OTG-CRYPST-001)
? Use strong Key Exchange
Rationale
dhparam
is only used when using DHE ciphers. Given the ciphers listed, dhparam would not be used. Most of the "modern" profiles from places like Mozilla's ssl config generator no longer recommend using this.
ExampleDefault key size in OpenSSL is
1024 bits
- it's vulnerable and breakable. For the best security configuration use your own4096 bit
DH Group or use known safe ones pre-defined DH groups (it's recommended) from mozilla.
# Generating DH parameters: openssl dhparam -dsaparam -out /etc/nginx/ssl/dhparam_4096.pem 4096 # Nginx configuration: ssl_dhparam /etc/nginx/ssl/dhparams_4096.pem;
ssllabs score: 100
External resources- Weak Diffie-Hellman and the Logjam Attack
- Pre-defined DHE groups
- Instructs OpenSSL to produce "DSA-like" DH parameters
? Defend against the BEAST attack
RationaleExampleEnables server-side protection from BEAST attacks.
ssl_prefer_server_ciphers on;
? Disable compression (mitigation of CRIME attack)
RationaleDisabling SSL/TLS compression stops the attack very effectively.
ExampleSome attacks are possible because of gzip being enabled on SSL requests. In most cases, the best action is to simply disable gzip for SSL requests.
gzip off;
? HTTP Strict Transport Security
RationaleExampleThe header indicates for how long a browser should unconditionally refuse to take part in unsecured HTTP connection for a specific domain.
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains" always;
ssllabs score: A+
External resources? Reduce XSS risks (Content-Security-Policy)
RationaleExampleCSP reduce the risk and impact of XSS attacks in modern browsers.
# This policy allows images, scripts, AJAX, and CSS from the same origin, and does not allow any other resources to load. add_header Content-Security-Policy "default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';" always;
? Control the behavior of the Referer header (Referrer-Policy)
RationaleExampleDetermine what information is sent along with the requests.
add_header Referrer-Policy "no-referrer";
? Provide clickjacking protection (X-Frame-Options)
RationaleExampleHelps to protect your visitors against clickjacking attacks. It is recommended that you use the x-frame-options header on pages which should not be allowed to render a page in a frame.
add_header X-Frame-Options "SAMEORIGIN" always;
? Prevent some categories of XSS attacks (X-XSS-Protection)
RationaleExampleEnable the cross-site scripting (XSS) filter built into modern web browsers.
add_header X-XSS-Protection "1; mode=block" always
? Prevent Sniff Mimetype middleware (X-Content-Type-Options)
RationaleExampleIt prevents the browser from doing MIME-type sniffing (prevents "mime" based attacks).
add_header X-Content-Type-Options "nosniff" always;
? Deny the use of browser features (Feature-Policy)
RationaleExampleThis header protect your site from third parties using APIs that have security and privacy implications, and also from your own team adding outdated APIs or poorly optimized images.
add_header Feature-Policy "geolocation none; midi none; notifications none; push none; sync-xhr none; microphone none; camera none; magnetometer none; gyroscope none; speaker none; vibrate none; fullscreen self; payment none; usb none;";
? Reject unsafe HTTP methods
RationaleExampleSet of methods support by a resource. An ordinary web server supports the HEAD, GET and POST methods to retrieve static and dynamic content. Other (e.g. OPTIONS, TRACE) methods should not be supported on public web servers, as they increase the attack surface.
add_header Allow "GET, POST, HEAD" always; if ( $request_method !~ ^(GET|POST|HEAD)$ ) { return 405; }
? Control Buffer Overflow attacks
RationaleExampleBuffer overflow attacks are made possible by writing data to a buffer and exceeding that buffers’ boundary and overwriting memory fragments of a process. To prevent this in nginx we can set buffer size limitations for all clients.
client_body_buffer_size 100k; client_header_buffer_size 1k; client_max_body_size 100k; large_client_header_buffers 2 1k;
? Mitigating Slow HTTP DoS attack (Closing Slow Connections)
RationaleExampleClose connections that are writing data too infrequently, which can represent an attempt to keep connections open as long as possible.
client_body_timeout 10s; client_header_timeout 10s; keepalive_timeout 5 5; send_timeout 10;
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK