1. 程式人生 > 實用技巧 >HTTPS之acme.sh申請證書

HTTPS之acme.sh申請證書

1.關於let's encrypt和acme.sh的簡介

1.1 let's encrypt

  Let's Encrypt是一個於2015年三季度推出的數字證書認證機構,旨在以自動化流程消除手動建立和安裝證書的複雜流程,並推廣使全球資訊網伺服器的加密連線無所不在,為安全網站提供免費的SSL/TLS證書。
  Let's Encrypt由網際網路安全研究小組(縮寫ISRG)提供服務。主要贊助商包括電子前哨基金會、Mozilla基金會、Akamai以及思科。2015年4月9日,ISRG與Linux基金會宣佈合作。
  用以實現新的數字證書認證機構的協議被稱為自動證書管理環境(ACME)。GitHub上有這一規範的草案,且提案的一個版本已作為一個Internet草案發布。

  Let's Encrypt宣稱這一過程將十分簡單、自動化並且免費

1.2 acme.sh

簡單來說acme.sh 實現了 acme 協議, 可以從 let‘s encrypt 生成免費的證書。
acme.sh 有以下特點:

  • 一個純粹用Shell(Unix shell)語言編寫的ACME協議客戶端。
  • 完整的ACME協議實施。 支援ACME v1和ACME v2 支援ACME v2萬用字元證書
  • 簡單,功能強大且易於使用。你只需要3分鐘就可以學習它。
  • Let's Encrypt免費證書客戶端最簡單的shell指令碼。
  • 純粹用Shell編寫,不依賴於python或官方的Let's Encrypt客戶端。
  • 只需一個指令碼即可自動頒發,續訂和安裝證書。 不需要root/sudoer訪問許可權。
  • 支援在Docker內使用,支援IPv6

2.安裝acme.sh

2.1 執行安裝

https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode
安裝很簡單, 一個命令:

curl  https://get.acme.sh | sh

指令碼會根據系統不通選擇不同的下載方式:

[[email protected] /opt] 
#wget -O -  https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh | INSTALLONLINE=1  sh
--2018-11-13 15:31:42--  https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh
正在解析主機 raw.githubusercontent.com... 151.101.0.133, 151.101.64.133, 151.101.128.133, ...
正在連線 raw.githubusercontent.com|151.101.0.133|:443... 已連線。
已發出 HTTP 請求,正在等待迴應... 200 OK
長度:168608 (165K) [text/plain]
正在儲存至: “STDOUT”

100%[======================================================================>] 168,608     --.-K/s   in 0.07s

2018-11-13 15:31:42 (2.38 MB/s) - 已寫入標準輸出 [168608/168608]

[2018年 11月 13日 星期二 15:31:42 CST] Installing from online archive.
[2018年 11月 13日 星期二 15:31:42 CST] Downloading https://github.com/Neilpang/acme.sh/archive/master.tar.gz
[2018年 11月 13日 星期二 15:31:43 CST] Extracting master.tar.gz
[2018年 11月 13日 星期二 15:31:43 CST] It is recommended to install socat first.
[2018年 11月 13日 星期二 15:31:43 CST] We use socat for standalone server if you use standalone mode.
[2018年 11月 13日 星期二 15:31:43 CST] If you don't use standalone mode, just ignore this warning.
[2018年 11月 13日 星期二 15:31:43 CST] Installing to /root/.acme.sh
[2018年 11月 13日 星期二 15:31:43 CST] Installed to /root/.acme.sh/acme.sh
[2018年 11月 13日 星期二 15:31:43 CST] Installing alias to '/root/.bashrc'
[2018年 11月 13日 星期二 15:31:43 CST] OK, Close and reopen your terminal to start using acme.sh
[2018年 11月 13日 星期二 15:31:43 CST] Installing alias to '/root/.cshrc'
[2018年 11月 13日 星期二 15:31:43 CST] Installing alias to '/root/.tcshrc'
[2018年 11月 13日 星期二 15:31:43 CST] Installing cron job
#未知資訊,已禁用 :34 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
[2018年 11月 13日 星期二 15:31:43 CST] Good, bash is found, so change the shebang to use bash as preferred.
[2018年 11月 13日 星期二 15:31:44 CST] OK
[2018年 11月 13日 星期二 15:31:44 CST] Install success!

