Nginx 實現全站 HTTPS(基於 Let's Encrypt 的免費通配符證書)

出處:https://blog.csdn.net/kikajack/article/details/80408145

Let’s Encrypt 在 18 年 1 月份推出了 ACME v2,支持通配符域名證書,對小網站、個人站長的友好度進一步增加。

常用的兩種安裝方式對比

ACME 協議支持的驗證協議一般有兩種:

  • http 驗證:必須有可以正常運行的服務器和公網 IP。驗證時,需要在你的網站根目錄下放一個文件來驗證域名所有權,完成驗證後就可以生成證書了。
  • dns 驗證:不需要服務器和公網 IP。只需要為域名添加一條 txt 解析記錄來驗證域名所有權。

Let’s Encrypt 通配符證書的兩種安裝方式:

  • acme.sh:對於 http 驗證,會自動在網站根目錄生成驗證文件, 然後自動完成驗證,最後自動刪除驗證文件。對於 dns 驗證,如果域名解析商提供 API,則可以自動藉助這個 API 通過工具添加 txt 記錄完成驗證(如果不提供 API 則無法自動化,目前騰訊雲、阿里雲都支持)。此外,還會自動生成更新域名的定時任務。
  • certbot-auto:對於域名驗證這一步,需要手工操作。且更新域名的定時任務也需要自己寫。

通過 acme.sh 獲取通配符域名

acme.sh 的所有相關文件(包括安裝文件、申請到的證書等)都在 ~/.acme.sh/ 這一個目錄中。

  • 安裝 acme.sh

在線安裝

地址:https://github.com/Neilpang/get.acme.sh

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

或者:

wget -O - https://get.acme.sh | sh

從Git安裝

git clone https://github.com/Neilpang/acme.sh.git

cd ./acme.sh

./acme.sh --install

安裝過程包含 3 個動作:

  • 創建並複製 acme.sh 到你的家目錄 $HOME:~/.acme.sh/。所有的證書都會放到這個目錄中
  • 創建別名: acme.sh=~/.acme.sh/acme.sh
  • 創建每天的定時任務檢查證書,如果快要到期了會自動更新

定時任務示例:

0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null

  • 驗證

安裝完成後,需要重新打開終端,acme.sh 命令才能生效。

root@v1:~# acme.sh -h

  • 生成證書

Http方式

acme.sh 會自動在網站根目錄生成驗證文件, 然後自動完成驗證,最後自動刪除驗證文件。

需要指定域名和域名對應的網站根目錄:

acme.sh --issue -d mydomain.com -d www.mydomain.com --webroot /home/wwwroot/mydomain.com/

對於 nginx 服務器,acme.sh 還可以智能的從 nginx 配置中自動完成驗證,不需要指定網站根目錄:

acme.sh --issue -d mydomain.com --nginx

域名獲取後,需要手動修改 Nginx 配置文件。

如果沒有運行任何 web 服務,80 端口是空閒的,那麼 acme.sh 可以運行為 webserver,臨時監聽 80 端口,完成驗證:

acme.sh --issue -d mydomain.com --standalone

DNS方式

如果域名解析商提供 API,則可以自動藉助這個 API 通過工具添加 txt 記錄完成驗證。

  • 對於阿里雲:

# 替換成從阿里雲獲取的 API 參數

export Ali_Key="666"

export Ali_Secret="888"

# 換成自己的域名

acme.sh --issue --dns dns_ali -d kikakika.com -d *.kikakika.com

  • 對於騰訊雲:

# 替換成從 DNSPod 獲取的 API 參數

export DP_Id="1234"

export DP_Key="sADDsdasdgdsf"

# 換成自己的域名

acme.sh --issue --dns dns_dp -d kikakika.com -d *.kikakika.com

  • 對於其他平臺

可以參考這裡:https://github.com/Neilpang/acme.sh/tree/master/dnsapi

DNS 生效需要一段時間,acme.sh 設置的是等待兩分鐘。

acme.sh 會保存 API 參數並生成定時任務,用於每天驗證證書是否即將過期,並及時更新。下面是通過 crontab -e 看到的新增的定時任務:

16 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

  • 安裝證書

證書生成後,需要把證書 copy 到真正需要用它的地方。

默認生成的證書都放在安裝目錄 ~/.acme.sh/ 下,但是請不要直接使用。而是使用 --installcert 命令安裝證書。

使用 --installcert 命令安裝證書

使用 --installcert 命令安裝證書時,證書文件會被複制到相應的位置:

acme.sh --installcert -d kikakika.com \

--key-file /etc/nginx/ssl/kikakika.key \

--fullchain-file /etc/nginx/ssl/fullchain.cer \

--reloadcmd "systemctl reload nginx.service"

示例:

[root@VM_139_74_centos ~]# acme.sh --installcert -d kikakika.com \

> --key-file /etc/nginx/ssl/kikakika.key \

> --fullchain-file /etc/nginx/ssl/fullchain.cer \

> --reloadcmd "systemctl reload nginx.service"

[Tue May 22 16:35:20 CST 2018] Installing key to:/etc/nginx/ssl/kikakika.key

[Tue May 22 16:35:20 CST 2018] Installing full chain to:/etc/nginx/ssl/fullchain.cer

[Tue May 22 16:35:20 CST 2018] Run reload cmd: systemctl reload nginx.service

[Tue May 22 16:35:20 CST 2018] Reload success

當證書更新以後,reloadcmd 中的命令會被自動調用,讓服務器加載更新後的證書。

--installcert 命令可以攜帶很多參數,來指定目標文件。這裡指定的所有參數都會被自動記錄下來, 並在將來證書自動更新以後, 被再次自動調用。

注意,對於 Nginx,需要通過 systemctl reload nginx.service 來重新加載證書。

  • 配置 Nginx

Nginx 的配置 ssl_certificate 使用 /etc/nginx/ssl/fullchain.cer,而非 /etc/nginx/ssl/.cer,否則 SSL Labs 的測試會報 Chain issues Incomplete 錯誤。

我將所有流量統一導入 https://www.kikakika.com,示例如下:

server {

listen 443 ssl;

server_name www.kikakika.com;

index index.html;

root /home/kikakika/www;

ssl on;

ssl_certificate /etc/nginx/ssl/fullchain.cer;

ssl_certificate_key /etc/nginx/ssl/kikakika.key;

ssl_session_timeout 5m;

}

server {

listen 80;

server_name www.kikakika.com;

return 301 https://$host$request_uri;

}

server {

listen 80;

server_name kikakika.com;

return 301 https://www.kikakika.com$request_uri;

}

server {

listen 443 ssl;

server_name kikakika.com;

return 301 https://www.kikakika.com$request_uri;

}

常見問題

遇到問題不要慌,通過 --debug 2 選項可以直接在終端上顯示詳細日誌:

acme.sh --issue --debug 2 --dns dns_dp -d kikakika.com -d *.kikakika.com

域名 API 需要登錄正確的解析平臺開啟

問題描述:獲取證書一直失敗,分析日誌發現有“The login token ID is invalid”這麼一句話:

...

[Tue May 22 14:43:48 CST 2018] Http already initialized.

[Tue May 22 14:43:48 CST 2018] _CURL='curl -L --silent --dump-header /root/.acme.sh/http.header --trace-ascii /tmp/tmp.LzYzrZRjvQ -g '

[Tue May 22 14:43:48 CST 2018] _ret='0'

[Tue May 22 14:43:48 CST 2018] response='{"status":{"code":"10002","message":"The login token ID is invalid","created_at":"2018-05-22 14:43:50"}}'

[Tue May 22 14:43:48 CST 2018] invalid domain

[Tue May 22 14:43:48 CST 2018] Error add txt for domain:_acme-challenge.kikakika.com

[Tue May 22 14:43:48 CST 2018] pid

[Tue May 22 14:43:48 CST 2018] No need to restore nginx, skip.

[Tue May 22 14:43:48 CST 2018] _clearupdns

[Tue May 22 14:43:48 CST 2018] skip dns.

[Tue May 22 14:43:48 CST 2018] _on_issue_err

[Tue May 22 14:43:48 CST 2018] Please check log file for more details: /root/.acme.sh/acme.sh.log

...

後來查找資料才發現,騰訊雲和 DNSPod 是兩個獨立的平臺。對於騰訊雲上的域名,域名解析並不在騰訊雲,仍然需要登錄 DNSPod 開啟 API:

Nginx 實現全站 HTTPS(基於 Let's Encrypt 的免費通配符證書)

登錄 DNSPod 添加 API 後,這次就顯示“Action completed successful”了。然後等待 120 秒,等 DNS 解析生效:

[Tue May 22 14:54:12 CST 2018] _postContentType

[Tue May 22 14:54:12 CST 2018] Http already initialized.

[Tue May 22 14:54:12 CST 2018] _CURL='curl -L --silent --dump-header /root/.acme.sh/http.header --trace-ascii /tmp/tmp.rkflZDBcOD -g '

[Tue May 22 14:54:13 CST 2018] _ret='0'

[Tue May 22 14:54:13 CST 2018] response='{"status":{"code":"1","message":"Action completed successful","created_at":"2018-05-22 14:54:15"},"record":{"id":"361406913","name":"_acme-challenge","status":"enabled","weight":null}}'

[Tue May 22 14:54:13 CST 2018] Sleep 120 seconds for the txt records to take effect

通配符域名申請的證書,不支持根域名

問題描述:對 *.kikakika.com 申請了通配符域名,但是在訪問 https://kikakika.com 是時候出問題。

解決辦法:必須在申請證書時同時指定根域名 kikakika.com 和通配符域名 *.kikakika.com 兩個域名,這樣生成的證書才是完整的通配符證書:

acme.sh --issue --debug 2 --dns dns_dp -d kikakika.com -d *.kikakika.com

下面是導致出問題的申請通配符證書的命令:

acme.sh --issue --debug 2 --dns dns_dp -d *.kikakika.com


分享到:


相關文章: