dwqs/blog

Nginx 上配置 HTTPS 环境

dwqs opened this issue · 8 comments

dwqs commented

这是一篇纯粹的流水账笔记,本文涉及到的 certbot/certbot-auto 版本是 0.21,如果你用的是 0.22 或以上版本,可参考官网步骤来配置通配符

环境

  • CentOS: 7.4
  • Nginx: 1.12.2
  • Python: 2.7.5

步骤

通过 yum install certbot 或者按照官方步骤,安装 certbot 之后,运行如下命令开始生成证书:

certbot certonly --email xxx@gmail.com --cert-name xxx --webroot -w /www/xxx/ -d xxxx.com -w /www/xxx2/ -d xxxx2.com
  • email:指定一个邮箱
  • cert-name:设定证书名字
  • d:对应的域名
  • w:域名对应的根目录

多个域名正式其实就是将 -w-d 部分重复即可。

但实际情况并不如此顺利,可能会碰到如下错误:

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

相关的 issue 讨论:#4886#5104

尝试 issue#5104 给出的一个方式:

pip install requests urllib3 pyOpenSSL --upgrade

运行之后再次生成证书时,又出现如下错误:

ImportError: 'pyOpenSSL' module missing required functionality. Try upgrading to v0.14 or newer.

升级 pyOpenSSL

pip install pyOpenSSL==16.2.0

ImportError 依然存在。

最后的解决方案是顺序运行如下命令:

pip uninstall requests
pip uninstall urllib3
yum remove python-urllib3
yum remove python-requests
yum remove certbot
yum install python-urllib3
yum install python-requests
yum install certbot
# 最后运行 certbot xxx 生成证书

如果证书创建成功的话会在终端看到类似如下的输出:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
 - ...
 # 会输出证书的保存位置

国内的域名需要先备案,不然最后生成证书的时候会失败

证书生成之后呢,需要再配置 Web Server,我使用的是 Nginx,如果你使用的是 Apache 或者别的服务器,需要自行更改对应的配置文件。

#  nginx.conf 的对应 server 进行配置
server {
    listen       443 ssl http2 default_server;
    listen       [::]:443 ssl http2 default_server;
    server_name  xxxx.com;
    root         /home/www;

    ssl_certificate "/etc/letsencrypt/live/xxxx.com/fullchain.pem";
    ssl_certificate_key "/etc/letsencrypt/live/xxxx.com/privkey.pem";
    ssl_trusted_certificate /etc/letsencrypt/live/xxxx.com/chain.pem;
    
    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

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

证书更新

由于 certbot 所使用的 letsencrypt 证书只有 90 天的有效期,所以需要定期更新证书。

测试自动更新功能:

sudo certbot renew --dry-run

如果功能正常,可以在 crontab 里添加计划任务来完成。在 /etc/crontab 文件里添加以下定时任务:

30 5 1 * * root /usr/bin/certbot renew --renew-hook "/usr/sbin/nginx -s reload"

以上每月1号5点30分执行更新,这个频率可以自己设定,不能太频繁。--renew-hook 后面根据自己的 web server 来改成相应的命令,上面是 nginx 作为 web server,证书更新后重新加载配置文件。

后记

对于 Python 2.6/CentOS 6/Nginx 的环境,则需要通过 certbot-auto 脚本安装:

wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto

创建证书:

sudo ./path/to/certbot-auto --nginx certonly --webroot -w /www/xxx/ -d xxx.com

但是有可能会出现如下的错误:

Error: Command '['/opt/eff.org/certbot/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1

相关 issue:#5523

运行如下命令:

export LC_ALL=C

再运行生成证书的命令即可,然后再配置对应的 server

#  nginx.conf 的对应 server 进行配置
server {
    server_name  your_domain;

    location / {
        root   /xxx/www/1111/;
        index  index.html index.htm;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

测试自动更新功能:

sudo /path/to/certbot-auto renew --dry-run

如果功能正常,可以在 crontab 里添加计划任务来完成。在 /etc/crontab 文件里添加以下定时任务:

30 5 1 * * root /path/to/certbot-auto renew --renew-hook "/usr/sbin/nginx -s reload"

修改配置之后,运行 nginx -s reload 重新加载配置文件,重新访问配置的域名地址,地址栏前则会有对应的 Secure 标记:

image

相关文章

dwqs commented
  1. 升级到通配符证书可能出现的问题:https://community.letsencrypt.org/t/certbot-the-currently-selected-acme-ca-endpoint-does-not-support-issuing-wildcard-certificates/55667

  2. certbot-auto 升级到 0.22.x,进行 certbot-auto renew --dry-run 可能出现类似如下错误:

An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively

修复方案是运行 certbot-auto renew

  1. certbot renew 的时间问题: https://community.letsencrypt.org/t/renew-says-cert-not-yet-due-for-renewal-though-it-is-more-than-30-days-old/21182/7
dwqs commented

更新证书时,如果 crontab 脚本不生效,或者执行 certbot renew 等出现如下错误时:

The manual plugin is not working; there may be problems with your existing configuration ......
.....
PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',

则需要运行下列命令手动更新

certbot certonly -d *.xxx.com --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory

// 或者
path/to/certbot-auto certonly -d *.xxx.com --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory

链接:Failed authorization procedure via DNS

So, certbot renew is a non-interactive command. The reason it will not run without passing the auth-hook scripts is that Certbot needs to be able to update your TXT records automatically with new challenge values. That is what the hooks are for.

The initial TXT records you created are most likely no longer valid. In the best case, they only authorize you to issue certificates for the domain for 30 days. After that time (or earlier), the value of the challenge changes, and the TXT records must be updated to a new challenge value.

The way you are calling certbot renew does not do this, because your empty scripts are meant to be updating the TXT records, but they do nothing.

If you wish to do the manual DNS challenge again (interactively, rather than non-interactively), then you need to run certbot certonly using the same parameters that you used the first time. certbot renew doesn’t do what you want.

更新完毕之后重新启动服务器

@dwqs 我阿里云配置certbot后可以上https,但是要翻墙才能上,这是什么原因?之前是不用翻墙的,今天发现网站打不开,log里面也没有错,翻墙后就能正常访问了。请问这是什么原因?谢谢

dwqs commented

@Fabriceli 这个我也不是很清楚了 之前我在阿里云上配置的时候 没有出现你的这种情况

你好,我用-d参数配置多个域名合在一个证书中时,浏览器检查是ok的,myssl检查不匹配,我不知道是不是因为我负载均衡的问题,请问你有测试过这样吗

dwqs commented

@Victorkangsh 这个我没测试过

@dwqs 我弄明白了,阿里云slb分默认证书和多域名证书,当把san证书加为多域名证书时,也就是默认证书不是san证书,san证书的非主域名检测会指向默认证书,只有san的主域名是正确指向san证书的。至于普通nginx没有测试,不知道情况

dwqs commented

@Victorkangsh 多谢分享