Nginx drop invalid requests
(Commonly, configuration must be done in production.)
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}
server {
listen 443 ssl;
server_name _;
ssl on;
ssl_certificate /home/ubuntu.pem;
ssl_certificate_key /home/ubuntu.key;
return 444;
}
Common security headers
### headers ####
proxy_hide_header X-Powered-By;
add_header X-Frame-Options SAMEORIGIN;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy "strict-origin";
add_header X-XSS-Protection "1; mode=block";
add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()";
server_tokens off;
#####headers close ####
Note : use CSP carefully as it may break code in browsers
More Header type
common CORS headers
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow_Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
Block request by type
(can be used inside proxy directive and multiple times in server directive )
# Only allow these request methods, Do not accept DELETE, SEARCH and other methods
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 404;
}
Common Proxy config
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass "http://127.0.0.1:8888/";
try_files $uri $uri/ =404;
}
or
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Referrer-Policy strict-origin;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass "http://127.0.0.1:8888/";
try_files $uri $uri/ =404;
}
or
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_pass "http://127.0.0.1:8888/";
try_files $uri $uri/ =404;
}
WebSocket proxy
location / {
proxy_pass http://wsbackend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
Turn OFF server tokens
server_tokens off;
add above in server directive or directly include in nginx.conf
Set Expiry for objects
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
Denying request and turning off logs
location = /robots.txt {
deny all;
access_log off;
}
SSL headers
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
php hosting
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Redirection by host
if ($host = www.example.com) {
return 301 https://$host$request_uri;
}
if ($host = example.com) {
return 301 https://$host$request_uri;
}
Match and alias a folder
location /static/ {
alias /var/www/example/examplecore/static/;
}
logging and client upload size
client_max_body_size 250m;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
Nginx timeouts
client_header_timeout 10s;
client_body_timeout 10s;
send_timeout 10s;
keepalive_timeout 60s;
proxy_read_timeout 120s;
proxy_connect_timeout 10s;
As Load balancer
http {
upstream backend {
server backend1.example.com:80;
server backend2.example.com:80;
server backend3.example.com:80;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
Nginx cache
add the below lines in nginx.conf
proxy_cache_path /data/nginx/cache keys_zone=mycache:200m;
Add the below to the server block
server{
## other configs
proxy_cache mycache;
add_header X-Proxy-Cache $upstream_cache_status;
}
Nginx Status
location = /nginx_status {
stub_status on;
#allow 192.168.10.0/24;
allow 172.16.0.0/24;
allow 127.0.0.1;
deny all;
# auth_basic "No Welcome X";
# auth_basic_user_file /etc/nginx/.htpasswd;# can also add auth
}
Match multiple paths
location ~* ^/(path1|path2|path3|path4|path5|path6)/ {
try_files $uri /$1/index.php?$query_string; ###other blocks
}
Adding multiple redirections
include conf.d/redirect/url_redirects;
add redirects as below block
if ($request_uri = /ind/mint ) {return 301 https://example.co ; }
if ($request_uri = /ind/mint2 ) {return 301 https://example.co/mint ; }
Optional headers
resolver 8.8.8.8 8.8.4.4;
ssl_stapling on;
ssl_stapling_verify on;
There are many configs. you can take a look at nginx official docs.