關於 HTTPS¶
人們很容易以為 HTTPS 只是單純「啟用」或「不啟用」的功能。
但實際上它比這複雜得多。
小技巧
如果您趕時間或不在意細節,請直接跳到下一節,按照步驟指示使用不同技術進行設定。
若要**學習 HTTPS 的基礎知識**(從使用者的角度),請參考 https://howhttps.works/。
現在,從**開發者的角度**來看,在考慮 HTTPS 時,需要牢記以下幾點:
- 對於 HTTPS,**伺服器**需要擁有由**第三方**產生的**「憑證」**。
- 這些憑證實際上是從第三方**取得**的,而不是「產生」的。
- 憑證具有**有效期限**。
- 它們會**過期**。
- 然後它們需要**續期**,再次從第三方**取得**。
- 連線的加密發生在**TCP 層級**。
- 這是**HTTP 之下**的一層。
- 因此,**憑證和加密**的處理是在**HTTP 之前**完成的。
- **TCP 不知道「網域」**。它只知道 IP 位址。
- 關於所請求的**特定網域**的資訊包含在**HTTP 資料**中。
- **HTTPS 憑證**「驗證」**特定網域**,但協定和加密發生在 TCP 層級,在**知道**正在處理哪個網域**之前**。
- **預設情況下**,這表示每個 IP 位址只能有一個**HTTPS 憑證**。
- 無論您的伺服器有多大,或您在其上執行的每個應用程式有多小。
- 然而,這有一個**解決方案**。
- **TLS** 協定(在 HTTP 之前於 TCP 層級處理加密的協定)有一個稱為 **SNI** 的**擴充功能**。
- 此 SNI 擴充功能允許單個伺服器(具有**單個 IP 位址**)擁有**多個 HTTPS 憑證**,並服務**多個 HTTPS 網域/應用程式**。
- 要使其運作,在伺服器上執行的**單個**元件(程式),監聽**公開 IP 位址**,必須擁有伺服器中的**所有 HTTPS 憑證**。
- 在取得安全連線**之後**,通訊協定**仍然是 HTTP**。
- 內容是**加密的**,即使它們是使用**HTTP 協定**傳送的。
常見的做法是在伺服器(機器、主機等)上執行**一個程式/HTTP 伺服器**,並**管理所有 HTTPS 部分**:接收**加密的 HTTPS 請求**,將**解密的 HTTP 請求**傳送到在同一個伺服器中執行的實際 HTTP 應用程式(在這種情況下是**FastAPI** 應用程式),從應用程式取得**HTTP 回應**,使用適當的**HTTPS 憑證**對其進行**加密**,並使用**HTTPS**將其發送回客戶端。這個伺服器通常稱為**TLS 終止代理伺服器**。
您可以用作 TLS 終止代理伺服器的一些選項是:
- Traefik(也可以處理憑證續期)
- Caddy(也可以處理憑證續期)
- Nginx
- HAProxy
Let's Encrypt¶
在 Let's Encrypt 出現之前,這些**HTTPS 憑證**是由受信任的第三方販售的。
取得這些憑證的過程過去很繁瑣,需要大量的文書作業,而且憑證價格相當昂貴。
但是後來Let's Encrypt出現了。
它是由 Linux 基金會推動的一個專案,以自動化的方式免費提供 HTTPS 憑證。這些憑證使用所有標準的加密安全性,而且有效期限短(約 3 個月),因此由於生命週期縮短,安全性實際上更好。
網域經過安全驗證,憑證會自動產生。這也允許自動續期這些憑證。
其理念是自動化取得和更新這些憑證,讓您可以永遠免費擁有安全的 HTTPS。
開發人員的 HTTPS¶
以下逐步說明 HTTPS API 的範例,主要關注對開發人員重要的概念。
網域名稱¶
這一切可能從您取得一些網域名稱開始。然後,您會在 DNS 伺服器(可能是您相同的雲端供應商)中設定它。
您可能會取得一台雲端伺服器(虛擬機器)或類似設備,它會有一個固定的公開 IP 位址。
在 DNS 伺服器中,您會設定一條記錄(「A 記錄
」),將您的網域指向伺服器的公開IP 位址。
您可能只會在第一次設定所有內容時執行一次。
小技巧
這個網域名稱部分遠早於 HTTPS,但由於一切都取決於網域和 IP 位址,因此值得在此提及。
DNS¶
現在讓我們專注於所有實際的 HTTPS 部分。
首先,瀏覽器會向DNS 伺服器查詢網域的 IP,在本例中為 someapp.example.com
。
DNS 伺服器會告知瀏覽器使用特定的IP 位址。這將是您在 DNS 伺服器中設定的伺服器所使用的公開 IP 位址。
TLS 握手開始¶
然後,瀏覽器會透過連接埠 443(HTTPS 連接埠)與該 IP 位址通訊。
通訊的第一部分只是建立用戶端和伺服器之間的連線,並決定他們將使用的加密金鑰等。
用戶端和伺服器之間建立 TLS 連線的這種互動稱為TLS 握手。
具有 SNI 擴展的 TLS¶
在特定IP 位址的特定連接埠上,伺服器中只能有一個行程在監聽。在同一個 IP 位址的其他連接埠上可能還有其他行程在監聽,但每個 IP 位址和連接埠的組合只能有一個。
TLS (HTTPS) 預設使用特定的連接埠 443
。所以這就是我們需要的連接埠。
由於只有一個行程可以監聽此連接埠,因此執行此操作的行程將是TLS 終止代理伺服器。
TLS 終止代理伺服器可以存取一個或多個TLS 憑證(HTTPS 憑證)。
使用上述的SNI 擴展,TLS 終止代理伺服器會檢查應該為此連線使用哪些可用的 TLS (HTTPS) 憑證,使用與用戶端預期網域相符的憑證。
在本例中,它會使用 someapp.example.com
的憑證。
用戶端已經信任產生該 TLS 憑證的實體(在本例中為 Let's Encrypt,但我們稍後會再說明),因此它可以驗證憑證是否有效。
接著,客戶端和 TLS 終止代理伺服器會使用憑證來**決定如何加密**其餘的**TCP 通訊**。這就完成了**TLS 握手**的部分。
之後,客戶端和伺服器之間就會建立一個**加密的 TCP 連線**,這就是 TLS 所提供的。然後它們就可以使用該連線來開始實際的**HTTP 通訊**。
這就是**HTTPS**的原理,它只是在**安全的 TLS 連線**內進行普通的**HTTP**通訊,而不是在純(未加密的)TCP 連線內進行。
小技巧
請注意,通訊的加密發生在**TCP 層級**,而不是 HTTP 層級。
HTTPS 請求¶
現在客戶端和伺服器(具體來說是瀏覽器和 TLS 終止代理伺服器)之間已經建立了**加密的 TCP 連線**,它們就可以開始**HTTP 通訊**了。
因此,客戶端會發送一個**HTTPS 請求**。這只是一個通過加密 TLS 連線的 HTTP 請求。
解密請求¶
TLS 終止代理伺服器會使用先前約定的加密方式來**解密請求**,並將**純(已解密的)HTTP 請求**傳輸到運行應用程式的程序(例如,使用 Uvicorn 運行 FastAPI 應用程式的程序)。
HTTP 回應¶
應用程式會處理請求,並將**純(未加密的)HTTP 回應**發送回 TLS 終止代理伺服器。
HTTPS 回應¶
然後,TLS 終止代理伺服器會使用先前約定的加密方式(以 `someapp.example.com` 的憑證開始)**加密回應**,並將其發送回瀏覽器。
接下來,瀏覽器會驗證回應是否有效,以及是否使用正確的加密金鑰加密等等。然後它會**解密回應**並進行處理。
客戶端(瀏覽器)會知道回應來自正確的伺服器,因為它使用了先前透過**HTTPS 憑證**約定的加密方式。
多個應用程式¶
在同一伺服器(或多台伺服器)上,可以有多個**應用程式**,例如,其他 API 程式或資料庫。
只有一個程序可以處理特定的 IP 和連接埠(在我們的範例中是 TLS 終止代理伺服器),但其他應用程式/程序也可以在伺服器上運行,只要它們不嘗試使用相同的**公用 IP 和連接埠組合**即可。
這樣,TLS 終止代理伺服器就可以為多個應用程式處理多個**網域**的 HTTPS 和憑證,然後在每種情況下將請求傳輸到正確的應用程式。
憑證續期¶
每個憑證在未來某個時間點都會**過期**(大約在取得憑證後 3 個月)。
然後,會有另一個程式(在某些情況下是另一個程式,在某些情況下可能是相同的 TLS 終止代理伺服器)與 Let's Encrypt 通訊,並續期憑證。
**TLS 憑證**是與**網域名稱**關聯的,而不是與 IP 位址關聯的。
因此,要續期憑證,續期程式需要向憑證授權單位(Let's Encrypt)**證明**它確實**「擁有」並控制該網域**。
為此,並為了適應不同的應用程式需求,它可以透過幾種方式來完成。一些常見的方式是
- 修改一些 DNS 記錄.
- 為了實現這個目標,憑證更新程式需要支援 DNS 供應商的 API,因此,根據您使用的 DNS 供應商,這可能是一個選項,也可能不是。
- 在與網域關聯的公共 IP 位址上以伺服器模式運行(至少在憑證獲取過程中)。
- 如上所述,只有一個程序可以監聽特定的 IP 和埠。
- 這就是為什麼當同一個 TLS 終止代理也負責憑證更新過程時,它非常有用的原因之一。
- 否則,您可能需要暫時停止 TLS 終止代理,啟動更新程式以獲取憑證,然後使用 TLS 終止代理配置它們,最後重新啟動 TLS 終止代理。這並不理想,因為在 TLS 終止代理關閉期間,您的應用程式將無法使用。
所有這些更新過程,在應用程式仍在服務的同時進行,是您需要一個獨立的系統來處理 HTTPS 並使用 TLS 終止代理,而不是僅直接在應用程式伺服器(例如 Uvicorn)上使用 TLS 憑證的主要原因之一。
摘要¶
擁有HTTPS 非常重要,而且在大多數情況下都相當關鍵。作為開發人員,您在 HTTPS 方面需要付出的絕大部分努力只是理解這些概念以及它們的工作原理。
但是,一旦您了解了開發人員適用的 HTTPS 的基本資訊,您就可以輕鬆地組合和配置不同的工具,以簡單的方式管理一切。
在接下來的幾章中,我將向您展示幾個為FastAPI 應用程式設定HTTPS 的具體範例。 🔒