osnosn

  博客园 :: 首页 :: 博问 :: 闪存 :: :: 联系 :: 订阅 订阅 :: 管理 ::

去freessl.org申请免费ssl服务器证书_acme.sh脚本_证书自动化_LetsEncrypt

来源: 本文链接 来自osnosn的博客
写于: 2019-03-30.

以下是正文。
访问 freessl.org,它会跳到 freessl.cn,这两站是一样的:


填入你要申请的域名,比如test.org,选择一个免费产品。(我为了偷懒,选了个最长的,一年)



填入你的邮箱,平时没什么用。证书快到期了,会发封邮件提醒你。

  • 会在到期前30天,7天,0天,发邮件给你。(2020-12)

选择证书类型:

  • RSA,传统算法。优点,支持好,老的客户端也支持。缺点,2048以下的都不算安全。密钥比较大,加密计算慢点(对比ECC)。
  • ECC,新算法,椭圆曲线。优点,密钥小,计算快。缺点,老客户端可能不支持。不过这年头,没什么老客户端了。

选择验证类型:

  • DNS,要把验证字符串,写入指定域名的TXT记录。
    • 现在改用 CNAME 记录来验证了。(2022-07)
  • 文件验证,把验证字符串,写入你的web服务器的,指定的路径的,文件中。

CSR生成:

  • 离线生成,你的浏览器需要装个插件(KeyManager 1.2.14以上版本),我没装,所以没用过。
  • 浏览器生成,edge,chrome,safari,ie11,都支持。唯独Firefox不支持。其他版本的ie,我不知道。但ie6肯定不支持。
  • 我有CSR,自己用openssl生成一个证书请求,上传给它。这个请求有什么要求,不清楚,没试过。

"点击创建",不会跳出新页面。下拉当前页面,在底下。



如果你选择DNS验证,就是这个页面。
就是给域名 _dnsauth.test.org 创建一个TXT记录。
用linux命令 dig _dnsauth.test.org txt 能显示那个验证字符串。
如何设置DNS的TXT记录,可以参考别人的文章
配置好TXT记录之后,可能生效需要一点时间(好几分钟)。不要着急点中间的"点击验证",先点页面右下角的"配置完成,检测一下"
因为,"检测一下" 可以多次检测。中间的"点击验证" 失败的话,似乎又要重头搞一遍。



验证结果,不需要全绿,只要有一个绿的(匹配),你就可以去点之前那个页面中间的"点击验证",生成证书了。




如果你选择文件验证,就是这个页面。
去你的网站,按照要求建立目录,文件,然后把验证字符串写入文件fileauth.txt中。
图片中的例子中,文件路径是 /.well-known/pki-validation/fileauth.txt,第一个目录是开头。
你的网站可以是运行在80口(http),
也可以是运行在443口(https),先自己搞个自签名证书用着 ,不影响验证。
网站运行在其他非标准端口的,验证不支持
验证前,可以自己用浏览器访问一下,看能否成功。



同样,"检测一下"的页面,只要有一行绿的(匹配),就OK。你就可以去点击"点击验证",去生成证书了。

最终,你会得到三个内容(PEM格式),CA证书服务器证书服务器密钥
你可以把它们分别保存为三个文本文件: ca.pem , server.pem, private.key
"下载证书" 会得到一个 full_chain.pem,其实就是 server.pem+ca.pem,server在上(前),ca在下(后)。

如需要,参考以下证书格式转换的指令:

查看/打印 pem 证书
openssl x509 -in ca.pem -text -noout
openssl x509 -in server.pem -text -noout
把 pem 转为 der 格式,(证书,密钥)
openssl x509 -outform der -in server.pem -out server.cer 服务器证书。
openssl rsa -in private.key -outform der -out server_key.cer 服务器密钥。
把 pem 转为 P12 格式(pfx),(证书,密钥),友好名称不支持utf8中文
openssl pkcs12 -export -out server.p12 -inkey private.key -in serverpem -certfile ca.pem -caname"ca friendly name" -name "friendly name"
把 p12 转 jks,
用java的 keytool 工具转换/导入
把 pem 转 pkcs#7 格式,(证书)
openssl crl2pkcs7 -nocrl -certfile server_cert.pem -out server.p7b

至于怎么配置到你的web站上(apache,nginx,iis,tomcat,...),不在本文范围。请自行搜索。

freessl.org 官网上有"常见问题"的链接,各种说明比较详细。

如果你的证书暂时不能成功验证,可以登陆之后找到未验证成功的订单。
现在注册登录,需要手机号短信验证了。(2020-12)
其中TrustAsia的订单有效期为1天,Let‘s Encrypt的订单有效期为30分钟


