Trace: nginx

Nginx

This is an old revision of the document!


Nginx

Usage with acme.sh

1. You need to create a blank site.

server {
    server_tokens off;
    listen 80;
    listen [::]:80;
    server_name example.com;
    
    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        root /var/www/acme-challenge/;
    }
}

Don't forget to link and restart nginx.

2. Install acme.sh to get a cert.

curl  https://get.acme.sh | sh

3. Get a cert.

acme.sh --issue -d example.com -w /var/www/acme-challenge/

Note: if you plan to use wildcard, then do this:

acme.sh --issue -d example.com -d '*.example.com' --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
acme.sh --renew -d example.com -d '*.example.com' --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please

4. Copy the cert to nginx folder.

acme.sh --install-cert -d example.com \
--key-file       /etc/nginx/ssl/example.com.key  \
--fullchain-file /etc/nginx/ssl/example.com.crt \
--reloadcmd     "service nginx force-reload"

5. Rewrite the site's config file.

Here is an example secure conf.

example.com
server {
    server_tokens off;
    listen 80;
    listen [::]:80;
    server_name example.com;
    
    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        root /var/www/acme-challenge/;
    }

    return 301 https://$host$request_uri;
}
server {
    server_tokens off;
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;
    
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://ssl.google-analytics.com https://assets.zendesk.com https://connect.facebook.net; img-src 'self' https://ssl.google-analytics.com https://s-static.ak.facebook.com https://assets.zendesk.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://assets.zendesk.com; font-src 'self' https://themes.googleusercontent.com; frame-src https://assets.zendesk.com https://www.facebook.com https://s-static.ak.facebook.com https://tautt.zendesk.com; object-src 'none'";

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_session_tickets off;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;

    # enables server-side protection from BEAST attacks
    # http://blog.ivanristic.com/2013/09/is-beast-still-a-threat.html
    ssl_prefer_server_ciphers on;
    # disable SSLv3(enabled by default since nginx 0.8.19) since it's less secure then TLS http://en.wikipedia.org/wiki/Secure_Sockets_Layer#SSL_3.0
    # ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    # Update 2019-05-08: Uses TLSv1.3 only, this requires nginx >= 1.13.0 else use TLS1.2
    ssl_protocols TLSv1.3;
    # ciphers chosen for forward secrecy and compatibility
    # http://blog.ivanristic.com/2013/08/configuring-apache-nginx-and-openssl-for-forward-secrecy.html
    ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
    # Or this:
    # ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
    ssl_ecdh_curve secp384r1;

    # enable ocsp stapling (mechanism by which a site can convey certificate revocation information to visitors in a privacy-preserving, scalable manner)
    # http://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox/
    resolver 1.1.1.1 1.0.0.1 valid=300s;
    resolver_timeout 5s;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/nginx/ssl/example.com.crt;

    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";

    root /home/wwwroot/example.com;
    index index.php index.html;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
    }

    location ~ /\.ht {
       deny all;
    }

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

}

dhparam.pem

Diffie–Hellman key exchange (DH) is a method of securely exchanging cryptographic keys over a public channel and was one of the first public-key protocols as originally conceptualized by Ralph Merkle and named after Whitfield Diffie and Martin Hellman. DH is one of the earliest practical examples of public key exchange implemented within the field of cryptography. (Source: Wikipedia)

openssl dhparam -out dhparam.pem 4096

If your openssl or nginx still uses a lot of CPU after that, then use:

openssl dhparam -dsaparam -out dhparam.pem 4096

Things that might help you out: Cipherli.st & Mozilla SSL Configuration Generator

Cool stuff

Connectivity Detection

    # Apple CNA
    location /hotspot-detect.html {
        return 200 '<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>';
        add_header Content-Type text/html;
    }

    # Apple CNA
    location /library/test/success.html {
        return 200 '<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>';
        add_header Content-Type text/html;
    }

    # ChromeOS
    location /generate_204 {
        return 204;
    }

    # Windows connectivity detection (http://blog.superuser.com/2011/05/16/windows-7-network-awareness/)
    location /ncsi.txt {
        return 200 'Microsoft NCSI';
    }

Reverse Proxy

    location / {
        proxy_pass http://127.0.0.1:8080/;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        client_max_body_size 0;
    }

log

    log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/example_com_access.log;
    error_log /var/log/nginx/example_com_error.log warn;

Ban direct access

1. Just modify default

default
server {
   listen 80 default_server;
   listen [::]:80 default_server;

   server_name _;

   return 304;
}

server {
    listen 443 default_server;
    listen [::]:443 default_server;
    server_name _;
    ssl on;
    ssl_certificate /etc/nginx/ssl/null/null.crt;
    ssl_certificate_key /etc/nginx/ssl/null/null.key;
    return 304;
}

2. Generate a self-signed certificate

openssl req -x509 -nodes -days 7305 -newkey rsa:2048 -keyout /etc/nginx/ssl/null/null.key -out /etc/nginx/ssl/null/null.crt