Nginx Snippets Tricks and Hacks

This is possible my first and last post written in English.

Right now, I am writing WAF, it is simple security tool right now based on Nginx and Lua (OpenResty) and I hoping it will solve some of my problems with bots.

I use it for years and backstory about our relation will be written later but I really love it.

This snippets are results of my jurney with writing WAF, using it for years on different applications and stuff like that. You can consider this for cheatsheet. Titles of this snippets will be retarded but there are because of SEO.

BEFORE ANYTHING RTFM

There are simple, well explained, you can find them here with more details of what does what.

Install nginx

Nginx have few different versions. Nginx CE, Nginx Plus (very nice thing but expensive), OpenRest (pre-build nginx with Lua support) and few more not worth mentioning. Before anything I hope that you have Debian based distro, you can search different kind od packages using apt search nginx but I advice you using something like:

apt update
apt install nginx-full nginx-extras

Turn off nginx version in header and error pages

in http block inside /etc/nginx/nginx.conf put

server_tokens off;

Before:

$ curl -I localhost
HTTP/1.1 200 OK
Server: nginx/1.23.3
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 13 Dec 2022 15:53:53 GMT
Connection: keep-alive
ETag: "6398a011-267"
Accept-Ranges: bytes

After

$ curl -I localhost
HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 13 Dec 2022 15:53:53 GMT
Connection: keep-alive
ETag: "6398a011-267"
Accept-Ranges: bytes

Remove nginx server header from requests

You need nginx-extras package. Put this in http block

more_clear_headers Server;
server_tokens off;

Change nginx server header

You need nginx-extras package.

server_tokens off;
more_set_headers 'Server: Comodore 64';

Return test/content directly from nginx

Great for debugging, you do now need any HTML to test if nginx returns something as it should.

location / {
	add_header Content-Type text/plain;
	return 200 "This is most useful for debugging";
}

Simple HTTP load balancer

Be aware that if you try to start nginx and none of backends are alive, if will fail. Also note that this is HTTP load balancer.

upstream backend {

    # select algorithm
    least_conn;

    # Defint backends
    server backend1.example.com weight=2; # weight parameter loads that backend two times more eg. that server have more cpu cores
    server backend2.example.com;
    server backend3.example.com backup; # of course, use this backend only as backup
}

server {

    listen 80;
    # Here may come SSL snippet

    location / {
        proxy_pass http://backend;
    }
    

}

More complex load balancing - TCP/UDP

This is example of TCP/UDP load balancing in nginx. Most of thing is same as in basic load balancing but diffrence is that in simple http loadbalancing, nginx every time handle http connections and deal with http content but with TCP/UDP load balancing you balance any application(mysql, redis, dns), not only the ones with http protocol.

Good topics:

stream {
    upstream stream_backend {
        least_conn;
        server backend1.example.com:12345 weight=5;
        server backend2.example.com:12345 max_fails=2 fail_timeout=30s;
        server backend3.example.com:12345 max_conns=3;
    }
    
    upstream dns_servers {
        least_conn;
        server 192.168.136.130:53;
        server 192.168.136.131:53;
        server 192.168.136.132:53;
    }   
    
    server {
        listen        12345;
        proxy_pass    stream_backend;
        proxy_timeout 3s;
        proxy_connect_timeout 1s;
    }
    
    server {
        listen     53 udp;
        proxy_pass dns_servers;
    }
    
}

I stole this from somewhere, sorry author!

React, Angular or any other SPA rewrite for routes

server {
    listen              80;
    server_name         somedomain.com;
    root                /home/app/www;
    index               index.html;

    location / {
      try_files $uri $uri/ /index.html;
    }

}

Add basic HTTP authentification to website or some of the routes

First of all, unfortunately we will need one Apache package called apache2-utils so install it.

After you will need to generate file with users and passwords which acts like database.

htpasswd -c /etc/nginx/users admin

You can add unlimited number of users and also you should verify that file okay, it should look something like this:

# cat /etc/nginx/users

admin:$apr1$/woC1jnP$rjh0Ss1w5qeSMjTtn0Ejd1

After you created user, add following config to your server.conf

server {

	auth_basic           "Super secret area";
	auth_basic_user_file /etc/nginx/users; 
	
	# rest of your config
	# ...

Also, you can put it in only one route

server {

	location /admin/ {
		auth_basic           "Super secret area";
		auth_basic_user_file /etc/nginx/users;
	}
	# rest of your config
	# ...

Or you can enable it for all routes and disable only for one


location /public/ {
	auth_basic off;
}

Nice thing is that everything support HTTP basic auth so external services can access URL by using following sintax

http://user:[email protected]/sercuredroute/

Add basic browser caching


location ~* \.(?:ico|css|js|gif|jpeg|jpg|png|svg|woff|woff2|ttf)$ {
	expires 15d;
	add_header Pragma public;
	add_header Cache-Control "public";
}

To be continued!