# 使用Duck DNS获取Let's Encrypt证书

# 注册Duck DNS

https://www.duckdns.org/

# 安装certbot

# nginx服务器(Ubuntu)

# 安装certbot

sudo apt install certbot
sudo apt install python3-certbot-nginx

# 创建申请

sudo certbot --manual --preferred-challenges dns certonly

后会有类似以下提示:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name:

_acme-challenge.test.duckdns.org.

with the following value:

sz8QCaKoQBBO5pYqTIUIVr-twoQYaa5yYiWHfcuDDTo
    
Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

# 更改TXT记录

# curl https://www.duckdns.org/update?domains={YOURVALUE}&token={YOURVALUE}&txt={YOURVALUE}
# 也可以浏览器访问,回显"OK"
curl https://www.duckdns.org/update?domains=test.duckdns.org&token=00000000-0000-0000-0000-00000000000f&txt=sz8QCaKoQBBO5pYqTIUIVr-twoQYaa5yYiWHfcuDDTo

# 继续申请

Enter

# 成功提示

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/test.duckdns.org/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/test.duckdns.org/privkey.pem
This certificate expires on 2023-08-18.
These files will be updated when the certificate renews.

NEXT STEPS:
- This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

证书:/etc/letsencrypt/live/test.duckdns.org/fullchain.pem
私钥:/etc/letsencrypt/live/test.duckdns.org/privkey.pem

# 创建自动续签任务

保存certbot-auth-duckdns.sh

#!/bin/bash

#
# Create: certbot certonly --manual --preferred-challenges dns-01 --email mail@domain.com -d laravel.run -d *.laravel.run --server https://acme-v02.api.letsencrypt.org/directory --manual-auth-hook /path/to/certbot-auth-duckdns.sh
# Renew:  certbot renew --manual-auth-hook /path/to/certbot-auth-duckdns.sh
#

# https://github.com/al-one/certbot-auth-dnspod/

API_TOKEN=""

if [ -z "$API_TOKEN" ]; then
    [ -f $HOME/.duckdns_token_$CERTBOT_DOMAIN ] && API_TOKEN=$(cat $HOME/.duckdns_token_$CERTBOT_DOMAIN)
fi

if [ -z "$API_TOKEN" ]; then
    [ -f /etc/duckdns_token_$CERTBOT_DOMAIN ] && API_TOKEN=$(cat /etc/duckdns_token_$CERTBOT_DOMAIN)
fi

if [ -z "$API_TOKEN" ]; then
    [ -f $HOME/.duckdns_token ] && API_TOKEN=$(cat $HOME/.duckdns_token)
fi

if [ -z "$API_TOKEN" ]; then
    [ -f /etc/duckdns_token ] && API_TOKEN=$(cat /etc/duckdns_token)
fi

if [ -z "$API_TOKEN" ]; then
    API_TOKEN="$DUCKDNS_TOKEN"
fi


echo "\
DOMAIN: $CERTBOT_DOMAIN
VALIDATION:     $CERTBOT_VALIDATION"

# CERTBOT_DOMAIN: test.duckdns.org
# VALIDATION:     ********

# curl https://www.duckdns.org/update?domains=test.duckdns.org&token=00000000-0000-0000-0000-00000000000f&txt=sz8QCaKoQB
if [ "$1" = "clean" ]; then
    APIRET=$(curl -s "https://www.duckdns.org/update?domains=$CERTBOT_DOMAIN&token=$API_TOKEN&txt=")
    echo "Remove Record: $CERTBOT_DOMAIN - $APIRET"
else
    APIRET=$(curl -s "https://www.duckdns.org/update?domains=$CERTBOT_DOMAIN&token=$API_TOKEN&txt=$CERTBOT_VALIDATION")
    echo "Update Record: $CERTBOT_DOMAIN - $APIRET"

    # Sleep to make sure the change has time to propagate over to DNS
    sleep 30
fi
sudo crontab -e

保持在线状态以免证书被吊销。在证书到期或续订之前不会执行任何操作。

0 */12 * * * export DUCKDNS_TOKEN=00000000-0000-0000-0000-00000000000f && python3 -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew --manual-auth-hook /path/to/certbot-auth-duckdns.sh
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/test.duckdns.org.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Renewing an existing certificate for test.duckdns.org
Hook '--manual-auth-hook' for test.duckdns.org ran with output:
 CERTBOT_DOMAIN: test.duckdns.org
 VALIDATION:     sz8QCaKoQBBO5pYqTIUIVr-twoQYaa5yYiWHfcuDDTo
 Update Record:  test.duckdns.org - OK

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all renewals succeeded: 
  /etc/letsencrypt/live/test.duckdns.org/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

# 参考

Letsencrypt通过DNS的TXT记录来验证域名有效性
Certbot DNS Authenticator For DNSPod