免費https證書

陳順吉發表於2019-01-13

這是搭建 docker registry 的前置文章,用來描述如何簡單獲取一個安全、可靠、免費的 https 證照。

雖然你可以使用自簽署證照來提供 https,但是由於自簽署證照的不可靠性,真實用起來受到重重限制,特別是谷歌瀏覽器對於自簽署證照的限制非常大。因此,簡單獲取免費、可靠 https 證照的手段你必須具備。

近幾年來,各大網際網路巨頭都在推進 https 的使用,谷歌瀏覽器更是將非 https 網站標記為不安全,可見其決心。但是證照申請也是一筆不小的費用,有些創業公司還不知道能活多久呢,能省則省,這個費用自然不願意花。

而且就算你申請到一個證照,一旦谷歌認為你證照的 CA(證照頒發機構)不符合它的要求,你即使是 https,它照樣給你標記為不安全。

基於這樣或那樣的原因,免費、可靠的 https 證照勢在必行。於是網際網路安全研究小組(縮寫 ISRG)於 2015 年三季度推出 Let's Encrypt 這樣的數字證照認證機構(其實就一 CA),為你免費頒發證照。

這個小組的背後站著電子前哨基金會、Mozilla 基金會、Akamai 以及思科這些大佬,因此絕對安全可靠。

如何做

既然有這種機構了,我應該怎麼申請證照呢?會不會很麻煩啊?放心,用起來非常簡單。首先,Let's Encrypt 自己肯定是有一個根證照的,因為只有根證照才能給你簽發證照。

然後呢,你需要傳送簽署請求給它,它驗證 ok 之後就給你發證照了,這一切 Let's Encrypt 內部都通過自動化來完成。由於需要自動化完成,所以證照的申請、續期以及銷燬都是通過精心設計的 ACME 協議來完成,這個協議你不需要懂,因為客戶端工具會自動幫你發起。

大家應該都清楚,你申請證照的時候是要提供主機名的,比如 www.ntpstat.com,因為主機名是需要寫進證照中的。還有一個種是隻提供通配主機名而非具體主機名的,比如 *.ntpstat.com,這種叫泛域名證照或者萬用字元證照,也就是隻要是這個域下的所有二級域名都可以使用這個證照。

比如說我只要申請了 *.ntpstat.com 這個泛域名證照,那麼我下面的 www.ntpstat.com、mail.ntpstat.com、file.ntpstat.com 等二級域名都可以使用這個證照了。相對來說,泛域名證照用起來更爽。

具體怎麼做呢?先拿具體的主機名證照申請為例,我們先將證照籤署請求傳送到 Let's Encrypt,傳送請求很簡單,有客戶端工具可以給你完成(下面會提到)。我們要做的就是提供給它驗證的方式,Let's Encrypt 得驗證你就是申請這個主機名的人。

這個大家應該能理解吧,不能說你要簽署個什麼證照它就籤給你對吧。驗證有兩種方式,假如我現在申請的主機名是 www.ntpstat.com:

  • 第一種驗證方式:Let's Encrypt 會通過訪問 http://www.ntpstat.com/.well-known/acme-challenge 由客戶端工具生成的驗證檔案,驗證通過會在伺服器上生成證照檔案。因此你在使用客戶端時需要指定你 web 伺服器的根目錄,這樣它才能夠在相應目錄下生成驗證檔案;
  • 第二種驗證方式:如果你申請的主機名並不對外,只是內部使用,或者你申請的是泛域名證照時,就可以使用第二個驗證方式了。你需要在公網的 dns 域下面新增一條 TXT 記錄,比如我就要在 *.ntpstat.com 這個域下新增一個 TXT 記錄,記錄的內容客戶端工具會給出。Let's Encrypt 解析出來的 TXT 記錄如果和客戶端工具給出的一致,那麼同樣生成證照檔案。

