手把手教你搭建基于 Let’s Encrypt 的免费 HTTPS 证书

Let's Encrypt 是国外一个公共的免费 SSL 项目,该项目是为了普及 HTTPS 而发起的,目前已经被 Mozilla、Google、Microsoft 和 Apple 等主流浏览器支持,对 HTTPS 技术的普及有着巨大贡献。随着 HTTPS 的普及,Let's Encrypt 已经成为全球最受欢迎的免费 SSL 证书签发机构。

注意事项

  • Let's Encrypt 的基础证书只提供了数据加密,不验证身份,从而也无法证明网站的所有者,虽然已经满足绝大部分应用场景,但若涉及核心功能时还是需要进行身份验证
  • Let's Encrypt 签发的证书一次的有效期为 3 个月,需要定期更新证书(官方推荐两个月左右更新一次,本文有提供自动更新方案)

安装 EPEL 仓库

Let's Encrypt 的签发证书工具在 EPEL 仓库中才能找到,所以如果没有安装 EPEL 仓库的话要先安装一下

# 查询是否已安装 epel 仓库
rpm -qa epel-release
# 若没有安装再安装 epel 仓库
sudo yum install -y epel-release

安装签发证书工具

用 Certbot 工具申请 Let's Encrypt 证书,要先安装该工具:

sudo yum install certbot-nginx

如果报以下错误:

ImportError:No module named 'requests.packages.urllib3'

执行以下命令解决:

# 如果没有 pip 可使用 `sudo yum install python-pip` 安装
pip install --upgrade --force-reinstall 'requests==3.6.0' urllib3

申请证书

I. 网站运行在申请 SSL 证书的服务器上

这边将申请证书分为两种情况,正常情况下我们使用第一种就好了,也就是网站运行在申请 SSL 证书的服务器上。另外就是比如在 A 机器上申请证书,但网站运行在 B 机器上,当然如果你是用 Docker 跑的 Nginx 也得用第二种方式

  • 第一种方式有以下几个条件:
    1. 你要申请 SSL 证书的域名已经指向到申请证书服务器的 ip
    2. 你的 Web 服务器需要使用 Nginx(在本例子中,可以在官网查看其它服务器的方式)
    3. Nginx 配置完成,并且已经绑定了你要申请 SSL 证书的域名

具备以上条件,就可以执行以下操作啦:

# 申请 SSL 证书,certonly 表示只生成证书,不做额外操作
sudo certbot --nginx certonly

certbot 会自动查找当前 Nginx 上的虚拟主机,并提示:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org

Which names would you like to activate HTTPS for?
-------------------------------------------------------------------------------
1: xxx.wolfcode.cn
-------------------------------------------------------------------------------
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1

如果出现以下错误:

# Saving debug log to /var/log/letsencrypt/letsencrypt.log
# The nginx plugin is not working; there may be problems with your existing configuration.
# The error was: NoInstallationError()

可能是因为找不到 nginx 命令,解决方案:

# 以下命令是分别将 nginx 安装目录的 nginx 命令与配置文件软连接到指定文件
# 你可以根据自己的具体情况修改目录
ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
ln -s /usr/local/nginx/conf /etc/nginx

还有可能提示无法连接到你的服务器,主要要开放防火墙的 443 端口

看到前面正确提示,出现我的 Nginx 上绑定的一个域名,如果你的 Nginx 有绑定多个,那么列表中也会以多个显示,然后输入你需要申请 SSL 证书对应域名的序号即可,验证成功后 Let's Encrypt 就会立即给你签发 SSL 证书,成功后提示:

# Obtaining a new certificate
# Performing the following challenges:
# tls-sni-01 challenge for g.wangchujiang.com
# Waiting for verification...
# Cleaning up challenges
# 
# IMPORTANT NOTES:
#  - Congratulations! Your certificate and chain have been saved at:
#    /etc/letsencrypt/live/xxx.wolfcode.cn/fullchain.pem
#    Your key file has been saved at:
#    /etc/letsencrypt/live/xxx.wolfcode.cn/privkey.pem
#    Your cert will expire on 2018-03-29. 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"
#  - 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

以上信息则表示证书生成成功了。其他信息主要是告诉你证书存放的位置、过期时间以及更新证书命令:

# 证书位置
/etc/letsencrypt/live/xxx.wolfcode.cn/fullchain.pem
/etc/letsencrypt/live/xxx.wolfcode.cn/privkey.pem
# 过期时间:Your cert will expire on 2018-06-19.
# 你的证书将在 2018-06-19 过期
# 可以使用如下命令更新证书有效期
certbot renew --dry-run

配置 Nginx,让所有 HTTP 请求转发到 HTTPS:

# 将 http 请求转发到 https
server {
    listen       80;
    server_name  xxx.wolfcode.cn;
    rewrite  ^(.*)$ https://$host$1 permanent;
    # 禁止在 heaader 中出现服务器版本,防止黑客利用版本漏洞攻击
    server_tokens off;
}

