├── README.md ├── renew.sh └── sslreload_web.sh /README.md: -------------------------------------------------------------------------------- 1 | # auto-ssl-renew 2 | 一个简易的ssl自动更新小脚本,部署只需5分钟。 3 | acme可实现自动修改dns并申请泛域名证书,因此写了这个小脚本,以方便在申请之后分发到每个客户端机器。 4 | 5 | 只有2个文件 6 | ### renew.sh 7 | 用于部署在服务器(或其他任何可以公网访问的机器,比如内网穿透的树莓派或有公网IP的nas),acme申请泛域名证书的示例脚本,只需部署一个实例即可 8 | 9 | ### sslreload_web.sh 10 | 所有需要证书的客户端机器执行该脚本自动拉取并更新证书 11 | 12 | 13 | 14 | # 使用方法 15 | 16 | ## 1. 安装acme脚本 17 | ``` 18 | 因网络问题 中国区安装参考这个 https://github.com/acmesh-official/acme.sh/wiki/Install-in-China 19 | # 建议安装的时候就设置邮箱,后续如果申请lets证书就不用重复设置 20 | git clone https://gitee.com/neilpang/acme.sh.git 21 | cd acme.sh 22 | ./acme.sh --install -m my@example.com 23 | ``` 24 | 25 | ## 2.下载auto-ssl-renew并修改里面的默认配置为你的 26 | ``` 27 | git clone https://github.com/del-xiong/auto-ssl-renew.git && cd auto-ssl-renew 28 | 29 | ``` 30 | 中国区 31 | ``` 32 | git clone https://gitee.com/splot/auto-ssl-renew.git && cd auto-ssl-renew 33 | 34 | ``` 35 | 36 | ### renew 文件配置 37 | renew_ 文件名和路径修改,给文件名添加复杂hash避免泄露路径(这是为了避免部分用户误将该文件部署到web目录被别人下载) 38 | 运行下面的命令进行**初始化** 39 | ``` 40 | 41 | # 初始化 一键运行 直接复制下面的命令回车 42 | rndhash=$(head -64 /dev/urandom |sha256sum|head -c 32) && \ 43 | find sslreload_web.sh -type f -print0 | xargs -0 sed -i "s/RNDHASH=\"\"/RNDHASH=\"${rndhash}\"/g" && \ 44 | mv sslreload_web.sh "sslreload_${rndhash}.sh" && \ 45 | mv renew.sh "renew_${rndhash}.sh" && \ 46 | ls && echo "初始化完毕" && \ 47 | echo "请将 renew_${rndhash}.sh 移动到你的系统目录" && \ 48 | echo "并将 sslreload_${rndhash}.sh 移动到web目录" 49 | ``` 50 | 上面命令的作用是将脚本重命名添加随机值,避免文件名太简单被别人爆破 51 | 52 | renew文件不需要web访问,所以可以放到系统目录 例如/root/renew_*.sh 53 | 54 | 修改renew_*.sh,将里面的示例申请代码移除,**替换为你自己的** 55 | 56 | 修改**OUTPUT变量值**,改为你的web目录的路径,例如 /www/html/sslrenew/ (末尾带斜杠) 57 | 58 | 注意不同解析服务商可能需要设置不同的环境变量,acme支持上百家dns服务商,具体参考 https://github.com/acmesh-official/acme.sh/wiki/dnsapi 59 | 60 | renew文件末尾,申请完毕所有证书后建议将证书文件所有者改为你的web用户组,以避免权限问题导致证书无法拉取 61 | 例如你的web用户组是www 则执行 62 | ``` 63 | chown www:www -R $OUTPUT 64 | ``` 65 | 还有个办法是直接使用web组运行acme,不过这样的话安装acme也需要安装在web用户目录下。 66 | 67 | ### sslreload_web 文件配置 68 | sslreload文件需要修改server_path变量为你的web目录路径例如 https://abc.com/ 69 | 然后直接将文件放到你的web目录确保可访问即可,例如 /www/html/sslrenew/sslreload_web.sh 70 | 71 | 72 | ## 3. 更新证书 73 | 部署计划任务,执行证书自动更新任务,建议每日一次 74 | 例如 通过crond添加计划任务 75 | 假设: 76 | 初始化时你生成的renew路径是 renew_23d02c1ae87f8f898730e41889bdab5f.sh 77 | sslreload路径是 sslreload_23d02c1ae87f8f898730e41889bdab5f.sh 78 | ``` 79 | 0 0 * * * bash /root/renew_23d02c1ae87f8f898730e41889bdab5f.sh 80 | ``` 81 | 默认在证书过期前一个月续期,未过期的会跳过,如果你想强制续期,可以删除~/.acme.sh/目录里对应的域名目录 82 | 83 | ## 4. 客户端如何更新证书 84 | 完成第3步检查证书申请正常后,你的web目录应该就有你的域名证书了,所有需要拉取证书的客户端都可以一行命令直接更新证书,例如 85 | (假如你的证书更新域名是 https://helloworld.com 想更新 openai.com 的证书 ) 86 | ``` 87 | curl https://abc.com/sslreload_23d02c1ae87f8f898730e41889bdab5f.sh -k|bash -s openai.com /www/ssl 'nginx force-reload'; 88 | 89 | ``` 90 | sslreload_web -s 参数解释 91 | openai.com: 你要拉去证书的域名 92 | /www/ssl/: 证书拉取成功后要放置到目录 /www/ssl 93 | 'nginx force-reload': 证书更新成功后你想执行的命令例如 强制reload下nginx 94 | 95 | 如果你看到如下消息,那说明就成功了 96 | ``` 97 | 下载域名证书成功 98 | key文件路径 /www/ssl/all.openai.com.key 99 | cert文件路径 /www/ssl/all.openai.com.cert 100 | 开始执行命令 '/etc/init.d/nginx force-reload' 101 | Reload service nginx... done 102 | ``` 103 | 104 | **Enjoy!** 105 | 106 | ## 5. 附录,如果想隐藏证书路径的建议 107 | 在上面的证书申请中,证书路径中包含了一个RNDHASH的随机值,从而避免了被外人爆破的风险,但仍可能存在内部泄露的风险,例如考虑一种这样的情况: 108 | - 你是某个小团队中的一员,使用脚本自动更新某个项目证书,其他团队成员也可能看到你的证书更新命令,那么他如果恰好知道你的其他域名,就存在遍历你的证书路径来下载证书的风险。 109 | 110 | 为了解决这个问题,你可以对部分证书设置不一样的命名方式,例如查看renew文件中的suffix="cf77713322c2463bf"下面的命令,我在申请这个域名的时候额外赋予了一个随机hash值,这样其他用户在不知道这个hash的情况下很难通过遍历的方式下载到你的证书。(因为renew文件对外部不可见) 111 | 112 | 同样的,拉取命令也需要指定这个hash参数(第4个参数) 113 | 114 | 上面的命令就需要变为 115 | ``` 116 | curl https://abc.com/sslreload_23d02c1ae87f8f898730e41889bdab5f.sh -k|bash -s openai.com /www/ssl 'nginx force-reload' cf77713322c2463bf; 117 | ``` -------------------------------------------------------------------------------- /renew.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | # 默认文件随机值 避免爆破 5 | RNDHASH=$(basename -- "$0") 6 | RNDHASH=${RNDHASH#*_} 7 | RNDHASH=${RNDHASH%.*} 8 | # 修改dns后等待多少秒 9 | DNSSLEEP="120" 10 | # 证书生成后的存放位置 11 | OUTPUT="/www/html/" 12 | 13 | 14 | # 默认使用zerossl 参考 https://github.com/acmesh-official/acme.sh/wiki/Change-default-CA-to-ZeroSSL 15 | ~/.acme.sh/acme.sh --set-default-ca --server zerossl 16 | # 申请lets证书 ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt 17 | 18 | # 阿里解析申请示例 登录阿里云创建子密钥并授权 19 | export Ali_Key="" 20 | export Ali_Secret="" 21 | domains=("example.com" "example.net") 22 | for item in ${domains[*]} 23 | do 24 | echo "开始检查域名【$item】" 25 | ~/.acme.sh/acme.sh --issue --dns dns_ali -d $item -d "*.${item}" --dnssleep $DNSSLEEP --fullchain-file "${OUTPUT}all${RNDHASH}.${item}.cert" --key-file "${OUTPUT}all${RNDHASH}.${item}.key" 26 | done 27 | 28 | 29 | # dnspod申请示例 登录 https://console.dnspod.cn/account/token/token 创建token 30 | export DP_Id="" 31 | export DP_Key="" 32 | domains=("example.com" "example.net") 33 | for item in ${domains[*]} 34 | do 35 | echo "开始检查域名【$item】" 36 | ~/.acme.sh/acme.sh --issue --dns dns_dp -d $item -d "*.${item}" --dnssleep $DNSSLEEP --fullchain-file "${OUTPUT}all${RNDHASH}.${item}.cert" --key-file "${OUTPUT}all${RNDHASH}.${item}.key" 37 | done 38 | 39 | # he.net申请示例 勾选域名记录的Enable entry for dynamic dns,然后为该记录创建一条动态更新key即可 40 | export HE_Username="" 41 | export HE_Password="" 42 | domains=("example.com" "example.net") 43 | suffix="cf77713322c2463bf" 44 | for item in ${domains[*]} 45 | do 46 | echo "开始检查域名【$item】" 47 | ~/.acme.sh/acme.sh --issue --dns dns_he -d $item -d "*.${item}" --dnssleep $DNSSLEEP --fullchain-file "${OUTPUT}all${RNDHASH}.${item}.${suffix}.cert" --key-file "${OUTPUT}all${RNDHASH}.${item}.${suffix}.key" 48 | done 49 | 50 | # cloudflare申请示例 需要去官网登录获取token和账户ID email 51 | domains=("example.com" "example.net") 52 | export CF_Token="" 53 | export CF_Email="" 54 | export CF_Account_ID="" 55 | suffix="" 56 | for item in ${domains[*]} 57 | do 58 | echo "开始检查域名【$item】" 59 | ~/.acme.sh/acme.sh --issue --dns dns_cf -d $item -d "*.${item}" --dnssleep $DNSSLEEP --fullchain-file "${OUTPUT}all${RNDHASH}.${item}.${suffix}.cert" --key-file "${OUTPUT}all${RNDHASH}.${item}.${suffix}.key" 60 | done 61 | 62 | # 如果要给web服务读取,建议授权一下web用户组 63 | # chown www:www -R $OUTPUT 64 | 65 | -------------------------------------------------------------------------------- /sslreload_web.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RNDHASH="" 4 | 5 | 6 | if [ ! -n "$3" ]; then 7 | echo "参数不正确 格式为 sslreload.sh [根域名] [证书保存路径] [完成后执行命令]" 8 | echo "例如 sh sslreload.sh katamao.com /www/server/panel/ssl/ \"bt reload\"" 9 | exit 10 | fi 11 | 12 | server_path="" 13 | if [[ -z "$server_path" ]]; then 14 | echo "sslreload的server_path未设置,请设置为你的证书拉取路径再重试" 15 | exit 16 | fi 17 | begin_str="\-\-BEGIN" 18 | echo "开始下载域名证书 【${1}】" 19 | # 如果定义了suffix参数 20 | if [ -n "$4" ]; then 21 | curl -o acme-renew.key -k "${server_path}all${RNDHASH}.$1.$4.key" 22 | curl -o acme-renew.cert -k "${server_path}all${RNDHASH}.$1.$4.cert" 23 | else 24 | curl -o acme-renew.key -k "${server_path}all${RNDHASH}.$1.key" 25 | curl -o acme-renew.cert -k "${server_path}all${RNDHASH}.$1.cert" 26 | fi 27 | 28 | if cat acme-renew.key | grep $begin_str > /dev/null && cat acme-renew.cert | grep $begin_str > /dev/null; then 29 | if mv acme-renew.key "${2}/all.${1}.key" && mv acme-renew.cert "${2}/all${RNDHASH}.${1}.cert" ; then 30 | echo "下载域名证书成功" 31 | echo "key文件路径 ${2}/all.${1}.key" 32 | echo "cert文件路径 ${2}/all.${1}.cert" 33 | echo "开始执行命令 '${3}'" 34 | $3 35 | else 36 | echo "复制证书时失败 请确认目录正确" 37 | fi 38 | else 39 | echo "下载证书失败,请确认网络和服务器(${server_path})正常以及域名(${1})正确无误" 40 | fi 41 | rm -rf acme-renew.key 42 | rm -rf acme-renew.cert --------------------------------------------------------------------------------