51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

使用Let's Encrypt保护你的数据包

【过年了,每天发一篇以前的存货,一共七篇。】

Let's Encrypt是去年底推出的一个免费SSL证书,且申请这个证书基本没有任何限制,只要你证明你是域名的所有者,你就可以为你的域名申请一个SSL证书。

我今天就来为我的 wiki.ioin.in 申请一个时髦的Let's Encrypt证书。

首先,我利用到的是acme-tiny,这是第三方人士开发的一个扩展。因为Let's Encrypt官方给出的方法比较麻烦,而acme-tiny这个小工具可以让用户敲几条命令即可生成好我们需要的证书。

下载acme-tiny: https://github.com/diafygi/acme-tiny

首先,生成一个用户私钥: account.key,acme-tiny通过这个证书来登录Let's Encrypt。再生成一个域名私钥,domain.key

openssl genrsa 4096 > account.key
openssl genrsa 4096 > domain.key

14552588259506.jpg

然后利用ACME协议,将domain.key生成domain.csr。如果你只有一个域名需要ssl,只需执行下面的语句:

openssl req -new -sha256 -key domain.key -subj "/CN=yoursite.com" > domain.csr

如果你有多个域名,比如www.xxx.com和xxx.com,你就执行下面的语句:

openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:yoursite.com,DNS:www.yoursite.com")) > domain.csr

我的 wiki.ioin.in 是单域名证书,所以执行下面语句即可:

14552588402436.jpg

Let's Encrypt有多种方法来验证你是否是域名的所有人,而acme-tiny这个小工具用的是最简单的方法,也就是利用http文件验证。
简单来说,就是生成一个验证文件,放在http://example.com/.well-known/acme-challenge/下,Let's Encrypt官方验证这个文件是否存在、内容是否正确。如果一切正确,说明域名是你所有。

所以我这里,新建了一个/home/www/challenges/目录,将它别名指向 /.well-known/acme-challenge/ 。这样,我在challenges目录里写入的文件,即可通过 http://xxxx.com/.well-known/acme-challenge/ 访问了。nginx配置如下:

14552588522823.jpg

然后,运行acme_tiny.py脚本:

python acme_tiny.py --account-key /etc/ssl/letsencrypt/account.key --csr /etc/ssl/letsencrypt/domain.csr --acme-dir /home/www/challenges/ > /etc/ssl/letsencrypt/signed.crt

其中,将--account-key的值改为你生成的account.key的路径;--csr的值改成你生成的domain.csr的路径;--acme-dir的值改为我要写入验证文件的文件夹。
最后成功生成signed.crt,这就是我的域名证书:

14552589980593.jpg

在nginx里,还需要将Let's Encrypt的中间证书放到自己的证书后面,构成一个证书链chained.pem:

wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
cat signed.crt intermediate.pem > chained.pem

另外,还需要生成一个较强的dh。(位数不要太多!我生成了一个4096位的dh,半个小时还没生成好)。关于dh的安全性,可以关注这个网站: https://weakdh.org ,这篇文章:https://weakdh.org/sysadmin.html

openssl dhparam -out dhparam.pem 2048

14552626630232.jpg

生成好以后,将以上生成的私钥、证书、dh等写入nginx的配置文件:

server
{
    listen 80;
    listen 443 ssl;
    #listen [::]:80;
    server_name wiki.ioin.in;
    index index.html index.htm;

    ssl on;
    ssl_certificate /etc/ssl/letsencrypt/chained.pem;
    ssl_certificate_key /etc/ssl/letsencrypt/domain.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DH$
    ssl_session_cache shared:SSL:50m;
    ssl_dhparam /etc/ssl/letsencrypt/dhparam.pem;
    ssl_prefer_server_ciphers on;
    ...the rest of your config
}

重启nginx,一切万事大吉: https://wiki.ioin.in

14552632280629.jpg

另外,我们看证书的过期日期。算一下这个证书其实只有3个月,也就是一个季度。当证书快要过期的时候,我们还需要重新颁发一下证书。
重新颁发证书的过程就比较简单了,只需要重新执行acme_tiny.py即可。

我们可以将重新颁发的过程写在一个脚本里:

#!/usr/bin/sh
python /path/to/acme_tiny.py --account-key /path/to/account.key --csr /path/to/domain.csr --acme-dir /var/www/challenges/ > /tmp/signed.crt || exit
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
cat /tmp/signed.crt intermediate.pem > /path/to/chained.pem
service nginx reload

然后将这个脚本加入cron,每月执行一次:

#example line in your crontab (runs once per month)
0 0 1 * * /path/to/renew_cert.sh 2>> /var/log/acme_tiny.log

就不需要人工操作了~

最后,测试一下SSL质量: https://www.ssllabs.com/ssltest/

14552645362489.jpg

赞(0)
未经允许不得转载:工具盒子 » 使用Let's Encrypt保护你的数据包