個人感覺第二種用的比較多,因為它可以使用泛域名證照以及內部使用。但是不管哪一種,申請下來的證照的有效期只有 90 天,到期就要續期了。但是不用擔心,你寫個定時任務就可以了,客戶端工具會自動幫你續期。

客戶端工具

說到這裡,想必你對 Let's Encrypt 有了個大致的瞭解了,接下來就要提到它的客戶端工具了。Let's Encrypt 官方的客戶端工具是 certbot,用起來挺簡單;另一種是國人寫的 acme.sh,據說比官方工具更好用。

只要你懂得 ACME 協議,也可以寫一個客戶端工具,所以可能還有另外的工具,但是這裡就不多提了。

certbot

官方的客戶端工具。

對於第一種驗證方式,certbot 本身會使用 nginx/apache 啟動一個 web 伺服器,並自動生成驗證檔案,對外提供服務。看官方的意思是這個 web 伺服器只提供服務於驗證請求,其他請求一概不響應。當然我沒有看它的 nginx 配置檔案,不知道是不是真的如此,這種模式稱為 Standalone。如果你要使用這種模式,那麼只需要在第一次請求證照以及在後續續期期間將 web 伺服器啟動即可,平時完全可以處於關閉狀態。並且你得確保系統的 80 和 443 埠沒有被其他服務監聽。

當然對於一些個人伺服器來講,可能就一臺伺服器,並且 80 埠正在提供服務,不可能為了申請證照就直接將服務關了。即使你現在無所謂,後面續期你又得關,總之是很麻煩的。所以 certbot 允許你使用當前的 web 服務進行驗證,只不過你要指定你 web 伺服器的根目錄,它會建立 .well-known 目錄,並在其下生成驗證檔案。這種模式稱為 Webroot

這兩種模式都屬於第一種驗證方式,只不過有兩種實現方式而已。

certbot 依賴 Python2.7 或者 Python3.4+,所以確保你的系統符合要求。

OK,我們先下載。我們不直接下載 certbot,而是下載 certbot-auto,它是一個 shell 指令碼,對 certbot 做了一層封裝,它用起來和 certbot 一樣,但是執行的時候它會檢測本地的 certbot 版本,如果本地沒有就安裝;本地有但是不是最新版本的話,它會自動將其升級。安裝或升級之後,會將傳遞給 certbot-auto 的所有引數都傳遞給 certbot 執行。

本人使用的系統是 CentOS7:

# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
複製程式碼

因為客戶端工具需要聯網給 Let's Encrypt 傳送證照籤署請求,因此請確保作業系統有網路連線。假如沒有,可以參考我之前的搭建代理服務讓內網上網,通過在一臺能上網的伺服器上搭建代理服務讓其他伺服器通過它來上網。

# wget https://dl.eff.org/certbot-auto
# chmod a+x ./certbot-auto
# ./certbot-auto --help
複製程式碼

你可以檢測這個指令碼的完整性:

# wget -N https://dl.eff.org/certbot-auto.asc
# gpg2 --keyserver pool.sks-keyservers.net --recv-key A2CFB51FA275A7286234E7B24D17C995CD9775F2
# gpg2 --trusted-key 4D17C995CD9775F2 --verify certbot-auto.asc certbot-auto
複製程式碼

最後一個命令的輸出應該是這樣:

gpg: Signature made Wed 02 May 2018 05:29:12 AM IST
gpg:                using RSA key A2CFB51FA275A7286234E7B24D17C995CD9775F2
gpg: key 4D17C995CD9775F2 marked as ultimately trusted
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   2  signed:   2  trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: depth: 1  valid:   2  signed:   0  trust: 2-, 0q, 0n, 0m, 0f, 0u
gpg: next trustdb check due at 2027-11-22
gpg: Good signature from "Let's Encrypt Client Team <letsencrypt-client@eff.org>" [ultimate]
複製程式碼

第一種驗證方式

