zoukankan      html  css  js  c++  java
  • SSL证书的申请、自动续期与常见问题

    背景

    网络上已经有很多关于Let's encrypt免费申请证书的文章,但是基本只谈最基础用法,立刻用起来是没问题了。但是在实际使用中,碰到了一些问题则比较头疼。整理以后,大概出在以下几个方面:

    • 单域名和泛域名的申请方式上有区别;
    • 单域名和泛域名的证书如何自动续期;
    • 如果提前验证自动续期是正常的;
    • 选择文件验证还是DNS验证;
    • 如何与docker有效配合;

    本文的价值在于阐述了解决这些问题的具体思路。

    安装工具

    申请Let's encrypt证书,既可以使用certbot官方工具,也可以使用acme.sh第三方工具,各有各的好处,主要看偏好,本文使用certbot演示。

    安装指南 :直接进《certbot官方安装指南》,选择nginx和自己的操作系统,就会生成对应的安装指南。

    文件验证与DNS验证

    在给域名申请证书时,Let's encrypt需要先验证你有对域名的控制权。这个验证方式有2种:文件验证和DNS验证。

    文件验证的原理是在你的网站下面放一个验证文件(/.well-known/acme-challenge/目录下),certbot通过域名直接访问到这个验证文件,能访问到说明是你的网站,也就可以申请证书。

    DNS验证的原理是你需要创建一条TXT的记录,设置指定值,certbot检查到这条记录就完成验证。

    两种方式各有其适用场景,对于自己可以控制的域名,直接通过DNS验证是最便捷的,不需要任何nginx的辅助就可以完成申请和续期。但是很多时候,我们是给客户提供服务,并没有域名的控制权,就只能使用文件验证的方式。假如使用了DNS的验证方式,客户首次申请是要手动改DNS记录,等到过期后,也不能自动续期,需要再次手动调整DNS记录。

    为保证域名正常续期,本文的单域名证书的申请上,使用的是文件验证的方式。

    单域名证书的申请与自动续期

    申请证书

    对于单域名,我们统一使用文件验证的方式,因此要先写好nginx的配置文件:

    server {
        listen 80;
        server_name www.papamk.com;
        root /var/www/html;
    
        server_tokens off;
        location /.well-known/acme-challenge/ {
            root /var/www/html;
            access_log off;
        }
    
       return 301 https://www.papamk.com$request_uri;
    }
    

    访问curl http://www.papamk.com将会返回如下结果:

    <html>
    <head><title>301 Moved Permanently</title></head>
    <body bgcolor="white">
    <center><h1>301 Moved Permanently</h1></center>
    <hr><center>nginx</center>
    </body>
    </html>
    

    接着开始申请证书:

    certbot  certonly --webroot -w /var/www/html -d www.papamk.com
    

    编辑nginx配置文件,给HTTPS增加证书的相关配置,重点是以下2名:

        ssl_certificate /etc/letsencrypt/live/www.papamk.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/www.papamk.com/privkey.pem;
    

    完整的nginx配置如下:

    server {   
        listen 443 ssl;
        server_name www.papamk.com;
    
        root /var/www/html;
        index index.php index.html index.htm;
        
        access_log /dev/stdout;
        error_log /dev/stderr;
        
        ssl_certificate /etc/letsencrypt/live/portfolia.papamk.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/portfolia.papamk.com/privkey.pem;
    
        location / {
            try_files $uri $uri/ /index.php$is_args$args;
        }
    
        location ~ .php$ {
            internal;
            try_files $uri /index.php =404;
            fastcgi_intercept_errors on;
            fastcgi_pass php-fpm:9000;
            fastcgi_index index.php;
            fastcgi_buffers 16 16k;
            fastcgi_buffer_size 32k;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    }
    

    以上配置使用php作为示例。

    更新证书与自动续期

    certbot renew --deploy-hook 'nginx -s reload'
    

    当证书在30天内过期时,就会自动更新,更新成功会重新加载nginx

    放在crontab中,每天凌晨1点更新。

    0 1 * * * certbot renew --deploy-hook 'nginx -s reload'
    

    泛域名证书的申请与自动续期

    泛域名证书只支持DNS验证的方式,所以如果不能直接修改DNS记录,泛域名证书过期后就会需要手动更新。要解决这个问题,需要使用对应的DNS插件,国外的主流DNS插件都有内置支持,如果是国内。我基本都使用阿里云,官方certbot没有对应的DNS插件,但是第三方有,传送门:

    https://github.com/tengattack/certbot-dns-aliyun

    安装certbot阿里云dns插件

    pip install certbot-dns-aliyun
    

    创建aliyun.ini,写入授权信息(授权账号需要有AliyunDNSFullAccess)

    certbot_dns_aliyun:dns_aliyun_access_key = 12345678
    certbot_dns_aliyun:dns_aliyun_access_key_secret = 1234567890abcdef1234567890abcdef
    

    修改下权限:

    chmod 600 aliyun.ini
    

    接下来就可以开始使用了。

    申请证书

    certbot certonly -a certbot-dns-aliyun:dns-aliyun --certbot-dns-aliyun:dns-aliyun-credentials aliyun.ini -d '*.yourdomain.com' --server https://acme-v02.api.letsencrypt.org/directory
    

    更新证书与自动续期

    certbot renew -a certbot-dns-aliyun:dns-aliyun --certbot-dns-aliyun:dns-aliyun-credentials aliyun.ini  --server https://acme-v02.api.letsencrypt.org/directory  --deploy-hook 'nginx -s reload'
    

    放到crontab每天自动检查:

    0 1 * * * certbot renew -a certbot-dns-aliyun:dns-aliyun --certbot-dns-aliyun:dns-aliyun-credentials aliyun.ini  --server https://acme-v02.api.letsencrypt.org/directory  --deploy-hook 'nginx -s reload'
    

    这里的每天检查与单域名的每日检查2选1即可。

    常见问题

    证书存放位置?

    证书一般存放在如下路径:/etc/letsencrypt/live/
    每个域名一个文件夹,可以看到www.yourdomain.com的目录。

    如何提前验证自动续期后可以重新加载nginx?

    先进浏览器,看下当前证书的过期时间,然后执行强制更新:

    certbot renew --force-renew --deploy-hook 'nginx -s reload'
    

    再次进浏览器,查看当前证书的过期时间,如果日期有变,说明nginx重新加载了。

    如何保证过期前证书就得到更新?

    certbot renew会对30天以内的证书更新,只要保证cron有执行每天定时更新一次就没问题。第一次使用时,证书在30以内要注意下这个问题,确保它们得到了更新。

    域名解析到内网,申请证书不成功?

    根据文件验证的原理,certbot无法访问到你的内网,也就验证不通过。使用DNS验证可以申请成功。

    Docker镜像的nginx如何获取证书与更新?

    在许多文章中,都是通过volume将主机的/etc/letsencrypt挂载到容器中,但是在生产环境时,由于应用变成了有状态应用,这种方式有很大的局限性。从A机器迁移到B机器时,将会立刻报错,必须手动解决完证书问题。推荐的做法是将证书做成动态获取的,具体来说要考虑以下2个方面:

    1. 有证书管理中心时(比如vault),nginx镜像在启动的时候,从vault获取证书。如果获取不到,但是证书又是必要的,就生成证书,同步到vault,以便镜像重启时可以获取。这个方案的技术细节可参考该文:https://developer.epages.com/blog/tech-stories/managing-lets-encrypt-certificates-in-vault/
    2. 没有证书管理中心,直接动态生成,具体看下这个镜像,它就是这么做的: https://github.com/SteveLTN/https-portal

    这些处理完全可以做成一个新的nginx镜像以便重复使用。具体的镜像如何处理将另开文章讨论。

    安装certbot阿里云DNS插件出错?

    pip install certbot-dns-aliyun
    

    执行上面命令时报出下面的错误:

    'extras_require' must be a dictionary whose values are strings or lists of strings containing valid project/version requirement specifiers. #1268

    解决方法:

    pip install --user --upgrade setuptools
    

    参考

  • 相关阅读:
    数据算法之汉诺塔
    Mvc模板页
    mvc局部视图
    Area区域
    mvc之文件下载
    MVC过滤器
    MVC_Ajax请求
    MVC之校验
    Json&Razor&控制器
    抓包分析,tcpdump 和 wireshark 配合使用的简单尝试
  • 原文地址:https://www.cnblogs.com/pheye/p/13021420.html
Copyright © 2011-2022 走看看