Skip to main content

nginx HTTPS Reverse Proxy

Free2017-04-23#Node#Solution#免费HTTPS证书推荐#nginx添加https模块#nginx反向代理https#nginx node https#nodejs https

Why not get a free green lock?

1. Environment

Centos:

$ cat /etc/redhat-releas
CentOS Linux release 7.3.1611 (Core)

Not required, the configuration method is the same, and the nginx compilation and installation process is also the same. Use whichever you're familiar with.

nginx:

$ /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.9.9
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-file-aio --with-http_realip_module

configure arguments must include with-http_ssl_module. This option must be added during ./configure to enable the ssl module, otherwise it's quite troublesome (there's nothing like phpize, you can only recompile with the added parameter to overwrite as needed).

Free SSL Certificate:

https://letsencrypt.org/getting-started/

Let's Encrypt is relatively more reliable. It's a non-profit organization aiming to promote HTTPS adoption, so let's contribute to world peace with this (although mainly just for the free aspect~).

P.S. The certificate has a 3-month validity period and needs renewal when expired. It can be renewed automatically via tools, which is not very troublesome.

node:

$ nvm ls
        v6.10.0
->       v7.9.0
default -> stable (-> v7.9.0)
node -> stable (-> v7.9.0) (default)
stable -> 7.9 (-> v7.9.0) (default)

Not required, used to verify that the reverse proxy works correctly after nginx configuration is complete. Any other way to start an HTTP server works too.

2. Apply for a Free SSL Certificate

Go to https://letsencrypt.org/getting-started/, follow the steps one by one. The With Shell Access method is recommended. It provides a command-line tool certbot, which is interactive and easy to use like clicking "next".

Additionally, the benefit of using the command-line tool is that certificates can be automatically renewed when they expire—just execute one command. Add it to the cron task, and you won't be disturbed. You can even run it once a day automatically. The official recommendation is to do this as a heartbeat to indicate the system is healthy and won't be screened/revoked:

Note:

if you're setting up a cron or systemd job, we recommend running it twice per day (it won't do anything until your certificates are due for renewal or revoked, but running it regularly would give your site a chance of staying online in case a Let's Encrypt-initiated revocation happened for some reason). Please select a random minute within the hour for your renewal tasks.

Following certbot step by step, for example, the steps for this environment are:

# Add yum repository
yum -y install yum-utils
yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional
# Install certbot
sudo yum install certbot
# Only request certificate, don't auto-configure
certbot certonly

If everything goes normally, you'll finally get a prompt like this:

Generating key (2048 bits): /etc/letsencrypt/keys/0000_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0000_csr-certbot.pem

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/<mydomain>/fullchain.pem. Your cert will
   expire on 2017-07-17. To obtain a new or tweaked version of this
   certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Both the certificate and private key are located under /etc/letsencrypt/live/<mydomain>/:

$ ls /etc/letsencrypt/live/<mydomain>/
cert.pem  chain.pem  fullchain.pem  privkey.pem  README

Among these, cert.pem is the certificate (server certificate), privkey.pem is the private key. These two are all you need. Additionally, chain.pem contains the root certificate and intermediate certificates, etc., excluding the server certificate—needed for the certificate chain authentication process. fullchain.pem is the complete certificate chain, including the contents of cert.pem and chain.pem.

Finally, enable automatic renewal:

# Test update
certbot renew --dry-run

If everything is normal, add a cron task:

crontab -e
# Update certificate daily at 1:11
1 1 * * * certbot renew >> ~/cron/cert.log --renew-hook "/usr/local/nginx/sbin/nginx -s reload"
# View all tasks
crontab -l

Note: You must add --renew-hook to automatically restart nginx after certificate renewal, otherwise the expired certificate will continue to be used. Although the certificate is updated, it won't take effect.

3. Configure nginx HTTPS Reverse Proxy

Check ssl module:

$ /usr/local/nginx/sbin/nginx -V

If configure arguments contains with-http_ssl_module, it means the ssl module is already present. Otherwise, you need to add the parameter and recompile to overwrite the existing nginx executable file. For specific steps, please refer to nginx recompile to add ssl module.

Modify configuration file:

# Backup
cp /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf_
# Edit
vi /usr/local/nginx/conf/nginx.conf
# Modify the content under HTTPS server to:
server {
    listen       443 ssl;
    server_name  localhost;

    ssl_certificate      /etc/letsencrypt/live/<mydomain>/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/<mydomain>/privkey.pem;

    ssl_session_timeout  5m;

    location / {
        proxy_pass http://localhost:7777;
    }
}
# Test configuration syntax
/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
# Restart nginx
/usr/local/nginx/sbin/nginx -s reload

If everything is normal, at this point the HTTPS reverse proxy for the entire site is configured, with all requests forwarded to port 7777.

P.S. If you need to configure forwarding for a specific path, just modify the location path matching rules. For details, refer to Nginx Configuration Brief.

4. Start HTTP Server to Confirm Proxy is Working

With nginx maintaining the HTTPS connection, the HTTP service behind it almost doesn't need to make any changes, because it still receives HTTP requests, just forwarded by nginx (but cookie and other items may have issues after forwarding and need proxy_cookie_path configuration—we'll discuss that later when we encounter it).

const http = require('http');

const PORT = 7777;

http.createServer((req, res) => {
    res.end('hoho, ' + PORT);
}).listen(PORT);
console.log('server is ready, listening ' + PORT);

Visit https:<mydomain>/ and see hoho, 7777, which indicates the proxy is working.

A beautiful green lock is now displayed in the address bar. Additionally, generally you also need to configure DNS resolution rules, force HTTP requests to redirect to HTTPS, or use the more reasonable HSTS method, etc. These are matters for later.

Comments

No comments yet. Be the first to share your thoughts.

Leave a comment