第一種驗證方式是直接在已存在的 web 伺服器上生成驗證檔案讓 Let's Encrypt 訪問驗證,因此你的伺服器必須要有外網 ip,且你申請 https 證照的域名能夠解析到這個 ip。比如我現在要申請 www.ntpstat.com 的證照,Let's Encrypt 會訪問 www.ntpstat.com/.well-known/acme-challenge 進行驗證。

這裡只介紹使用 Webroot 的方式,Standalone 就不多提了,我也沒有弄過。

我現在安裝一個 nginx 來表示我本地已經存在 web 伺服器了:

# vim /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1

# yum install -y nginx
# systemctl enable nginx
# systemctl start nginx
複製程式碼

因為我用於簽署證照的域名是 www.ntpstat.com,此時可以直接訪問了。

免費https證書

訪問 ok,並且還被瀏覽器標記為了不安全,嗯,馬上它就安全了。使用客戶端工具發出證照籤署請求:

# ./certbot-auto certonly --webroot -w /usr/share/nginx/html -d www.ntpstat.com
複製程式碼

引數說明:

  • certonly:表示只生成證照而不安裝 web 伺服器,雖然它也可以通過 nginx 外掛來提供 web 服務,但是還是自己安裝來的放心;
  • --webroot:使用 webroot 外掛,這是配合 certonly 使用的;
  • -w--webroot-path 的縮寫,用來指定 web 伺服器的根目錄,nginx 預設根目錄是 /usr/share/nginx/html;
  • -d:指定用於訪問的主機名。

第一次執行上面的命令它會幫你安裝 certbot,安裝完成之後開始執行,下面是它的輸出資訊:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): # 讓你輸入郵箱地址,這個郵箱用來傳送續期和安裝通知類的郵件,當然你可以輸入 c 來取消

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A # 讓你同意註冊 ACME server,同意就是了

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: n # 是否共享你的郵箱,後面會發一些周邊的郵件之類的,這個看需要了
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for www.ntpstat.com
Using the webroot path /usr/share/nginx/html for all unmatched domains.
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/www.ntpstat.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/www.ntpstat.com/privkey.pem
   Your cert will expire on 2019-04-06. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - 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
複製程式碼

OK,這就簽署完成了,證照在 /etc/letsencrypt/live/www.ntpstat.com/fullchain.pem,對應的私鑰檔案為 /etc/letsencrypt/live/www.ntpstat.com/privkey.pem。上面還介紹了這個證照的有效期,並且還告訴你需要只需要執行 certbot-auto renew 就可以了。

既然證照都有了,那就 https 搞起唄。

修改 nginx 配置檔案:

# vim /etc/nginx/conf.d/ssl.conf
server {
    listen   *:443;
    server_name  www.ntpstat.com;

    ssl on;
    ssl_certificate      /etc/letsencrypt/live/www.ntpstat.com/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/www.ntpstat.com/privkey.pem;

    location / {
        root /usr/share/nginx/html;
    }
}
複製程式碼

瀏覽器使用 https 訪問就可以看到連線是安全的。

免費https證書

當然,你可能想要 http 訪問直接跳轉到 https,很簡單,在 http 訪問中加個跳轉就可以了。

