使用 Let's Encrypt 签署免费 Https 证书

2,447 阅读4分钟
原文链接: blog.timeliar.com

本文操作在Linux操作系统下完成,需要Python和Nginx

超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,常称为HTTP over TLS,HTTP over SSL或HTTP Secure)是一种网络安全传输协议。在计算机网络上,HTTPS经由超文本传输协议进行通信,但利用SSL/TLS来加密数据包。HTTPS开发的主要目的,是提供对网络服务器的身份认证,保护交换数据的隐私与完整性。这个协议由网景公司(Netscape)在1994年首次提出,随后扩展到互联网上。
HTTPS连接经常用于万维网上的交易支付和企业信息系统中敏感信息的传输。HTTPS不应与在 RFC 2660 中定义的安全超文本传输协议(S-HTTP)相混淆。

以上引用自维基百科关于Https的解释
关于Https的详细信息网上都有,请查阅维基百科Google

本文签发Https证书的机构为Let’s Encrypt(以下简称为LE), 该组织旨在消除当前手动创建和安装证书的复杂过程的自动化流程,为安全网站提供免费的SSL/TLS证书。

流程开始

注册Let’s Encrypt账户(account.key)

account.key为LE用来识别你身份(相当于账户)的RSA key,使用openssl生成

openssl genrsa 4096 > account.key

创建CSR文件

LE和ACME协议旨在配置一个自动化的,不需要人为干涉
即可以获得浏览器信任证书的Https服务器,该功能是通过服务器上运行一个证书管理代理程序(Certificate Management Agent)来实现的,该程序首先需要一个域名的证书签名请求文件(Certificate Signing Request, CSR),然后将该文件递交给LE进行签发。
首先生成domain.key文件来作为域名的身份凭证

openssl genrsa 4096 > domain.key

切记不可使用account.key来作为domain.key
然后生成CSR文件

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

将{domain1},{domain2}替换成自己的域名即可,比如timeliar.date,blog.timeliar.date,可添加多个,以逗号分隔,写成DNS:domain的格式即可。
提示/etc/ssl/openssl.cnf找不到的话请自行google:can not open /etc/ssl/openssl.cnf,路径有可能是/usr/local/ssl/openssl.cnf,这个取决于openssl是如何安装的

认证

LE想给你域名签发证书首先得确定域名可用,并且域名是你的。

  • 首先创建一个写入临时文件的目录,如/var/www/le

    mkdir -p /var/www/le
    
  • 修改Nginx配置文件,添加一个virtual server

    server {
          listen 80;
          location ^~ /.well-known/acme-challenge/ {
            alias /var/www/le/;
            try_files $uri =404;
          }
    }
    

    path /.well-known/acme-challenge/为LE固定访问URI,请不要修改

  • 启动nginx

    nginx
    
  • 开始认证
    python acme_tiny.py \
            --account-key account.key \
            --csr domain.csr \
            --acme-dir /var/www/le/ > \
            signed.crt
    # 获取LE中见证书
    wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem
    # 将le的中间证书和生成的证书组合成证书链
    cat ./signed.crt ./intermediate.pem > ./chained.pem
    
    认证过程中py脚本会对提供的本机目录/var/www/le里写文件,然后通过访问{domain}/.well-known/acme-challenge/{文件名}来校验域名是否可用

生成dhparam

前段时间Google完成了SHA-1的碰撞实验(Google宣布攻破SHA-1,从此SHA-1不再安全),是时候该抛弃SHA-1了,这里使用了迪菲-赫尔曼密钥交换协议,具体讲解请看wikipedia

openssl dhparam -out dhparam.pem 2048

配置Nginx

将生成的chained.pem配置到Nginx中

ssl on;
ssl_certificate /path/to/chained.pem;
ssl_certificate_key /path/to/domain.key;
ssl_dhparam /path/to/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers  on;

然后开始使用吧!
但是出于安全考虑,该证书有效期只有90天,到期之后只需要再次进行认证即可,将下列脚本加入crontab,90天运行一次

python acme_tiny.py \
        --account-key account.key \
        --csr domain.csr \
        --acme-dir /var/www/le/ > \
        signed.crt
cat ./signed.crt ./intermediate.pem > ./chained.pem

此外还有一些著名付费Https证书签发机构

免费的证书认证级别还是还是比较低的,只能起到加密信息的作用,适合做个人网站博客等安全要求不是特别高的。电商站点还是得用认证级别更高的付费证书来防止钓鱼网站

  • 自行Google吧