Enable HTTPS on localhost with NGINX

# Enable HTTPS on localhost with NGINX

From: [digitalocean](https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-nginx-in-ubuntu-16-04)

# 1. Create a self-signed key and certificate pair
```bash
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.cer
# Note: digitalocean use extension .crt not .cer.
```

*[req](# 'We want to use X.509 certificate signing request (CSR) management.'). [X.509](# 'Is a public key infrastructure standard. It specifies that we want to make a self-signed certificate instead of generating a certificate signing request'). [nodes](# 'Stop encrypting certificate with a passphrase. We need Nginx to be able to read the file, without user intervention'). [days](# 'Valid days before expire.'). [newkey](# 'Generate a new certificate and a new key at the same time.'). [rsa:2048](# 'To make an RSA key that is 2048 bits long.'). [keyout](# 'Path to save the private key.'). [out](# 'Path to save the certificate.').* 
Prompt: `Common Name (e.g. server FQDN or YOUR name):` 
[FQDN](# 'A Fully Qualified Domain Name has the format: [hostname].[domain].[tld] . e.g. "shop.a.com", "*.a.com", or "*.a.com/CN=a.com", or IP(LAN or WAN).').

# 2. Enable perfect forward secrecy
Create a strong Diffie-Hellman group, which is used in negotiating Perfect Forward Secrecy with clients. This may take a few minutes.
```bash
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
```
*[Perfect Forward Secrecy](# 'Protect past sessions even though long-term secret keys or passwords are compromised in the future.'). [dhparam](# '(Generation and management of) Diffie-Hellman Parameters.').*

# 3. Create a reusable configuration snippet pointing to key and cer
```bash
sudo nano /etc/nginx/snippets/self-signed.conf
```
```
# /etc/nginx/snippets/self-signed.conf
ssl_certificate /etc/ssl/certs/nginx-selfsigned.cer;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
```
# 4. Create a reusable configuration snippet with encryption settings
```bash
sudo nano /etc/nginx/snippets/ssl-params.conf
```
```
# /etc/nginx/snippets/ssl-params.conf
# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now.  You can use the commented out header line below
#  that includes the "preload" directive if you understand the implications.

#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;
```
Nginx will simply output a warning because we are using a self-signed certificate, so the SSL stapling will not be used.

# 5. Now ready to adjust the nginx configuration to use SSL
We use server block file named "default", adjust the keyword if you use another file.
```bash
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
sudo nano /etc/nginx/sites-available/default
```
```
# /etc/nginx/sites-available/default
# server 1, ignore illegal requests from server_name _ (won't match)
server {
        listen 80 deferred;
        listen [::]:80;
        server_name _;
        return 444;
}

# server 2, redirect http (80) to https (443)
server {
    listen 80;
    listen [::]:80;
    server_name server_domain_or_IP;
    return 302 https://$server_name$request_uri;

    # 302 code (temporarily redirect) for testing.
    # TODO: change to "301" if test finished and https works.
}

# server 3, our real server finally.
server {
    # SSL configuration

    listen 443 ssl http2 default_server; # default_server must be <= 1.
    listen [::]:443 ssl http2 default_server;
    server_name server_domain_or_IP;
    include snippets/self-signed.conf;
    include snippets/ssl-params.conf;

    # ... other configurations ...
```
Alternative: allow both HTTP and HTTPS traffic (not recommended if it can be avoided)
```
# server 1
server {
        listen 80 deferred;
        listen [::]:80;
        server_name _;
        return 444;
}

# Server 2 and 3 combined, serve both 80 and 443 ports, no redirect.
server {
    listen 80 default_server;
    listen 443 ssl http2 default_server;

    listen [::]:80 default_server;
    listen [::]:443 ssl http2 default_server;

    server_name server_domain_or_IP;
    include snippets/self-signed.conf;
    include snippets/ssl-params.conf;

    # ... other configurations ...
```
# 6. Adjust the firewall
Make sure [ufw](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-14-04 'is an interface to iptables that is geared towards simplifying the process of configuring a firewall, for beginners') is active by:
```bash
sudo ufw status verbose

# If not active, set it up and enable it:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw enable

# reconnected via ssh.
sudo ufw status verbose
sudo ufw allow http
sudo ufw allow https
# sudo ufw deny from 15.15.15.51 # ban someone
```
Allow the "Nginx Full" profile:
```bash
sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'
sudo ufw status
```
# 7. Apply changes in nginx
Syntax errors testing:
```bash
sudo nginx -t
```
*nginx: [warn] "ssl_stapling"* means self-signed certificate can't use SSL stapling. 
If no other errors, restart nginx:
```bash
sudo systemctl restart nginx
```

# 8. Testing
Visit `https://server_domain_or_IP`. Connection not private? You are not worth trusting. Only certificate issued by trusted authority is trusted. Of course you can trust yourself. 

Now test http redirection: `http://server_domain_or_IP`

# 9. Change temp redirect to a permanent redirect 301
```bash
sudo nano /etc/nginx/sites-available/default
```
```
# /etc/nginx/sites-available/default
# server 2
server {
    # ...
    return 301 https://$server_name$request_uri;
    # ...
}
```
Test syntax, restart, visit page.
```bash
sudo nginx -t
sudo systemctl restart nginx
```
# 10. DONE.

评论

此博客中的热门博文

Windows下ShadowSocks客户端安装和配置 顺带KCP

How to Install KeePass on M1 Mac

How User Friendly is a MacOS