Let's Encrypt,站点加密之旅
97

HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

Let's Encrypt,是2016年4月12日成立的一家证书授权中心,提供免费的传输层安全(TLS)X.509证书,通过自动化的过程消除目前安全网站证书需要手工创建,加密,签名,安装以及更新的复杂性。

一直以来都觉得浏览器网址开头的那把小绿锁很别致啊,现在Let's Encrypt横空出世提供免费证书,说明https势在必行,那我也来动手给博客加把锁吧,看着就安全是吧。

Let's Encrypt 的官网提供的脚本看起来更加自动化一些,但我没有亲自尝试,而是在Github上搜到了一个开源脚本acme-tiny,用下来之后成功将博客加密完成。

特别提醒:请注意用户权限问题,下文都是使用的普通用户,而非 root ,请根据自己的情况调整。

file

根据acme-tiny提供的说明文档和我自己的实施过程列出以下几步:

克隆脚本

sudo git clone https://github.com/diafygi/acme-tiny.git  
cd acme-tiny

创建Let's Encrypt私钥

openssl genrsa 4096 > account.key

创建CSR(Certificate Signing Request,证书签名请求) 文件

ACME协议 (Let's Encrypt所使用的) 需要一个csr文件,用来进行证书签名和证书更新。

将需要加密的域名加到下面的代码中,目前一张证书最多可以加密 100 个域名:

openssl genrsa 4096 > domain.key     
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

注意:openssl.cnf 文件的位置可能会因为linux版本的不同而有变

证明你拥有该域名

acme-tiny脚本会生成验证文件并写入到你指定的目录下,然后通过 ".well-known/acme-challenge/" 这个URL来访问到验证文件. 注意: Let's Encrypt 会对你的服务器做一次http请求来进行验证,因此你需要保证80端口能够访问.

  • 手动生成challenges目录,用来存放验证文件(路径可以根据需要修改)

    mkdir -p /var/www/challenges

  • 配置nignx的80端口
    server {

        listen 80;
        server_name yoursite.com www.yoursite.com;

        if ( $request_uri !~ "/.well-known/acme-challenge/*" ) { # 让 Let's Encrypt 成功访问到验证文件不受 301 影响
                  return 301 https://yoursite.com$request_uri; # 注意进行301重定向到https,否则通过http仍能访问你的站点
        }

        location /.well-known/acme-challenge/ {
            alias /var/www/challenges/;
            try_files $uri =404;
        }

        #...你的其他配置
    }

Apache 则需修改 .htaccess 文件配置301重定向:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

获取签名证书

sudo chmod +x acme_tiny.py  
sudo python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /var/www/challenges/ > ./signed.crt

安装证书

针对nginx, 你还需要将 Let's Encrypt 的中间件证书 intermediate.pem 内容附加在签名证书signed.crt之后:

    wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem  
    cat signed.crt intermediate.pem > chained.pem
    server {
        listen 443;
        server_name yoursite.com www.yoursite.com;

        ssl on;
        ssl_certificate /path/to/chained.pem;
        ssl_certificate_key /path/to/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:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
        ssl_session_cache shared:SSL:50m;
        ssl_prefer_server_ciphers on;

        #...你的其他配置
    }

证书自动更新定时任务

恭喜!你的网站已经使用上了HTTPS。 但Let's Encrypt 证书有效期只有90天, 所以需要定期更新。现在只需要写一个更新脚本并把它放到定时任务中即可。

脚本内容:

    #!/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-x3-cross-signed.pem > intermediate.pem

    cat /tmp/signed.crt intermediate.pem > /path/to/chained.pem

    service nginx reload

定时任务可以设置为每个月执行一次:
0 0 1 * * sudo bash /path/to/renew_cert.sh 2>> /var/log/acme_tiny.log

原文链接:https://macken.me/article/encrypt-your-webiste-with-lets-encrypt

本帖由 Summer 于 2年前 加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 75
Summer

很酷炫,给你补了张图片。

2年前

:thumbsup:

2年前
RryLee

:100:

2年前

很常用的功能 :+1:

2年前

@Aufree 发哥好:smile:

2年前

请问一个证书可以绑定多个域名吗?比如一个a.example.com, b.example.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

是在这个里面nsubjectAltName后面不断加吗?

2年前

ValueError: Wrote file to /home/xxx/www/challenges/oJbvpIhkwkBGBAQUklWJXyC8VbWAdQqlgpwUJkgC1Vg, but couldn't download http://www.yoursite.com/.well-known/acme-challenge/oJbvpIhkwkBGBAQUklWJXyC8VbWAdQqlgpwUJkgC1Vg

出现这个问题,楼主是怎么解决的?

2年前

问题解决了,是因为我买的是腾讯云的新加坡CVM,无法域名无法解析到造成的。在CVM上ping了一下,无法ping通。我试了linode主机后,发现可以了。

2年前

:thumbsup:

2年前

@纸牌屋弗兰克

file

根域名没有配置好。

2年前

@all
大家注意了昂。按照上面的配置,有可能会踹你www.yourdomain.site可以访问,但是yourdomain.site则会出现不安全链接,造成无法访问,原因是。nginx中的配置文件中的逗号引起的。

file

去掉这个逗号就可以了。

2年前

@江边望海

server {
    listen 443;
    server_name tanteng.me;
    return 301 $scheme://www.$host$request_uri;
}

server {
    listen 443;
    server_name *.tanteng.me;
    root   /usr/share/nginx/html/tanteng.me/public;
    index  index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

我的server_name这样写根域名无法访问,301 重定向加上去也没用。。

2年前

@纸牌屋弗兰克 帖子一发我发现低级错误了。。。不能这样。。

2年前

@纸牌屋弗兰克 我试了一下你的域名根域名没有办法访问。原因,我已经说过了,是逗号引起的。

2年前

@江边望海
我的不是逗号的原因,你看我前面回复发的 nginx 配置,我新做了一个重定向,要注意的是 ssl 的重定向也需要带上验证信息。我看有没有更好的方法。现在OK了。

server {
    listen 443;
    server_name tanteng.me;
    return 301 https://www.tanteng.me$request_uri;

    ssl on;
    ssl_certificate /xxx/acme-tiny/chained.pem;
    ssl_certificate_key /xxx/acme-tiny/www.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
    ssl_session_cache shared:SSL:50m;
    ssl_prefer_server_ciphers on;
}
2年前

@江边望海 :+1: 恭喜!

2年前
Summer

PHPHub 已经参照此教程部署上 :beers:

2年前

@Summer 棒棒哒:100: 龙哥!

2年前

开启了 HTTPS 网站有时候好慢啊,大家有同样的感觉吗,如何优化
https://www.tanteng.me

2年前

@纸牌屋弗兰克 我访问了下你的blog,pretty fast ! 你网速是不是有点slow :smile:

2年前

@Macken 我登录wordpress后台巨慢无比,然后主站和前台页面就会很卡。。

2年前

<https:://www.h57.pw>

https://h57.pw

感谢分享,开心搞定了

2年前

@M1racle 我一开始也用多说,但因为多说的头像资源是http,导致没有心爱的小绿锁,所以还是选择使用disqus了~

2年前

@Macken 恩,我的那些图片什么的还是 http 过来的,慢慢改,争取早日小绿锁,明天放假就都能搞定了

2年前

Nice

2年前

@Macken @江边望海 请问下这个报错怎么解决,腾讯CVM,部署了很多东西不想换服务器。
Traceback (most recent call last):
File "acme_tiny.py", line 198, in
main(sys.argv[1:])
File "acme_tiny.py", line 194, in main
signed_crt = get_crt(args.account_key, args.csr, args.acme_dir, log=LOGGER, CA=args.ca)
File "acme_tiny.py", line 123, in get_crt
wellknown_path, wellknown_url))
ValueError: Wrote file to /var/www/challenges/GeyNz3Z0Jig5aujuqc-XdaqqHsgnD98fXnG5JjitsMg, but couldn't download http://www.xxxxx.club/.well-known/acme-challenge/GeyNz3Z0Jig5aujuqc-XdaqqHsgnD98fXnG5JjitsMg

