letsencrypt https - downgoon/hello-world GitHub Wiki

HTTPS 与 免费CA机构 letsencrypt

HTTPS需求背景与行业动态

互联网http是明文传输,经常被ISP进行“流量劫持”。你可以搜索下“百度被流量劫持”的案例。于是大概在 2015年百度等互联网公司“全站启用https”(不仅仅是passport这类账号应用,连一个普通的静态页面都走https)。

走https,首先得向CA申请一个证书。而且这个CA必须被各大主流浏览器厂商认可,否则用户访问站点时,会被告知“潜在的安全风险”。

letsencrypt 这个组织做了一件伟大的事情——免费的CA,而且它被主流浏览器认可。

借助letsencrypt实现HTTPS

如何向免费CA机构:letsencrypt 申请 HTTPS的安全证书呢? 官方有教程:

  • 一方面letsencrypt提供了免费的,且主流浏览器认可的证书;
  • 另一方面它要求每90天更新一次证书。

但是还有热心网友写了一个自动化脚本,能够自动申请&更新证书。

下载脚本

wget https://raw.githubusercontent.com/xdtianyu/scripts/master/lets-encrypt/letsencrypt.conf
wget https://raw.githubusercontent.com/xdtianyu/scripts/master/lets-encrypt/letsencrypt.sh
chmod +x letsencrypt.sh

修改配置

ACCOUNT_KEY="letsencrypt-account.key"
DOMAIN_KEY="example.com.key"
DOMAIN_DIR="/var/www/example.com"
DOMAINS="DNS:example.com,DNS:whatever.example.com"

上述4项配置,只需修改最后三项:

  • DOMAIN_KEY: 域名对应的私钥(脚本执行时,会自动生成私钥,并保存到这个文件)。
  • DOMAIN_DIR:域名对应的ROOT目录。如果是nginx服务器,那么对应的就是 root 配置指向的目录。
  • DOMAINS: 证书被用于哪几个域名。

如果您的域名是downgoon.xyz,那么上述配置修改为:

ACCOUNT_KEY="letsencrypt-account.key"
DOMAIN_KEY="downgoon.xyz.key"
DOMAIN_DIR="/data/wwwroot/default"
DOMAINS="DNS:downgoon.xyz"

对应的nginx配置形如:

server {
  listen 80;
  root /data/wwwroot/default;
  index index.html index.htm index.php;
  ...  
} 

其中 DOMAIN_DIR 与 nginx的 root 取值 /data/wwwroot/default 必须一致。

执行脚本

$ ./letsencrypt.sh letsencrypt.conf
Generate account key...
Generating RSA private key, 4096 bit long modulus
................................................................................................................++
...........................................................................................................................................++
e is 65537 (0x10001)
Generate domain key...
Generating RSA private key, 2048 bit long modulus
.........................................................+++
.....................................+++
e is 65537 (0x10001)
Generate CSR...downgoon.csr
Parsing account key...
Parsing CSR...
Registering account...
Registered!
Verifying downgoon.xyz...
downgoon.xyz verified!
Signing certificate...
Certificate signed!
New cert: downgoon.chained.crt has been generated

生成的文件列表:

├── downgoon.chained.crt  (4)被盖章的公钥证书 ?
├── downgoon.crt  (3)公钥证书
├── downgoon.csr   (2)证书请求文件 Cerificate Signing Reques,网站给CA发送申请,希望CA给它的网站公钥盖章。这个申请函就叫``csr``。
├── downgoon.xyz.key   (1)网站私钥,私钥可以导出公钥。用openssl自己生成就可以。
├── letsencrypt-account.key
├── letsencrypt.conf    (热心网友的配置)
├── letsencrypt.conf.origin
├── letsencrypt.sh    (热心网友的脚本)
└── lets-encrypt-x3-cross-signed.pem

nginx配置证书

假设刚才执行脚本的目录是/root/https,那么生成的文件也在这个目录,我们在nginx里面配置侦听 443 端口(HTTPS默认端口),ROOT目录保持跟HTTP相同(即:root /data/wwwroot/default;)。

使用指令 ssl_certificate_key指定网站私钥,指令 ssl_certificate 指定网站公钥。如下所示:

server {
   listen 443 ssl;
   ssl_certificate /root/https/downgoon.chained.crt;
   ssl_certificate_key /root/https/downgoon.xyz.key;
   root /data/wwwroot/default;
   index index.html index.htm index.php;
  }

重新加载nginx的配置:

$ nginx -s reload

访问测试

在浏览器中输入:https://downgoon.xyz

注意:downgoon.xyz 必须是一个公网域名。如果您没有公网域名,可以去阿里云或者Namecheap, GoDaddy 等申请一个。如果在阿里云申请的域名,申请后,接着使用阿里云的“云解析”把域名A记录到公网IP(也可以申请阿里云的ECS云主机)。

思考题:域名确权

我们向免费CA机构letsencrypt申请 downgoon.xyz 的公钥盖章时,letsencrypt怎么知道声称的域名 downgoon.xyz 的确就是我的呢?假如我向CA声称自己是google.com呢?它能相信我吗?

https flow.png

Let's Encrypt 会从公网访问域名http://downgoon.xyz/.well-known/acme-challenge,这个隐藏的目录是跟Let's Encrypt的一种约定,只要用户能在目标服务器上放置这个文件,就表示用户拥有这个域名的控制权。

参考资料