脚本更新证书

acme.sh

  • 以下内容,于 2023-08 记录。
  • acme.sh 是个 shell 脚本。在 2023-08 这个时间点来看,acme.sh 功能更多,建议装这个用。
  • acme.sh 脚本的安装,使用,网上有很多文章。很容易搜到。
    装好后,在当前用户的 crontab中会自动加入 30 0 * * * acme.sh --cron ... 的计划任务。
  • 第一次部署acme.sh,很容易出错而重复申请,导致超出限制 申请失败。
    letsencrypt提供了测试服务,基本无限制,方便用于测试。
    --test 代替 --server letsencrypt 即可。
    acme.sh 执行 --renew 或 --cron 时,也要带上 --test 参数,否则就不是测试服务。

    比如:
    ./acme.sh --issue -d mydns.dns -d *.mydns.dns --days 80 --dns dns_ali --test -k ec-256
    ./acme.sh --renew -d xxx.ddns.ddns --test
    
    等测试OK,成功获取证书,再改回来就行了。
  • 样例: 用阿里dns认证,申请 Letsencrpyt的3个月的泛域名证书,80天后再更新,更新成功 reload nginx。
    用于 Linux,如: debian,centos ...
    • 第一次执行 "--issue"之前要提供 阿里的密钥。
      export Ali_Key=xxxxxx
      export Ali_Secret=xxxxxx
      
      会被自动保存在 account.conf 中,SAVED_Ali_Key=xxxSAVED_Ali_Secret=xxx
      后续的执行无需提供 密钥了。
    • ec-256,创建或覆盖已有配置。
      ./acme.sh --issue -d mydns.dns -d *.mydns.dns --days 80 --dns dns_ali --server letsencrypt -k ec-256 --reloadcmd '/sbin/service nginx reload'
      
    • rsa 4096,创建或覆盖已有配置。
      ./acme.sh --issue -d mydns.dns -d *.mydns.dns --days 80 --dns dns_ali --server letsencrypt -k 4096 --reloadcmd '/sbin/service nginx reload'
      
  • 可以直接修改配置文件。在 acme 的home 目录中 (通常是"~/.acme.sh/"),
    修改文件 "mydns.dns/mydns.dns.conf" 或 "mydns.dns_ecc/mydns.dns.conf"。
    Le_Keylength='ec-256'
    Le_RenewalDays='80'
    # 内容为: /sbin/service nginx reload
    Le_ReloadCmd='__ACME_BASE64__START_L3NiaW4vc2VydmljZSBuZ2lueCByZWxvYWQ=__ACME_BASE64__END_'
    
  • Letsencrypt: 证书有效期通常是 90天。
    不指定 "--days",默认,证书生效后60天,更新 新证书。
  • Letsencrypt: 在168 hours(1 week)内,同一域名,限制申请/更新证书5次。超过,就更新失败。
  • 有时会因为 https://acme-v02.api.letsencrypt.org 无法访问(被封) 而导致更新失败。
    因为使用的是curl,可以创建 "~/.curlrc" 配置代理,再试试。
    或指定 "--use-wget" 参数,用 "~/.wgetrc" 配置代理。
  • 支持的 DNS 提供商:【How to use DNS API
    如: Aliyun,CloudFlare, dynv6, ...
  • 支持的 CA 提供商:【Supported CA
    用 "--server" 指定不同的 CA 提供商。
    如: Letsencrypt, ZeroSSL, Freessl, ...

certbot

freessl 自动化

  • freessl 推荐用 acme,也支持 certbot
  • ACME v2证书自动化快速入门
    在Debian12,完全按照这个教程,安装github版acme,v3.0.7,手工设置好域名和cname,DCV验证通过。
    始终保留cname的记录,(否则acme.sh脚本会报 dns 验证不通过).
    执行 "acme.sh --issue ..." 显示 Verify finished, start to sign.
    然后一直循环,
    Order status is processing, lets sleep and retry.
    Retry after: 15
    
    9分钟后 Sign failed, can not get Le_LinkCert, retry time limit.
    (配置acme自动化失败。2023-08测)
  • 马上用acme去申请一个 letsencrypt 的证书,非常顺利,没有错误。
    所以,怀疑是 freessl 本身的问题。2023-08测
  • 隔了两天之后,执行 "acme.sh --issue ..." 申请freessl的证书,跳了两次Retry after: 15后,证书申请成功。
    证书有效期 90天。签发者是 O=TrustAsia Technologies
    • 再申请另一个域名的证书,freessl又进入 Retry 15的循环,直至失败。
      失败后,再试。重新执行了6次,居然申请成功了。很无语。
  • 看来 freessl自动化 没什么优势,又很不稳定。很不好用。
    freessl 网页版,手工申请一年期的证书,还算稳定。
  • acme.sh只能获得90天的证书。一年期证书只能在web端手工申请。
    freessl的acme.sh方式不支持多域名,仅支持单域名。申请ecc证书,对应的CA也是ecc证书。