连接地址ngnix报403 Forbidden
nginx.conf
listen 80 default_server;

listen [::]:80 default_server ipv6only=on;

    server_name xxxxx.club www.xxxxxx.club;
    return 301 https;//xxxxx.club$request_uri;

    location /.well-known/acme-challenge/{
            alias /var/www/challenges/;
            try_files $uri = 404;
    }
    index index.html index.htm index.php;
    root  /home/xxxxxxx/xxxx;
2年前

@GTYoung 你是用哪里的服务器?新加坡的还是香港的

2年前
  1. 服务器的原因。新加坡或者香港的可能是由于网络原因引起的。
  2. 你配置的时候最好将301注释一下,等验证通过再开启301
2年前

@江边望海 广州三区的服务器。。。 301注释了下还是couldn't download。加了301访问这个链接会报此页面有重定向循环

2年前

@GTYoung 出现这个问题是因为没有办法访问你的域名,是由于dns解析造成的,毕竟encrypt是在国外。

2年前

@江边望海 我发现我也死在这一步了,总是提示没有。。。。而我的是阿里云的服务器,万网的域名。。。目前不知道怎么解决。。。。

Traceback (most recent call last):
  File "acme_tiny.py", line 198, in <module>
    main(sys.argv[1:])
  File "acme_tiny.py", line 194, in main
    signed_crt = get_crt(args.account_key, args.csr, args.acme_dir, log=LOGGER, CA=args.ca)
  File "acme_tiny.py", line 123, in get_crt
    wellknown_path, wellknown_url))