# vim /etc/nginx/conf.d/default.conf
server {
    listen       80;
    server_name  www.ntpstat.com;

    # 新增一行,強制跳轉 https
    rewrite ^(.*)$ https://$host$1 permanent;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
複製程式碼

驗證完成後,生成的驗證目錄都會自動刪除掉。

第二種驗證方式

可以看到,很簡單就完成了針對單個域名的 https 證照獲取。這可能在你建自己的網站方面有用,因為你對外提供了 web 服務。但是當你的證照只是內部使用,並沒有對外提供 web 服務,let's encrypt 伺服器根本訪問不到,比如 docker registry、ldap https 等等這樣的,又或者是簽署泛域名證照這樣的場景,第一種驗證方式就不可用了。當然,Let's Encrypt 肯定是瞭解大家需求的,因此現在就來講講它的第二種驗證方式。

前面也提到了,第二種驗證方式就是通過新增 dns 的 TXT 記錄來完成。這就要求你的域名必須能夠在公網上面被解析,因此你的一級域必須是 com、cn、net、pro 等公網上能夠買的到域,否則 Let's Encrypt 發起個 TXT 記錄的解析不可能收到結果的。

自己內部搭建的 DNS 就不用想了,因為外部訪問不到。

之前的域名我們先不管,重新簽署一個泛域名的吧,這樣好驗證。

# ./certbot-auto certonly --manual --preferred-challenges dns
複製程式碼

先說說選項:

  • certonly:這個前面也提到了,只簽署證照不需要 http 服務;
  • --manual:用於當前這種通過 dns 驗證的方式,它還提供另一種 http 的方式驗證,比如你現在執行 certbot 命令的機器並不是你提供 web 服務的那一臺,當然這不重要;
  • --preferred-challenges:配合 --manual 使用的,因為我們們要通過 dns 驗證,所以選擇 dns。

這個命令的執行需要花點時間,可能是用在檢測本地的 certbot 版本。

以下是命令的輸出內容:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'
to cancel): *.ntpstat.com # 讓你輸入你的域,因為簽署的是泛域名證照,因此需要加上 *
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for ntpstat.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: n
Cleaning up challenges
Must agree to IP logging to proceed
[root@host ~]# ./certbot-auto certonly --manual --preferred-challenges dns
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'
to cancel): ntpstat.com
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for ntpstat.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y # 意思是這個機器的 ip 已經被公開記錄為請求這個證照,有點沒搞懂。但你只能輸入 y,否則命令執行終止

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.ntpstat.com with the following value: # 給出了 TXT 記錄的名稱和對應的值

me0g64A6vImOjdeC0yyG26m_LLxtQPELWXdInzqynVk

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
複製程式碼

先別急著回車,我們先新增它的 dns 記錄。你需要登入你的域名運營商,並且你的域名下面新增一條記錄。根據我上面生成的資訊,我需要在我的 ntpstat.com 這個域下面增加一個 TXT 記錄,名稱是 _acme-challenge(後面的 .ntpstat.com 不要加上去),值為 me0g64A6vImOjdeC0yyG26m_LLxtQPELWXdInzqynVk

然後使用 dig 命令檢測一把:

# dig -t TXT _acme-challenge.ntpstat.com

; <<>> DiG 9.9.4-RedHat-9.9.4-72.el7 <<>> -t TXT _acme-challenge.ntpstat.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64655
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1452
;; QUESTION SECTION:
;_acme-challenge.ntpstat.com.	IN	TXT

# 看 ANSWER SECTION 這個欄位
;; ANSWER SECTION:
_acme-challenge.ntpstat.com. 3582 IN	TXT	"me0g64A6vImOjdeC0yyG26m_LLxtQPELWXdInzqynVk"

;; Query time: 5 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Sun Jan 13 00:22:13 EST 2019
;; MSG SIZE  rcvd: 112
複製程式碼

可以檢視解析 OK,然後就可以回車了。

Press Enter to Continue
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/ntpstat.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/ntpstat.com/privkey.pem
   Your cert will expire on 2019-04-13. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - 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
複製程式碼

簽署成功!證照的路徑也已給出了。那麼泛域名證照就簽署完畢了,那麼這個域下面的任何三級域都可以使用這個證照,比如 blog.ntpstat.com、www.ntpstat.com、file.ntpstat.com 等。

我們現在就可以修改 nginx 配置檔案,將證照換成新證照進行測試。

# vim /etc/nginx/conf.d/ssl.conf
server {
    listen   *:443;
    server_name  www.ntpstat.com;

    ssl on;
    ssl_certificate      /etc/letsencrypt/live/ntpstat.com/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/ntpstat.com/privkey.pem;

    location / {
        root /usr/share/nginx/html;
    }
}
複製程式碼

只需要換個證照即可,其他什麼都不需要改。reload nginx 之後,直接訪問 https://www.ntpstat.com。當然,你需要換成你的域名。

