Let’s Encrypt 的 DNS-01 Challenge

自從我懂事以來,都是利用 certbot 進行 「HTTP-01 Challenge」,讓發證單位透過http方式驗證,以取得免費的https證書。

除非遇到Let’sEncrypt考驗伺服器秀逗,否則不可能出問題;長大後,我雄心壯志到各地歷練,發現有些主機 80、443 port 居然被封鎖,沒有了80 port (http),就無法透過HTTP-01考驗方式取得https證書。直到此時,我才知道「代誌不是我們憨人想的架甘丹」—事情不是我們想像的這麼簡單啊。

Let’s Encrypt的Challenge Types,列出支援的驗證類型,裡面提到若 HTTP-01 不能用,還有其他選擇,例如本文要說的:DNS-01 Challenge

DNS-01 使用原理很簡單:DNS伺服器提供ACME DNS API,讓Let’s Encrypt能夠透過API進行考驗,就能取得https證書了。


2024-4-2
新作法 使用開源acme.sh專案

1. 線上安裝

# 若需要使用dns-01方式,email必須是提供API token相同帳號
curl https://get.acme.sh | sh -s email=xxx@test.com
# 安裝完畢程式會在 /root/.acme.sh/acme.sh ("root"因帳號而異)

2. 使用DNS方式授權
取得API Token 或 API Key (以 cloudflare 為例子)

3. 取得授權檔案

/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt

export CF_Key = "b0e689102efab2cf7a1547aaa8b57c4eb65ff"
export CF_Email = "提供API Key之email帳號"
/root/.acme.sh/acme.sh --issue --dns dns_cf -d remote.test.com


export CF_Token = "ibrxxFFlKZ5FrsBpisXRU7GzO_2KzSwRAQoAwbsT"
export CF_Email = "提供API Token之email帳號"
/root/.acme.sh/acme.sh --issue --dns dns_cf -d remote.test.com

# 因為我使用apache httpd、CentOS 7.9;httpd 最高到2.4.6,只能支援RAS加密,不支援ECC;
# 然而acme預設產生的是ECC加密檔案,所以指令需額外加上 -k 4096改成產生RSA加密檔案。
/root/.acme.sh/acme.sh --issue --dns dns_cf -k 4096 -d remote.test.com
# 產生完授權證書後,進行安裝到letsencrypt所在目錄
/root/.acme.sh/acme.sh --install-cert -d remote.test.com \
--cert-file /etc/letsencrypt/live/remote.test.com/cert.pem \
--key-file /etc/letsencrypt/live/remote.test.com/privkey.pem \
--fullchain-file /etc/letsencrypt/live/remote.test.com/fullchain.pem
#自動更新授權證書(會自動加到crontab)
/root/.acme.sh/acme.sh --upgrade --auto-upgrade
# acme產生檔案與 Let's encrypt檔案對應如下
ACME <-> Let's Encrypt
==========================================================
ca.cer <-> cer.pem
fullchain.cer <-> fullchain.pem
remote.test.com.cer <-> chain.pem
remote.test.com.key <-> privkey.pem
==========================================================

(已失效)google domains 為範例:(很可惜google賣掉網域代管業務)

1、先建立權杖(token)

登入google domain後,點選「安全性」->ACME DNS API 「建立權杖」

此權杖只會出現一次,因此複製後,要妥善保存

2、我想使用certbot方式取得憑證,所以到 「certbot-dns-google-domains 」github ,取得執行方式。
2.1 新增權杖檔案

vi /var/lib/letsencrypt/dns_google_domains_credentials.ini
dns_google_domains_access_token = QWVpQWZjT1xxxxxxg2N3lrMi1LUQ==
dns_google_domains_zone = test.com

2.2 docker方式執行,輕鬆取得https證書。

docker run \
  -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
  -v '/etc/letsencrypt:/etc/letsencrypt' \
  --cap-drop=all \
  ghcr.io/aaomidi/certbot-dns-google-domains:latest \
  certbot certonly \
  --authenticator 'dns-google-domains' \
  --dns-google-domains-credentials '/var/lib/letsencrypt/dns_google_domains_credentials.ini' \
  --server 'https://acme-v02.api.letsencrypt.org/directory' \
  --non-interactive \
  --dns-google-domains-zone 'test.com' \
  -d 'xxx.test.com'

3、還有其他取得證書方式(一樣是google domain)
請參考 List of known ACME clients to work the ACME DNS API