ValueError: Wrote file to /var/www/challenges/BEo7QjU4lE9pv5kExEJWcjYSjE-LrI5IIG3ZrWim0ag, but couldn't download http://yoursite.com/.well-known/acme-challenge/BEo7QjU4lE9pv5kExEJWcjYSjE-LrI5IIG3ZrWim0ag

@Macken 可有解决之法?

2年前

@叶落山城 你要确定通过浏览器能访问到那个文件即可

2年前

@Macken 然而并不能,我猜,应该是我nginx配置的问题。。。。

2年前

@Macken 配置成功了,但是提示是 未授权证书, 红色的。。。。。

2年前

@叶落山城 你的网址发来看看

2年前

@Macken 获取证书那,一直download失败,然后我把301跳转那个注释掉就可以了。

Parsing account key...
Parsing CSR...
Registering account...
Already registered!
Verifying iphpt.com...
iphpt.com verified!
Verifying www.iphpt.com...
www.iphpt.com verified!
Signing certificate...
Certificate signed!

到后面 再把301打开的

2年前

@叶落山城 对的,就是要先关闭,验证成功再打开

2年前

@Macken 然而 并没有绿色。。。。 心塞。。。

2年前

@叶落山城 http://obq9881x1.bkt.clouddn.com/2e3cd3f854613d26ce7b9753ecc2cddd.jpg
你这张图片是http资源,换成https的就OK了,把图片下载下来,放到你的项目下就OK。

2年前

@Macken ok啦,确实是这个问题,谢谢亲,这篇文章其实是我昨天在 开发者头条看到的,不错不错
如果有人down失败了,且是国内服务器的,注意要把上面的301跳转记得注释掉哦。。。
吼吼吼~~~
叶落山城秋

2年前

@江边望海 我还用了 DigitalOcean 的解析。
domain:gtblog.club

@Macken 请问还有没有什么解决方案....

2年前
乔布斯隆

已收藏

2年前

已成功开启哦。 独音电台:https://indie-music.cn

2年前

@skov 恭喜!Nice ~

2年前

能加QQ吗,我这边一直提示文件不存在:346127275,@Macken

2年前

@ailulee 各位朋友随意加我QQ:615170821

2年前

CentOS6 的 openssl.cnf 文件在 /etc/pki/tls/openssl.cnf

2年前

@Macken
如果challenge.conf这样写的话就既能跳转到https页面,也能在不注释掉 301 跳转的情况下完成验证

