Nginx在Ubuntu20.04使用Let’s Encrypt自签SSL证书

header

Let’s Encrypt是由互联网安全研究组(ISRG)授权开发的免费、自动化和开放的SSL证书。

Let’s Encrypt颁发的证书目前已得到各主流浏览器信任,每次签有都有 90 天的有效期。所以如果个人轻度使用,我们可以利用Let’s Encrypt来签发SSL证书。

本指南将逐步演示如何在 Ubuntu 20.04 上安装免费的加密 SSL 证书,并使用该证书在 Web 服务器Nginx上运行。除此之外,我们还将展示如何配置 Nginx 以使用 SSL 证书并启用 HTTP/2。


先决依赖

在开始之前,请务必你的环境已经满足了以下的要求:

  • 你有一个域名,并且有一个公共IP地址指向该域名,这里我以esharing.net为例
  • 你的Ubuntu20.04已经安装了Nginx
  • 确保你的防火墙已开放80与443端口

安装Certbot

我们将利用Cerbot这个工具来获取证书,并定期更新证书。

Certbot是一款功能全面并且容易使用的工具,可自动完成获取和更新“Let’s Encrypt” SSL证书。

Certbot已经在Ubuntu20.04的软件库里,所以我们可以直接运行以下命令进行安装:

sudo apt update
sudo apt install certbot

生成强DH(Diffie-Hellman)组

Diffie–Hellman Key Exchange(DH)是一种通过不安全的通信通道安全交换加密密钥的方法。

通过键入以下命令我们可以生成一组新的 2048 位 DH 参数:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

你也可以把2048改成4096,使得生成的是一个4096位的密钥,不过生成过程会耗时比较长,我试过将近30分钟才完成,这也取决于你的服务器性能。

获取Let’s Encrypt SSL 证书

域名所有权验证
  • 对于单一域名证书,多数情况下推荐使用webroot插件,因为它可以在不影响你的既有web服务器的情况下生成证书。webroot工作原理为:通过既有的web服务器向外暴露访问接口(需要通过域名能访问得到),在运行certbot命令时指定需要向外暴露访问的目录(通过--webroot-path-w指定),cerbot在于Let‘s Encrypt通信过程中会将挑战文件放在指定文件夹(${webroot-path}/.well-known/acme-challenge)下,然后Let’s Encrypt会通过域名访问该文件
  • 通过DNS,如果你拥有该域名,那么Let’s Encrypt会让你在该域名下设置一个TXT记录,记录值设置成Let’s Encrypt所要求的(在运行certbot时会提示),做到这一点则可以证明你的确拥有对该域名的拥有权。这种方式通常用于通配符证书,certbot无需运行在域名指向的服务器上。

在这里,因为我们只生成单一域名证书,我们选用第一种验证方式,但我们更加简单把所有/.well-know/acme-challenge 的HTTP请求全部转到 /var/lib/letsencrypt

下面的命令是创建相关的文件夹设定Nginx服务有写入权限

sudo mkdir -p /var/lib/letsencrypt/.well-known
sudo chgrp www-data /var/lib/letsencrypt
sudo chmod g+s /var/lib/letsencrypt

为了避免重复的代码,我们将创建两个snippets文件,并放到Nignx服务器配置文件夹中

使用nano创建并编辑文件第一个snippets文件”letsencrypt.conf

sudo nano /etc/nginx/snippets/letsencrypt.conf
/etc/nginx/snippets/letsencrypt.conf
location ^~ /.well-known/acme-challenge/ {
  allow all;
  root /var/lib/letsencrypt/;
  default_type "text/plain";
  try_files $uri =404;
}

创建第二个snippets文件:ssl.conf,让其支持Mozillo要求的chippers,开启OCSP Stapling,HSTS(HTTP Strict Transport Security),强制不安全的HTTP Headers

sudo nano /etc/nginx/snippets/ssl.conf
/etc/nginx/snippets/ssl.conf
ssl_dhparam /etc/ssl/certs/dhparam.pem;

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

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;

ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 30s;

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

这两个snippets文件创建成功后,我们需要把这两个配置文件添加到Nignx的配置参数server下面:

sudo nano /etc/nginx/sites-available/esharing.net.conf
/etc/nginx/sites-available/esharing.net.conf
server {
  listen 80;
  server_name esharing.net www.esharing.net;

  include snippets/letsencrypt.conf;
}

我们把这个配置文件生成一个软链接到/etc/nginx/sites-enabled文件夹中使其生效:

sudo ln -s /etc/nginx/sites-available/esharing.net.conf /etc/nginx/sites-enabled/

重启Nginx服务,使新的配置文件生效:

sudo systemctl restart nginx
获取自签SSL证书

上面的配置都完成后,我们就可以使用Cerbot及插件webroots来获取SSL 证书文件:

sudo certbot certonly --agree-tos --email admin@esharing.net --webroot -w /var/lib/letsencrypt/ -d esharing.net -d www.esharing.net

email填写你的邮箱,域名改成你的域名。

如果获取成功的话,你将来收到像下面一样的信息:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/esharing.net/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/esharing.net/privkey.pem
   Your cert will expire on 2021-10-18. 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

现在你就有你自己域名的SSL证书,存放在/etc/letsencrypt/live/esharing.net/里面。现在我们编辑我们域名的Nginx 配置文件:

sudo nano /etc/nginx/sites-available/esharing.net.conf
/etc/nginx/sites-available/esharing.net.conf
server {
    listen 80;
    server_name www.esharing.net esharing.net;

    include snippets/letsencrypt.conf;
    return 301 https://$host$request_uri;
}

//www跳转到non-www
server {
    listen 443 ssl http2;
    server_name www.esharing.net;

    ssl_certificate /etc/letsencrypt/live/esharing.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/esharing.net/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/esharing.net/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    return 301 https://esharing.net$request_uri;
}

server {
    listen 443 ssl http2;
    server_name esharing.net;

    ssl_certificate /etc/letsencrypt/live/esharing.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/esharing.net/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/esharing.net/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    # . . . other code
}

上面的配置我们已经把生成的证书加载进Nginx,并把www跳转到non-www.

最后重启Nginx生效所有新的配置

sudo systemctl reload nginx

打开浏览,以”https://“访问你的域名,如果地址栏的加密锁完好不报错,证明你已成功部署。

你也可以通过SSL证书测试网站 来验证,如果一切没有错的话,你将可以得到A+的得分!

自动更新证书有效期

由于我们获得的证书只有3个月有效期,如果每次到期后都需要人工去获取新的证书,那将是一个非常麻烦的事,所以我们可以通过自动化计划任务来定期获取SSL证书

我们先判断certbot是否正常运行:

sudo certbot renew --dry-run

如果显示下面信息则表示已正常运行:

...
Congratulations, all renewals succeeded.
...

那就编写cron脚 本,让自动运行更新命令:

sudo nano /etc/cron.d/certbot
/etc/cron.d/certbot
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew --renew-hook "systemctl reload nginx"

以上脚本每天运行2次,但是只有在证书即将过期的时候才会真正执行renew操作。

写在最后

如果你想了解更多关于certbot的使用,请查看官方文档

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注