2.2 安裝後的配置

普通使用者和 root 使用者都可以安裝使用。
安裝過程進行了以下幾步:
把 acme.sh 安裝到你的 home 目錄下:~/.acme.sh/並建立 一個 bash 的 alias, 方便你的使用:

alias acme.sh=~/.acme.sh/acme.sh
echo 'alias acme.sh=~/.acme.sh/acme.sh' >>/etc/profile

安裝過程中會自動為你建立 cronjob, 每天 0:00 點自動檢測所有的證書, 如果快過期了, 需要更新, 則會自動更新證書。

00 00 * * * root /root/.acme.sh/acme.sh --cron --home /root/.acme.sh &>/var/log/acme.sh.logs

更高階的安裝選項請參考:https://github.com/Neilpang/acme.sh/wiki/How-to-install
在該指令碼的安裝過程不會汙染已有的系統任何功能和檔案, 所有的修改都限制在安裝目錄中: ~/.acme.sh/

3.申請證書

acme.sh 實現了 acme 協議支援的所有驗證協議. 一般有兩種方式驗證: http 和 dns 驗證。

3.1 HTTP 方式

http 方式需要在你的網站根目錄下放置一個檔案, 來驗證你的域名所有權,完成驗證. 然後就可以生成證書了.

acme.sh  --issue  -d clsn.io -d *.clsn.io  --webroot  /www/wwwroot/clsn.io/

只需要指定域名, 並指定域名所在的網站根目錄.acme.sh會全自動的生成驗證檔案, 並放到網站的根目錄, 然後自動完成驗證. 最後會聰明的刪除驗證檔案. 整個過程沒有任何副作用.
如果你用的 apache伺服器,acme.sh還可以智慧的從 apache的配置中自動完成驗證, 你不需要指定網站根目錄:

acme.sh --issue  -d clsn.io   --clsn.io

如果你用的 nginx伺服器, 或者反代,acme.sh還可以智慧的從 nginx的配置中自動完成驗證, 你不需要指定網站根目錄:

acme.sh --issue  -d clsn.io  --nginx

注意, 無論是 apache 還是 nginx 模式, acme.sh在完成驗證之後, 會恢復到之前的狀態, 都不會私自更改你本身的配置. 好處是你不用擔心配置被搞壞。
該型別的配置有一個缺點, 你需要自己配置 ssl 的配置, 否則只能成功生成證書, 你的網站還是無法訪問https. 但是為了安全, 你還是自己手動改配置吧.
如果你還沒有執行任何 web 服務, 80 埠是空閒的, 那麼acme.sh還能假裝自己是一個webserver, 臨時聽在80 埠, 完成驗證:

acme.sh  --issue -d clsn.io   --standalone

更高階的用法請參考:https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert

3.2 DNS方式

這種方式的好處是, 你不需要任何伺服器, 不需要任何公網 ip, 只需要 dns 的解析記錄即可完成驗證。
這種方式的缺點是,如果不同時配置 Automatic DNS API,使用這種方式 acme.sh 將無法自動更新證書,每次都需要手動再次重新解析驗證域名所有權。

3.2.1 頒發證書