若使用的是阿里雲解析,可參考這篇文章,我自己測試結果沒問題;提醒一下,要使用let’s encrypt,dns需要有CAA record 允許let’s encrypt 發證,否則會出現 「Verify error : CAA ……」錯誤

未免忘記,節錄一些指令;
除了指令外,還需要在阿里雲加上RAM帳號,授權該帳號能透過阿里雲OpenAPI修改DNS,
並且取得該RAM帳號「Key」與「Secret」,以下指令需要用到。

yum install socat
curl https://get.acme.sh | sh
vim /root/.acme.sh/acme.sh.env
export LE_WORKING_DIR="/root/.acme.sh"
alias acme.sh="/root/.acme.sh/acme.sh"
export Ali_Key="xxxx"
export Ali_Secret="yyyy"
source ~/.bashrc
env
acme.sh --set-default-ca --server letsencrypt

acme.sh --issue --dns dns_ali --dnssleep 180 -d xxxx.test.com
#若以上指令不行,可改以下指令
acme.sh -f --use-wget --issue --dns dns_ali --dnssleep 180 -d xxxx.test.com

2023/6/16 我在RockyLinux 9.2安裝失敗出現以下問題(google代管之網域)

[Errno 13] Permission denied: '/etc/letsencrypt/.certbot.lock'

這很複雜,原因很多,我的解法如下:

解法1. selinux 放行,然後再關起門來
 setenforce 0 ; docker run \
  -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
  -v '/etc/letsencrypt:/etc/letsencrypt' \
  --cap-drop=all \
  ghcr.io/aaomidi/certbot-dns-google-domains:latest \
  certbot certonly \
  --authenticator 'dns-google-domains' \
  --dns-google-domains-credentials '/var/lib/letsencrypt/dns_google_domains_credentials.ini' \
  --server 'https://acme-v02.api.letsencrypt.org/directory' \
  --non-interactive \
  --dns-google-domains-zone 'test.com' \
  -d 'xxx.test.com' ; setenforce 1;

解法2. 確認相關套件是否安裝
dnf install httpd mod_ssl
certbot --apache
#若出現The requested apache plugin does not appear to be installed,則代表缺少套件
yum list installed|grep certbot
certbot.noarch                                   2.6.0-1.el9                         @epel
python3-certbot.noarch                           2.6.0-1.el9                         @epel
這樣還缺少  python3-certbot-apache , 我再安裝一下
dnf install python3-certbot-apache

linux hostname lookup

主機名稱很重要, hostname , 我們公司有台老鼎新tiptop erp主機 安裝的是 redhat enterprise 4 .


tiptop的架構我簡單的敘述, client端連線到這台 server , 這台server會辨識client 端ip , 再將資料以xml方式, 反向傳回去client端的接收程式, 該接收程式(genero desktop client , gdc )會把xml資料轉成UI介面 , 方便讓使用者使用.

可是呢, 每次使用者執行程式, 都必須進行license檢驗, 以及進行 host name lookup 查詢資料庫的ip在哪, 我說的是每次執行程式哦, 都要進行資料庫主機在哪的查訪動作, 實在是有夠怪的設計 , 這10多年來我困擾很久, 終於有點了解了
為何要了解這個, 因為使用者執行程式, 常常導致跑一隻程式, 光是等待程式冒出來就要等2分鐘… 我們早就知道是lookup的問題, 但找不出真正的解法, 以下是lookup的解決切入點

nsswitch 可以指定優先查 /etc/hosts 或是 dns 或是 winbind 

但這款老舊版本有個怪怪的bug, 設定了相關的lookup , 總是沒用, 就是會查詢失敗導致時間過久使用者憤怒, 我無意間看到有人寫了可以這樣檢查

getent hosts 資料庫主機名稱
或是
strace  getent hosts 資料庫主機名稱

我發現ap主機查詢很快, 但是查詢db主機超慢, 於是加上strace檢查問題 , 我加上去之後看不懂, 於是就多看了幾次,

這指令居然神奇的自己解決查詢過久的問題, 多執行幾次就變快了…. @@ 傻眼

dns代管的建議事項

