Let's Encrypt为了推广HTTPS的普及,提供了免费证书,麻烦的是每三个月就到期,需要重新续签一下。重新续签有两种途径
- 自动续签
- 手动续签
自动续签与国际通用的DNS提供商有较好的合作支持,但对于国内比如Dnspod没有在它的自动续签支持里,不过它提供hook,你可以写任意shell脚本完成TXT记录即可实现自动续签。
Dndpod从新版开始token直接采用id,token
组合而成,这里需要注意一下,脚本如下
renew.sh
#!/bin/bash
#
# Description:
# This program will auto obtain a Let's Encrypt certificate for qttc.net with Dnspod
#
# Author: 琼台博客 <lizhongit@gmail.com>
#
#
# Reference:
# Certbot https://certbot.eff.org/docs/
#
# 2020, April 29 First release
#
DNSPOD_TOKEN=[YOUR DNSPOD TOKEN]
DNSPOD_ID=[YOUR DNSPOD ID]
USER_AGENT='Qttc Renew Client/1.0.0(lizhongit@gmail.com)'
DOMAIN=qttc.net
echo "\
CERTBOT_DOMAIN: $CERTBOT_DOMAIN
DOMAIN: $DOMAIN
VALIDATION: $CERTBOT_VALIDATION"
if [ -f /tmp/CERTBOT_$CERTBOT_DOMAIN/VALIDATION ]; then
VALIDATION_PRE=$(cat /tmp/CERTBOT_$CERTBOT_DOMAIN/VALIDATION)
if [ "$CERTBOT_VALIDATION" = "$VALIDATION_PRE" ]; then
echo "Same Validation: $CERTBOT_VALIDATION"
exit
fi
fi
# Getting record id of named _acme-challenge
RECORD=$(curl -s -X POST "https://dnsapi.cn/Record.List" \
-H "User-Agent: $USER_AGENT" \
-d "login_token=$DNSPOD_ID,$DNSPOD_TOKEN&format=json&domain=$DOMAIN&record_type=TXT&keyword=_acme-challenge&lang=en" \
| python -c "import sys,json;ret=json.load(sys.stdin);print(ret.get('records',[{}])[0].get('id',ret.get('status',{}).get('message','error')))")
echo "RECORD: $RECORD"
sleep 3
# Updating record with validation value
if [ -n "$RECORD" ]; then
RET=echo $(curl -s -X POST "https://dnsapi.cn/Record.Modify" \
-H "User-Agent: $USER_AGENT" \
-d "login_token=$DNSPOD_ID,$DNSPOD_TOKEN&format=json&domain=$DOMAIN&record_id=$RECORD&sub_domain=_acme-challenge&record_type=TXT&record_line_id=0&value=$CERTBOT_VALIDATION&lang=en" \
| python -c "import sys,json;sys.stdin = UTF8Reader(sys.stdin);ret=json.load(sys.stdin);print(ret.get('status',{}).get('message', ''))")
else
RET=$(curl -s -X POST "https://dnsapi.cn/Record.Create" \
-H "User-Agent: $USER_AGENT" \
-d "login_token=$DNSPOD_ID,$DNSPOD_TOKEN&format=json&domain=$DOMAIN&sub_domain=_acme-challenge&record_type=TXT&value=$CERTBOT_VALIDATION&lang=en" \
| python -c "import sys,json;ret=json.load(sys.stdin);print(ret.get('status',{}).get('message', ''))")
fi
echo "Dnspod result: $RET"
# Save info for cleanup
if [ ! -d /tmp/CERTBOT_$CERTBOT_DOMAIN ]; then
mkdir -m 0700 /tmp/CERTBOT_$CERTBOT_DOMAIN
fi
echo $DOMAIN > /tmp/CERTBOT_$CERTBOT_DOMAIN/DOMAIN
echo $CERTBOT_VALIDATION > /tmp/CERTBOT_$CERTBOT_DOMAIN/VALIDATION
# Sleep to make sure the change has time to propagate over to DNS
while [ -n "$TXT_RECORD" ]
do
TXT_RECORD=$(/usr/bin/dig _acme-challenge.qttc.net txt | grep "$CERTBOT_VALIDATION")
sleep 10
done
sleep 10
以上脚本有几个环境变量需要说明一下,当你执行certbot-auto hook此脚本时,会自动预置几个变量,其中最最重要的变量是$CERTBOT_VALIDATION
,你需要用它去改写dnspod的TXT值。
为了防止默认dnspod返回中文字符导致Python包字符集错误,我这里图省事就在所有的dnspod请求加一个参数lang=en
要求返回英文。
最后只需要使用certbot-auto配合此脚本即可实现自动续签证书
#!/bin/bash
certbot-auto certonly --server https://acme-v02.api.letsencrypt.org/directory --preferred-challenges dns-01 -d *.qttc.net -d qttc.net --manual-auth-hook ./renew.sh --manual --non-interactive --agree-tos --manual-public-ip-logging-ok
如果提示没有dig
命令,安装一下dnsutils
就好
apt install -y dnsutils
最后,我们可以放到计划任务让它每80天执行一次,为了什么是80天呢?因为90天就过期,太早了会申请失败,所以比较合适的时间就是80天左右。
Crontab里要描述每80天执行一次还是比较麻烦的,所以采用了比较流行的Systemd来干这个事
/etc/systemd/system/qttc-ssl-auto.service
[Unit]
Description=Auto renew SSL for qttc.net
[Service]
Type=simple
ExecStart=/root/qttc_cron.sh
[Install]
WantedBy=multi-user.target
/etc/systemd/system/qttc-ssl-auto.timer
[Unit]
Description=Run it on each 80 days
[Timer]
OnUnitActiveSec=80d
[Install]
WantedBy=multi-user.target
System开启一下
systemctl enable qttc-ssl-auto.service
systemctl enable qttc-ssl-auto.timer
一切搞定,以后每80天会自动续签一次SSL证书