可以看到,照樣是安全的。你其實可以新增個三級域名的 A 記錄,比如 file.DOMAIN.com(或者本地修改 hosts 檔案),然後使用這個域名進行 https 訪問看是否存在問題,這也就能夠驗證泛域名證照是否有效了。

證照續期

證照預設三個月到期,certbot 提供了證照續期的方法,使用 renew 子命令。

./certbot-auto renew
複製程式碼

簡單的不行!之前使用的外掛和選項它會沿用,它不同於 certonly,它會檢查當前機器上使用 certbot 申請的所有證照是否過期,而不是單單隻針對一個。

只有當證照有效期不足 30 天后這個命令才工作,因此你可以寫個定時任務執行這個命令,可以每天執行也可以每週或每月執行,隨便你了。你現在執行的話,它會提示證照還未到失效期,直接就跳過了。

使用 crontab 執行續期命令的話,一定要注意環境變數的問題,因此你執行的最好將命令寫入到一個指令碼中,在執行這個指令碼時將指令碼的輸出全重定向到一個檔案,這樣你就能知道這個指令碼的執行情況了。

就像這樣:

1 1 * * * sh -x /PATH/TO/certbot-renew.sh &>/tmp/certbot-auto.log
複製程式碼

renew 這個子命令提供了鉤子,可以在執行這個命令之前和之後執行某些命令。比如對於 Standalone 模式續期之前需要啟動 web 服務,在驗證之後又想關掉時就可以這麼用。

./certbot-auto renew --pre-hook "service nginx stop" --post-hook "service nginx start"
複製程式碼

但是這種證照續期方式只適用於普通的域名,對於泛域名證照,由於需要修改 TXT 記錄,這個涉及到域名提供商,Let's Encrypt 就無能為力了,比如下面的錯誤提示。

Processing /etc/letsencrypt/renewal/ntpstat.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert is due for renewal, auto-renewing...
Could not choose appropriate plugin: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',)
Attempting to renew cert (ntpstat.com) from /etc/letsencrypt/renewal/ntpstat.com.conf produced an unexpected error: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',). Skipping.
複製程式碼

當然,現在的域名運營商基本都提供了 api 供你呼叫來完成自動化操作,就有人提供了對熱門域名運營商的 Let's Encrypt 續期操作,Github 地址在此,按照上面的說明進行操作就行。

有個問題就是,證照續期之後證照檔案的內容肯定會發生改變(還未來得及測試,但應該如此),如果這個證照檔案在其他伺服器上使用的話,不知道在續期後要不要進行替換。

證照撤銷

如果你私鑰被盜用,或者你就是想撤銷證照的話可以使用 revoke 子命令。

certbot revoke --cert-path /etc/letsencrypt/live/CERTNAME/cert.pem
複製程式碼

注意它要指定的是證照的路徑,而非域名。

好了,certbot 要講到的內容就這麼多了,關於 certbot 命令的使用還有很多內容,有興趣的話可以自行檢視官方文件。

acme.sh

acme.sh GitHub star 已經 10k 多了,還是非常值得一用的。有需要的話,可以自行檢視使用,反正有中文文件,看起來一點不費事。這裡就不多提了,想必有了前面的基礎,使用它應該沒有任何問題。這裡只是告訴大家有這麼個東西,其實我也沒有用過 :)

監控證照的有效期

雖然我們可以使用定時任務去自動對證照進行續期,並且快到期時 Let's Encrypt 也會傳送郵件,但是還是有些被動,我們最好能夠主動監控它,當證照有效期不足比如 7 天時,傳送告警。

d=`openssl x509 -in /etc/letsencrypt/live/ntpstat.com/fullchain.pem -noout -enddate | awk -F= '{print $2}'`
end_timestamp=`date -d "$d" +"%s"`
current_timestamp=`date +"%s"`
echo $((end_timestamp-current_timestamp))
複製程式碼

