手把手教你搭建基于 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 证书就算彻底完成啦

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容