[[email protected] /opt] 
#cd /root/.acme.sh/
[[email protected] /root/.acme.sh]
#acme.sh --issue -d *.clsn.io -d clsn.io --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
[2018年 11月 13日 星期二 15:34:55 CST] Creating domain key
[2018年 11月 13日 星期二 15:34:55 CST] The domain key is here: /www/server/panel/vhost/cert/*.clsn.io/*.clsn.io.key
[2018年 11月 13日 星期二 15:34:55 CST] Multi domain='DNS:*.clsn.io,DNS:clsn.io'
[2018年 11月 13日 星期二 15:34:55 CST] Getting domain auth token for each domain
[2018年 11月 13日 星期二 15:34:56 CST] Getting webroot for domain='*.clsn.io'
[2018年 11月 13日 星期二 15:34:57 CST] Getting webroot for domain='clsn.io'
[2018年 11月 13日 星期二 15:34:57 CST] Add the following TXT record:
[2018年 11月 13日 星期二 15:34:57 CST] Domain: '_acme-challenge.clsn.io'
[2018年 11月 13日 星期二 15:34:57 CST] TXT value: '9rj0bhiGrO9UJ44XgV0APXuGBRL1vOk4XKdsnnxaIf4'
[2018年 11月 13日 星期二 15:34:57 CST] Please be aware that you prepend _acme-challenge. before your domain
[2018年 11月 13日 星期二 15:34:57 CST] so the resulting subdomain will be: _acme-challenge.clsn.io
[2018年 11月 13日 星期二 15:34:57 CST] Add the following TXT record:
[2018年 11月 13日 星期二 15:34:57 CST] Domain: '_acme-challenge.clsn.io'
[2018年 11月 13日 星期二 15:34:57 CST] TXT value: 'yJ4Ca9yVg1Fsp4RhH5XZJohh0eE3dFXEKM2KGUFNHio'
[2018年 11月 13日 星期二 15:34:57 CST] Please be aware that you prepend _acme-challenge. before your domain
[2018年 11月 13日 星期二 15:34:57 CST] so the resulting subdomain will be: _acme-challenge.clsn.io
[2018年 11月 13日 星期二 15:34:57 CST] Please add the TXT records to the domains, and re-run with --renew.
[2018年 11月 13日 星期二 15:34:57 CST] Please add '--debug' or '--log' to check more details.
[2018年 11月 13日 星期二 15:34:57 CST] See: https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh

3.2.2 修改DNS

在NS管理方修改主機記錄

3.2.3 驗證解析是否生效

$dig -t txt  _acme-challenge.clsn.io @8.8.8.8

; <<>> DiG 9.9.7-P3 <<>> -t txt _acme-challenge.clsn.io @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35785
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;_acme-challenge.clsn.io.	IN	TXT

;; ANSWER SECTION:
_acme-challenge.clsn.io. 599	IN	TXT	"yJ4Ca9yVg1Fsp4RhH5XZJohh0eE3dFXEKM2KGUFNHio"
_acme-challenge.clsn.io. 599	IN	TXT	"9rj0bhiGrO9UJ44XgV0APXuGBRL1vOk4XKdsnnxaIf4"

;; Query time: 2502 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Tue Nov 13 15:40:55 CST 2018
;; MSG SIZE  rcvd: 164

3.2.4 生成證書

獲取Let’s Encrypt免費泛域名證書。等DNS解析生效後,執行以下命令重新生成證書:

[[email protected] /root/.acme.sh]
#acme.sh --renew  -d *.clsn.io -d clsn.io --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
[2018年 11月 13日 星期二 15:39:26 CST] Renew: '*.clsn.io'
[2018年 11月 13日 星期二 15:39:26 CST] Multi domain='DNS:*.clsn.io,DNS:clsn.io'
[2018年 11月 13日 星期二 15:39:27 CST] Getting domain auth token for each domain
[2018年 11月 13日 星期二 15:39:27 CST] Verifying:*.clsn.io
[2018年 11月 13日 星期二 15:39:29 CST] Success
[2018年 11月 13日 星期二 15:39:29 CST] Verifying:clsn.io
[2018年 11月 13日 星期二 15:39:32 CST] Success
[2018年 11月 13日 星期二 15:39:32 CST] Verify finished, start to sign.
[2018年 11月 13日 星期二 15:39:33 CST] Cert success.
-----BEGIN CERTIFICATE-----
MIIFUzCCBDugAwIBAgISBFW6y9vj0CLdCtlbjd5uRZFoMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODExMTMwNjM5MzJaFw0x
OTAyMTEwNjM5MzJaMBQxEjAQBgNVBAMMCSouY2xzbi5pbzCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBANsBQz9vlST55GYdf/F9awtMqnwa2S+4nftk75NJ
s8zRLmj0LvtgZCn0fXgpNH4zAGRR3qzx7VGU80pDg539Kn8k3peoOFxRq5J3JCK2
NhvVLws7HspIsgHXngf3AyawUg+QN69K50ZDNF6/brgnOiNbmSY5fF2F9zXkNCd2
4Nsg8ptmYs3RL99ZM2CvjgLLgey3CPAuMWCse8afA4tHJ4pEZRk3dBTtWXy4q2wl
Uba8K4LuDmqOkWmQ7x3ufrq+1pQUTVQeJbKVQeDHsWQgFJVYnuHrGdd8mbz08quB
g4ruNCRnkHM1Fyxfu71IEnH1dutIeHv5OAvC3XMJUFE44kMCAwEAAaOCAmcwggJj
MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUP0ZkyUrkFWnJMVT/zGVVTfhJudgwHwYD
VR0jBBgwFoAUqEpqYwR93brm0Tm3pkVl7/Oo7KEwbwYIKwYBBQUHAQEEYzBhMC4G
CCsGAQUFBzABhiJodHRwOi8vb2NzcC5pbnQteDMubGV0c2VuY3J5cHQub3JnMC8G
CCsGAQUFBzAChiNodHRwOi8vY2VydC5pbnQteDMubGV0c2VuY3J5cHQub3JnLzAd
BgNVHREEFjAUggkqLmNsc24uaW+CB2Nsc24uaW8wTAYDVR0gBEUwQzAIBgZngQwB
AgEwNwYLKwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRz
ZW5jcnlwdC5vcmcwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdgDiaUuuJujpQAno
hhu2O4PUPuf+dIj7pI8okwGd3fHb/gAAAWcMAtr/AAAEAwBHMEUCIDn0gs520um3
dbTpgm3J/QhbjCwVG7Ln8cmONkhiA0S/AiEAqV2/kS63iMF4TGOVQ9s206OPnyx8
1sLMm7NQfGrUNsYAdgApPFGWVMg5ZbqqUPxYB9S3b79Yeily3KTDDPTlRUf0eAAA
AWcMAtsEAAAEAwBHMEUCIQDqMPOXRxylye3P2SBDP/DIeDlsa8QFcWM0lYKCmYQW
zwIgGhTWGjpMOnw4fkoygDE3mHceg+k2vqUBPTwCfu+qRNIwDQYJKoZIhvcNAQEL
BQADggEBADZWQ8ms7VG10pSQVGg98VHnRE9VfgYq+zCpoJdjVv3OZZ+3hZGkxlQU
jbpQDPdx2x2KWrhPIlSylZpw1KHFjXq5pwZpkcVjkTO5tkB4+XRsUl0dENj5HGMN
pwNRPNsiWMnvxiQgKnCpIPPVTOGsajJ5ByQA4+Vni3VNvEEAOurN024e0rfzxhYV
oXBnb7tK01+HIzoOBsOl9FRbIzkmuogjCrbjU8dBudAKPNAPmFS6bwFnYeFWO2G7
DhyNrlDFJodx8JjZ9qnzD53gCfutYzsftN3jwBBiGxRpLyWXXAQLqBN5QrkTwL+h
PFn9Tul9nibZXRIQsyutHx7jFMtAyOY=
-----END CERTIFICATE-----
[2018年 11月 13日 星期二 15:39:33 CST] Your cert is in  clsn.io/clsn.io.cer
[2018年 11月 13日 星期二 15:39:33 CST] Your cert key is in  /www/server/panel/vhost/cert/clsn.io/clsn.io.key
[2018年 11月 13日 星期二 15:39:33 CST] The intermediate CA cert is in  /www/server/panel/vhost/cert/clsn.io/ca.cer
[2018年 11月 13日 星期二 15:39:33 CST] And the full chain certs is there:  /www/server/panel/vhost/cert/clsn.io/fullchain.cer
[2018年 11月 13日 星期二 15:39:33 CST] It seems that you are using dns manual mode. please take care: The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead.
[2018年 11月 13日 星期二 15:39:33 CST] Call hook error.

注意第二次這裡用的是--renew

3.2.5 dns 方式API

dns 方式的真正強大之處在於可以使用域名解析商提供的 api 自動新增 txt 記錄完成驗證.
acme.sh 目前支援 cloudflare, dnspod, cloudxns, godaddy 以及 ovh 等數十種解析商的自動整合.
以 dnspod 為例, 你需要先登入到 dnspod 賬號, 生成你的 api id 和 api key, 都是免費的. 然後:

export DP_Id="76GJHG4SG1Q"
export DP_Key="qaEDHSJiokjhfs"
acme.sh   --issue   --dns dns_dp   -d clsn.io  -d www.clsn.io

證書就會自動生成了. 這裡給出的 api id 和 api key 會被自動記錄下來, 將來你在使用 dnspod api 的時候, 就不需要再次指定了. 直接生成就好了:

acme.sh  --issue   -d  clsn.io   --dns  dns_dp

更詳細的 api 用法:https://github.com/Neilpang/acme.sh/blob/master/dnsapi/README.md

4.證書的使用

4.1 安裝證書

前面證書生成以後, 接下來需要把證書 copy 到真正需要用它的地方。

注意, 預設生成的證書都放在安裝目錄下: ~/.acme.sh/, 請不要直接使用此目錄下的檔案,
例如: 不要直接讓 nginx/apache 的配置檔案使用這下面的檔案.
這裡面的檔案都是內部使用, 而且目錄結構可能會變化.正確的使用方法是使用 --installcert 命令,並指定目標位置, 然後證書檔案會被copy到相應的位置, 例如:

acme.sh  --installcert  -d  <domain>.com   \
    --key-file   /etc/nginx/ssl/<domain>.key \
    --fullchain-file /etc/nginx/ssl/fullchain.cer \
    --reloadcmd  "service nginx force-reload"

4.2 Nginx/Tengine伺服器安裝SSL證書

以Nginx標準配置為例,生成的證書檔案推薦使用 fullchain.cer,私鑰檔案為是clsn.io.key。

Nginx 的配置 ssl_certificate 使用 fullchain.cer ,而非.cer ,否則 SSL Labs 的測試會報 Chain issues Incomplete 錯誤。
(1)通過上述中生成的證書路徑為/www/server/panel/vhost/cert/clsn.io/;
修改配置檔案

server {
  listen 443;
  server_name localhost;
  ssl on;
  root html;
  index index.html index.htm;
  ssl_certificate   /www/server/panel/vhost/cert/clsn.io/fullchain.cer;
  ssl_certificate_key  /www/server/panel/vhost/cert/clsn.io/clsn.key;
  ssl_session_timeout 5m;
  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers on;
  location / {
    root html;
    index index.html index.htm;
  }
}

(2)重啟nginx

/etc/init.d/nginx  force-reload

__注意:__這裡用的是service nginx force-reload, 不是 service nginx reload, 據測試, reload 並不會重新載入證書, 所以用的 force-reload

5.更新

5.1 證書的更新

目前證書在 60 天以後會通過定時任務自動更新, 你無需任何操作。
今後有可能會縮短這個時間, 不過都是自動的, 你不用關心.

5.2 acme.sh 更新

目前由於 acme 協議和 letsencrypt CA 都在頻繁的更新, 因此 acme.sh 也經常更新以保持同步.
升級 acme.sh 到最新版 :

acme.sh --upgrade

如果你不想手動升級, 可以開啟自動升級:

acme.sh  --upgrade  --auto-upgrade

之後, acme.sh 就會自動保持更新了.
你也可以隨時關閉自動更新:

acme.sh --upgrade  --auto-upgrade  0

6.參考文獻

https://letsencrypt.org/
https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E