# https 的配置
server {
    listen   443 ssl;
    server_name  xxx.wolfcode.cn;

    ssl_certificate /etc/letsencrypt/live/xxx.wolfcode.cn/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/xxx.wolfcode.cn/privkey.pem;
    # 禁止在 heaader 中出现服务器版本,防止黑客利用版本漏洞攻击
    server_tokens   off;
    # 设置ssl/tls会话缓存的类型和大小。如果设置了这个参数一般是shared,buildin可能会参数内存碎片,默认是none,和off差不多,停用缓存。如shared:SSL:10m表示我所有的nginx工作进程共享ssl会话缓存,官网介绍说1M可以存放约4000个sessions。
    ssl_session_cache    shared:SSL:1m;


    # 客户端可以重用会话缓存中ssl参数的过期时间,内网系统默认5分钟太短了,可以设成30m即30分钟甚至4h。
    ssl_session_timeout  5m;

    # 选择加密套件,不同的浏览器所支持的套件(和顺序)可能会不同。
    # 这里指定的是OpenSSL库能够识别的写法,你可以通过 openssl -v cipher 'RC4:HIGH:!aNULL:!MD5'(后面是你所指定的套件加密算法) 来看所支持算法。
    ssl_ciphers  HIGH:!aNULL:!MD5;

    # 设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。
    ssl_prefer_server_ciphers  on;

    location / {
        root   /www/html/website;
        index  dist/index.html;
    }

    error_page   404    /404.html;
    location = /404.html {
    root    html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

到此就配置完成啦,使用 HTTPS 访问看看吧

II. 网站运行在申请 SSL 证书以外的服务器上

为其他主机上的网站或 Docker 中的网站申请 SSL 证书,只需要多一步验证即可:

# 申请证书
# certonly 只生成证书,不做额外操作
# --manual 交互式操作,也就是追加验证条件
sudo certbot certonly --manual

提示让你输入想要申请证书的域名

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'
to cancel): xxx.wolfcode.cn

接着会提示需要记录你申请 SSL 证书域名对应服务器的 IP,问你是否同意:

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for ninghao.net

-------------------------------------------------------------------------------
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
-------------------------------------------------------------------------------
(Y)es/(N)o: Y

然后会给一个字符串,让你将字符内容保存在一个文件内,并可以通过它所指定的 URL 进行访问,cretbot 会对该 URL 进行校验

-------------------------------------------------------------------------------
Create a file containing just this data:

HNIVXWGNL99iXcy5zI9OwSZmugf0xnv786nw5HchlJ4.n3Pm5l0vxnRwAslvOBBkXT1rGGJ7AwbTnaSCsSiQJFc

And make it available on your web server at this URL:

http://wolfcode.cn/.well-known/acme-challenge/HNIVXWGNL99iXcy5zI9OwSZmugf0xnv786nw5HchlJ4

-------------------------------------------------------------------------------
Press Enter to Continue

比如我这个,则可以在 website 根目录创建:

# 创建验证文件夹
mkdir -p /yourwebsite/.well-known/acme-challenge/
# 进入该文件夹
cd /yourwebsite/.well-known/acme-challenge/
# 创建文件(以下两部内容请修改为你自己的数据)
touch HNIVXWGNL99iXcy5zI9OwSZmugf0xnv786nw5HchlJ4
# 将提示信息写入文件
echo "HNIVXWGNL99iXcy5zI9OwSZmugf0xnv786nw5HchlJ4.n3Pm5l0vxnRwAslvOBBkXT1rGGJ7AwbTnaSCsSiQJFc" > HNIVXWGNL99iXcy5zI9OwSZmugf0xnv786nw5HchlJ4

验证通过之后便会签发证书:

Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/wolfcode.cn/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/wolfcode.cn/privkey.pem
   Your cert will expire on 2018-03-29. 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"
 - 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

到此证书申请便完成了,Nginx 配置可以参考上面的配置

添加定时任务完成自动更新

现在证书申请、配置都已经完成了,并且也可以正常访问,但还有个小问题就是 Let's Encrypt 签发的证书只有 90 天的有效期,到期后需要再更新,此时便可以使用到 linux 上的 crontab 工具来定时帮我们完成更新操作

certbot 为我们提供了很方便的更新方式,你只需要执行如下命令:

# 更新所有证书
sudo certbot renew --dry-run

使用以上命令便可以将所有证书更新,那么此时我们可以添加一个定时任务来完成这一操作:

# 进入定时任务存放目录
cd /etc/cron.d
# 将脚本写入文件,该脚本是每 2 个月的 20 号凌晨 2:15 执行一次
echo "15 2 20 */2 * certbot renew --dry-run" > certbot-auto-renew-cron
# 将脚本加入到 crontab
crontab certbot-auto-renew-cron

至此,SSL 证书就算彻底完成啦

你可能感兴趣的:(手把手教你搭建基于 Let’s Encrypt 的免费 HTTPS 证书)