輸出的時間戳表示證照過期時間距離當前時間相差多少秒,你就可以通過這個時間戳來制定觸發器了,比如 7 天總共 604800 秒,如果上面的時間小於這個值那就表示 7 天后過期,要報警了。

godaddy 續期操作

由於國內的域名需要備案,因此使用 godaddy 購買域名是個很不錯的選擇。

本人買的就是 godaddy 的域名,且之前申請的 https 泛域名證照快到期了,續期的時候才發現還需要修改 TXT 記錄。雖然有人提供了自動化操作的指令碼,但是自己想研究研究。

稍稍看了下 godaddy 的開發者文件,發現原來修改 TXT 記錄只需要一條 curl 命令就行,簡單的一逼。下面我就將如何使用 curl 命令,以及指令碼如何呼叫的方式寫出來,供大家參考。

首先使用火狐瀏覽器訪問 developer.godaddy.com,注意一定要使用火狐瀏覽器,我之前用谷歌、edge、ie 訪問都不行,這裡不得不吐槽 godaddy,做的真是垃圾。

開啟網頁之後,點選 api keys,登入之後就可以生成 key 和 secret 了,環境我選擇的是 production。它們之間的區別不是很瞭解,或許生產環境才能直接生效?不同的環境呼叫的域名不同,其他引數都一樣。

#!/bin/bash

api_key=""
api_secret=""
record="_acme-challenge" # 固定值
record_ttl="1500" # 單位是秒
record_type="TXT"
record_value=""
domain=""
api_base_url="https://api.godaddy.com/"
api_url=`echo -n "${api_base_url}v1/domains/${domain}/records/${record_type}/${record}"`

curl -X PUT "${api_url}" -H "accept: application/json" -H "Content-Type: application/json" -H "Authorization: sso-key ${api_key}:${api_secret}" -d "[{\"data\": \"${record_value}\", \"ttl\": ${record_ttl}}]"
複製程式碼

一條 curl 命令就 ok 了,非常簡單,你現在就可以填入對應值測試一把。

接下來就需要使用 certbot-auto 命令進行呼叫了,它會自動傳遞域名和 TXT 記錄的值到指令碼中,所以我們需要修改下指令碼。

#!/bin/bash

api_key=""
api_secret=""
record="_acme-challenge"
record_ttl="600"
record_type="TXT"
record_value="${CERTBOT_VALIDATION}"
domain="${CERTBOT_DOMAIN}"
api_base_url="https://api.godaddy.com/"
api_url=`echo -n "${api_base_url}v1/domains/${domain}/records/${record_type}/${record}"`

curl -sX PUT "${api_url}" -H "accept: application/json" -H "Content-Type: application/json" -H "Authorization: sso-key ${api_key}:${api_secret}" -d "[{\"data\": \"${record_value}\", \"ttl\": ${record_ttl}}]"
複製程式碼

它不會將值作為引數進行傳遞,而是直接傳遞環境變數,上面兩個環境變數就是它傳遞的。然後我們將上面的內容貼入到一個檔案中,我這裡使用的是 /tmp/test.sh,接著賦予該指令碼執行許可權。

最後續期:

./certbot-auto renew --preferred-challenges=dns --manual-auth-hook /tmp/test.sh
複製程式碼

--preferred-challenges 可以指定 http 和 dns,我們是 dns,所以使用 dns。

--manual-auth-hook 會自動傳遞三個環境變數,其中 dns 只有上面我們用到的兩個,而 http 則會多一個 CERTBOT_TOKEN

你還可以使用 --manual-cleanup-hook 指定驗證完成後的操作,同樣是個指令碼,並且會自動傳遞 CERTBOT_AUTH_OUTPUT 給指令碼。不過這個選項我們用不上。

當你續期的時候,測試的時候不要太頻繁。如果你剛修改 TXT 記錄,並且時間還未超過 TTL 的時間時就開始續期,那麼驗證會失敗,因為 Let’s Encrypt’s 查到的會是上次的快取,而不是此次修改的值。

相關文章