申請網域之後, 接下來就是思考如何設定dns, 以下是幾點建議:

  1. TW網域, 請到申請的網域公司設定成cloudflare代管,功能非常多,而且免費,還能作為CDN網站分流呢!
    為何不使用網域公司提供的功能呢? 因為國內網域公司提供的dns很陽春, 萬年功能就是A, TXT, PTR, MX,NS之類, 很不思進步, 台灣的能耐大概也就只能這樣. Hinet甚至還出現額外功能還要收費的情形.
  2. 其他網域若能使用google domain代管最好了, 直接提供超強的dns功能, 若網域不是向google domain購買,則無法請google domain代管, 請轉成cloudflare.
    另外若網域向GoDaddy申請, 您一定知道申請者資料保護還要另外收費,真是傻眼,趕快移轉到別地方吧, 偶認為GoDaddy是個很不優質的網域服務商, 但有些網域倒是不得不拜託GoDaddy 如 DE 德國的網域.
  3. 自架設PowerDNS-Admin , 本站爬一下文, pdns非常實用, 還支援DDNS功能, 若要突破大陸封鎖google的網路, 請務必準備好自架的DNS server.

2019年2月1日是 DNS flag day

長期以來很多自行架的dns伺服器, 並沒有支援Extension mechanisms for DNS (EDNS) , 造成google等公眾dns服務器(8.8.8.8, 1.1.1.1)效能低落, 常常要重複存取這些舊版的dns服務器,浪費資源.

因此, 這些公眾服務器廠商發表聲明, 將於2019年2月1日, 不再支援沒有EDNS功能dns伺服器.

若您因台灣爛到爆的dns代管功能太差, 失望之餘而自行架設dns服務器, 應該立即使用以下網址中的檢測工具, 查詢您的網域是否能通過檢測.

ps. 國外dns代管功能非常棒,除了.com.tw, org.tw , idv.tw 等等網域申請外跑不掉外, 請儘量不要在國內申請任網域.

https://dnsflagday.net/

老毛子Padavan 韌體, 如何透過PowerDNS-Admin更新DDNS

之前介紹過小米路由器mini可以刷老毛子padavan韌體, 不只功能強,還可以啟用shadowsocks功能, 但是有些路由器上網ip是動態的, 因此需要用到DDNS來綁定動態ip, 目前最穩定的DDNS大概就是google domain了, 他支援dyndns 2.
有些人若要綁定自己的網域, 可以安裝PowerDNS-Admin , 這個軟體也支援dyndns 2.
但是問題來了, padavan 與自行建立的PowerDNS-Admin 並不相容, 偶研究了很久, 終於用迂迴的方式搞定.

1. 建立正確的ddns設定文件
vi /etc/storage/script/inadyn.conf

background
verbose 1
checkip-url ip.3322.net /
startup-delay 15
period 600
forced-update 864000
cache-dir /tmp/inadyn
exec /sbin/ddns_updated
system custom@http_srv_basic_auth
  username <帳號>
  password <密碼>
  server-name :
  server-url //nic/update?hostname=<想改的網域主機名字>&myip=
  append-myip
  alias <想改的網域主機名字>

2. 找出padavan啟動後執行的腳本, 於最後一行加上

#!/bin/sh
pid=`ps | grep inadyn | awk 'NR==1{print $1}' | cut -d' ' -f1`
name=`ps | grep inadyn | awk 'NR==1{print $5}' | cut -d' ' -f1`
if  [[ "$name" == "/bin/inadyn" ]];
then
  if [[ -z "$pid" ]]
    /bin/kill $pid
  then
    echo "kill $pid"
  fi
fi
/bin/cp /etc/storage/script/inadyn.conf /etc/
/bin/rm -r /tmp/inadyn
/bin/inadyn --config /etc/inadyn.conf

當然做這些動作之前,padavan要設定啟用DDNS功能, 基本上這樣重開機之後, 會將正確的conf複製到系統目錄上,再重新執行就可以了,
另外設定檔裡面的 ip.3322.net 是可以透過padavan預設的ddns功能修改的.

CentOS 7使用docker安裝超強的power dns 域名服務器

台灣提供網域代管服務廠商實在是很糟糕, 如hinet , seednet 等龍頭都只願意提供基本功能.

進階功能如 CAA等功能大家根本不敢奢望, 因此只能靠自己安裝dns網域伺服器, 做得好的話還能達到fail-over功能,壞了自動由別台替代呢.

請參考

https://docs.kafeiou.pw/!/#iammis/view/head/%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0/HowTo/10025_(CentOS)(Docker)%E5%A6%82%E4%BD%95%E5%AE%89%E8%A3%9D%E8%B6%85%E5%BC%B7%E7%9A%84PowerDNS-Admin%E7%B6%B2%E5%9F%9F%E6%9C%8D%E5%8B%99%E5%99%A8.txt

1 2