server {

    listen 80;
    server_name foo.domain.com bar.domain.com;

    location /.well-known/acme-challenge/{
        alias /var/www/challenges/;
        try_files $uri =404;
    }

    location / {

        if ($host = "foo.domain.com"){
            return 301 https://foo.domain.com$request_uri;
        }

        if ($host = "bar.domain.com"){
            return 301 https://bar.domain.com$request_uri;
        }
    }

}

本人新手,如果有什么不妥之处,欢迎指正

2年前

@NicholasStone 多谢指教,已做相应的修改:+1:

2年前

补充:需要在location中加入对IP的验证,否则会通过80端口访问到nginx的默认界面

location / {
        if ($host = "xxx.xxx.xxx.xxx"){
            return 301 https://bar.domain.com$request_uri;
        }
       #Others
}
2年前

阿兰 2016/10/4 10:56:40
root@iZ23vqb2akbZ acme-tiny]# openssl req -new -sha256 -key domain.key -subj "/CN=www.jyhelper.com" > domain.csr
unable to load Private Key
3077805804:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:703:Expecting: ANY PRIVATE KEY

2年前

@xiao345 仔细看文章,有说明的:smile:

2年前

@all

file

今天突然发现我的证书失效了,说明自动续约没起作用,研究了发现需要针对301做如上处理,其他同学有什么看法,可以留言。

2年前

(SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch)

2年前

虽然安装成功了,但是假如nginx配置加上
if ( $request_uri !~ "/.well-known/acme-challenge/*" ) { # 让 Let's Encrypt 成功访问到验证文件不受 301 影响
return 301 https://yoursite.com$request_uri; # 注意进行301重定向到https,否则通过http仍能访问你的站点
}

    location /.well-known/acme-challenge/ {
        alias /var/www/challenges/;
        try_files $uri =404;
    }

的话会造成多次重定向,造成无法访问,所以没加,自然也就无法自动更新证书了,不知道nginx怎样写才不会多次重定向?

2年前

厉害了 我的哥

2年前

用官网的脚本的确简单些。推荐用官方脚本。

2年前

这个月刚开启https,也是用了 Let's encrypt 的证书,不过我的博客是又拍云赞助的免费cdn,直接在又拍云申请的let's encrypt免费证书,自主配置还是很方便的。最主要的是不用自主更新,配置完后自动续期,一劳永逸,哈哈,五星好评!

2年前

我的服务器是Apache

file

这个文件什么时候生成的

1年前

@496604841 在执行 acme_tiny.py 脚本的时候

1年前
Destiny

亲,自动续费那个定时任务可以用?

1年前

@Destiny 可以的,不放心的话可以手动执行一下。

1年前
Destiny

@Macken 嗯嗯。。

1年前
Destiny

不错不错,每月自动更新的脚步也生效了~~~!!!!

1年前

@Macken Already registered!
Verifying www.jc91715.top...
Traceback (most recent call last):
File "acme_tiny.py", line 198, in
main(sys.argv[1:])
File "acme_tiny.py", line 194, in main
signed_crt = get_crt(args.account_key, args.csr, args.acme_dir, log=LOGGER, CA=args.ca)
File "acme_tiny.py", line 123, in get_crt
wellknown_path, wellknown_url))
ValueError: Wrote file to /var/www/challenges/3Ub2MpiE01xEvtB5MOzHgQzoe5nYcnbHfVrGjPaiLKI, but couldn't download http://www.jc91715.top/.well-known/acme-challenge/3Ub2MpiE01xEvtB5MOzHgQzoe5nYcnbHfVrGjPaiLKI

apache2 vps 一直报这个错注释掉301 也不管用 大神这是怎么回事

1年前

@Macken location /.well-known/acme-challenge/ {
alias /var/www/challenges/;
try_files $uri =404;
}

这是Nginx的配置 apache上如何配置。

1年前

需要注意 这个证书不被支付宝支持,支付宝异步通知时不认识这个证书 ,只能用http了 。

1年前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!