Letsencrypt 自动化

  • 2023-08 测试并记录。
  • 安装github版acme.sh,v3.0.7,
    装好后,在当前用户的 crontab中会自动加入 30 0 * * * acme.sh --cron ... 的计划任务。
  • 第一次部署acme.sh,很容易出错而重复申请,导致超出限制 申请失败。
    letsencrypt提供了测试服务,基本无限制,方便用于测试。
    --test 代替 --server letsencrypt 即可。
    acme.sh 执行 --renew 或 --cron 时,也要带上 --test 参数,否则就不是测试服务。

    用测试服务获取的证书,用的是测试CA,不被信任。不能使用。
    比如:
    ./acme.sh --issue -d xxx.ddns.ddns --days 80 --dns dns_?? -k ec-256 --test
    ./acme.sh --renew -d xxx.ddns.ddns --test
    
  • 申请一个单域名ecc证书。
    export TOKEN=xxxxxx  #对应的 dns_?? 需要的密钥
    ./acme.sh --issue -d xxx.ddns.ddns --days 80 --dns dns_?? -k ec-256 --server letsencrypt
    
    第一次执行,会自动去 letsencrypt 用你提供的邮箱,注册一个账号,保存在 "ca/acme-v02.api.letsencrypt.org/" 目录中。后续的执行就会使用这个 letsencrypt 账号。
    第一次执行,会把你提供的 TOKEN 保存在 account.conf 中,例如SAVED_TOKEN=xxxx,后续的执行无需提供 TOKEN。
    letsencrypt 会在证书到期前20天,发邮件到你的邮箱,提醒你的证书还剩20天。
  • 注意,如果申请的域名,之前在freessl中操作过,需要删除 _acme-challenge 的 cname记录。
    因为,letsencrypt 需要创建同名的 txt 记录用于 dns 验证。不删除 cname,会导致 创建 同名的 txt失败。
  • 大约 2min 就可以获取签署好的证书了。证书有效期 90天。
    还是 letsencrypt 的稳定,好用。
  • letsencrypt的acme.sh支持范域名。申请ecc证书,对应的CA也是ecc证书。
  • 如果想 吊销这个证书。
    ./acme.sh --revoke -d xxx.ddns.ddns --ecc
  • 如果想 删除这个域名的申请。
    ./acme.sh --remove -d xxx.ddns.ddns --ecc
    然后 rm -rf xxx.ddns.ddns_ecc 删除对应目录。
  • 下面几条 注册/更新/注销 账号的命令。不常用。
  • 更新账号信息。如果不指定 --server,默认是 zerossl。
    ./acme.sh --update-account --server letsencrypt
  • 注销账号。如果不指定 --server,默认是 zerossl。
    ./acme.sh --deactivate-account --server letsencrypt
  • 重新注册账号。如果不指定 --server,默认是 zerossl。
    先删除之前注销的账号,rm -rf ca/acme-v02.api.letsencrypt.org
    如果不删除,会因为原 account.key 已经被注销,而无法重新注册。
    然后 ./acme.sh --register-account --server letsencrypt -m <email>
  • 安装证书,可以用 --install-cert ... --reloadcmd ...安装,
    执行后,证书的安装路径会被自动保存。reloadcmd 命令也会被自动保存。
    当执行 acme.sh --cron ... 时,会自动安装证书到目标路径,并执行 reloadcmd。
  • 另一个办法。高级用法。不执行 --install-cert ...
    在执行--issue的同时,指定--post-hook /pathto/mypost.sh --renew-hook /pathto/myrenew.sh
    #完整的例子, 泛域名, 80天再更新.
    ./acme.sh --issue -d xxx.ddns.ddns -d '*.xxx.ddns.ddns' --days 80 --dns dns_?? -k ec-256 --server letsencrypt --post-hook /pathto/mypost.sh --renew-hook /pathto/myrenew.sh
    
    (注: mypost.sh 和 myrenew.sh 需要设置执行权限,即 "chmod +x ...")
    mypost.sh 会在 issue完成后,被执行一次,myrenew.sh不会被执行。
    • 今后,执行 --renew--cron 结束后,会执行 mypost.sh。
      如果成功获取到证书,还会执行 myrenew.sh。
      • 如果成功获取到证书,脚本mypost.sh, myrenew.sh 执行中,会有以下几个环境变量可用。
      CA_CERT_PATH=/绝对路径/my.ddns.ddns_ecc/ca.cer
      CERT_FULLCHAIN_PATH=/绝对路径/my.ddns.ddns_ecc/fullchain.cer
      CERT_KEY_PATH=/绝对路径/my.ddns.ddns_ecc/my.ddns.ddns.key
      CERT_PATH=/绝对路径/my.ddns.ddns_ecc/my.ddns.ddns.cer
      DOMAIN_PATH=/绝对路径/my.ddns.ddns_ecc
      Le_Domain=my.ddns.ddns     # 更新的域名
      Le_Next_Domain_Key=/绝对路径/my.ddns.ddns_ecc/my.ddns.ddns.key.next
      PWD=/绝对路径/my.ddns.ddns_ecc  # 执行脚本时的当前目录
      
      • 如果获取证书失败,脚本myrenew.sh 不会执行。
        如果获取证书失败,脚本mypost.sh 执行中,会有以下几个环境变量可用。
      DOMAIN_PATH=/绝对路径/my.ddns.ddns_ecc
      Le_Next_Domain_Key=/绝对路径/my.ddns.ddns_ecc/my.ddns.ddns.key.next
      PWD=/绝对路径/my.ddns.ddns_ecc  # 执行脚本时的当前目录
      
      • 无论是否成功,脚本mypost.sh 执行中; 成功后,脚本myrenew.sh 执行中,还会有以下几个环境变量可用。
      ACCOUNT_JSON_PATH=/home/...
      ACCOUNT_KEY_PATH=/home/...
      ACME_AGREEMENT=https://...
      ACME_DIRECTORY=https://...
      ACME_KEY_CHANGE=https://...
      ACME_NEW_ACCOUNT=https://...
      ACME_NEW_NONCE=https://...
      ACME_NEW_ORDER=https://...
      ACME_REVOKE_CERT=https://...
      CA_CONF=/home/...
      LE_CONFIG_HOME=/home/...  # .acme.sh 安装目录
      LE_WORKING_DIR=/home/...  # .acme.sh 的工作目录, 通常=LE_CONFIG_HOME
      _SCRIPT_HOME=/home/...    # mypost.sh 所在的目录
      
    • 如果用了--pre-hook mypre.sh,脚本执行时,有以下几个环境变量可用。
      Le_Domain=my.ddns.ddns
      Le_Alt=*.my.ddns.ddns
      DOMAIN_PATH=/绝对路径/my.ddns.ddns_ecc
      PWD=/绝对路径/my.ddns.ddns_ecc
      
    • mypost.sh 的例子
      #!/usr/bin/bash
      log_path=/home/myuser/.acme.sh/log.hook
      br='\n'
      if [ -z "$CA_CERT_PATH" -o  -z "$CERT_FULLCHAIN_PATH" -o  -z "$CERT_KEY_PATH" -o  -z "$CERT_PATH" ]; then
         #证书获取失败
         if [ -z "$DOMAIN_PATH" ]; then
            send_msg="脚本执行错误, SSL证书申请失败"
         else
            _domain=$(basename $DOMAIN_PATH)
            _domain=${_domain%_ecc}  #去掉结尾的 _ecc
            echo $_domain
            send_msg="SSL证书申请失败,${_domain}"
         fi
      else
         #证书获取成功
         send_msg="SSL证书申请成功,${Le_Domain}"
      fi
      # 发送通知
      echo $send_msg >> ${log_path}
      #../Send_msg.py --to myemail@xxx.xxx --info "${send_msg}" --send >> ${log_path}
      exit 0
      
      # 如果成功
      #CA_CERT_PATH=/home/myuser/.acme.sh/ddns2.xx.xx_ecc/ca.cer
      #CERT_FULLCHAIN_PATH=/home/myuser/.acme.sh/ddns2.xx.xx_ecc/fullchain.cer
      #CERT_KEY_PATH=/home/myuser/.acme.sh/ddns2.xx.xx_ecc/ddns2.xx.xx.key
      #CERT_PATH=/home/myuser/.acme.sh/ddns2.xx.xx_ecc/ddns2.xx.xx.cer
      #DOMAIN_PATH=/home/myuser/.acme.sh/ddns2.xx.xx_ecc
      #Le_Domain=ddns2.xx.xx
      #PWD=/home/myuser/.acme.sh/ddns2.xx.xx_ecc
      # 如果err
      #DOMAIN_PATH=/home/myuser/.acme.sh/ddns2.xx.xx_ecc
      #PWD=/home/myuser/.acme.sh/ddns2.xx.xx_ecc
      
    • myrenew.sh 的例子
      #!/usr/bin/bash
      log_path=/home/myuser/.acme.sh/log.hook
      reload_and_notify(){
         ddns="$1"
         br='\n'
         sudo /usr/sbin/service nginx reload
         retcode=$?
         if [ $retcode -eq 0 ];then
            send_msg="SSL证书已更新,${ddns}${br}nginx reload 成功"
         else
            send_msg="SSL证书已更新,${ddns}${br}nginx reload 失败:${retcode}"
         fi
         #发送通知
         echo $send_msg >> ${log_path}
         #../Send_msg.py --to myemail@xxx.xxx --info "${send_msg}" --send >> ${log_path}
      }
      
      if [ "$Le_Domain" = "ddns2.xx.xx" ]; then
         #注意目标文件的权限设置
         /usr/bin/cp -f "$CERT_KEY_PATH" /etc/nginx/freessl/${Le_Domain}.key
         /usr/bin/cp -f "$CERT_FULLCHAIN_PATH" /etc/nginx/freessl/${Le_Domain}.pem
         reload_and_notify "${Le_Domain}"
      fi
      if [ "$Le_Domain" = "ddns3.yy.yy" ]; then
         #如果nginx在远程服务器上,可以用 expect 解决,需要"apt install expect"
         expect -c "
           spawn scp -q -i ed25519_key \"$CERT_KEY_PATH\" remotehost:freessl/${Le_Domain}.key
           expect {
            \"Enter passphrase for key\" { send \"keypass\r\"; }
           }
           expect eof
         "  >> ${log_path}
         expect -c "
           spawn scp -q -i ed25519_key \"$CERT_FULLCHAIN_PATH\" remotehost:freessl/${Le_Domain}.pem
           expect {
            \"Enter passphrase for key\" { send \"keypass\r\"; }
           }
           expect eof
         "  >> ${log_path}
         #执行远程服务器上的脚本reload_and_notify.sh;这个脚本需要自己写。
         expect -c "
           spawn ssh -i ed25519_key remotehost freessl/reload_and_notify.sh ${Le_Domain}
           expect {
            \"Enter passphrase for key\" { send \"keypass\r\"; }
           }
           expect eof
         "  >> ${log_path}
      fi
      
      exit 0
      # 如果成功
      #CA_CERT_PATH=/home/myuser/.acme.sh/ddns3.yy.yy_ecc/ca.cer
      #CERT_FULLCHAIN_PATH=/home/myuser/.acme.sh/ddns3.yy.yy_ecc/fullchain.cer
      #CERT_KEY_PATH=/home/myuser/.acme.sh/ddns3.yy.yy_ecc/ddns3.yy.yy.key
      #CERT_PATH=/home/myuser/.acme.sh/ddns3.yy.yy_ecc/ddns3.yy.yy.cer
      #DOMAIN_PATH=/home/myuser/.acme.sh/ddns3.yy.yy_ecc
      #Le_Domain=ddns3.yy.yy
      #PWD=/home/myuser/.acme.sh/ddns3.yy.yy_ecc
      
      脚本需要的权限,
      chgrp myuser /etc/nginx/freessl/ddns2.xx.xx.key
      chmod g+rw /etc/nginx/freessl/ddns2.xx.xx.key
      chgrp myuser /etc/nginx/freessl/ddns2.xx.xx.pem
      chmod g+rw /etc/nginx/freessl/ddns2.xx.xx.pem
      
      脚本需要的权限, visudo,加一行 myuser ALL=(root) NOPASSWD:/usr/sbin/service nginx reload
      其中 myuser 为执行脚本的普通用户的用户名

ZeroSSL 自动化

  • 可以获取 90天的双域名证书。支持泛域名。
  • 无更新频率限制。
  • 参考【ZeroSSL.com-CA】。

BuyPass.com 自动化

  • 2023-10 测试并记录。
  • 安装github版acme.sh,v3.0.7,
  • 可以获取 180天的双域名证书。不支持泛域名。(泛域名要付费)。180天证书测试OK。泛域名没测试。
  • 单个证书中,最多可加到 5个域名。
  • 可以申请ecc证书,但对应的CA是rsa4096证书。
  • 参考【BuyPass.com-CA】。

acme.sh 支持的 CA

其他CA自动化

转载请注明来源。
来源: 本文链接 https://www.cnblogs.com/osnosn/p/10627969.html 来自osnosn的博客
-------------end----------------

posted on 2019-03-30 18:38  osnosn  阅读(5831)  评论(0编辑  收藏  举报