2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不再支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

18.9. 使用 SSL 安全地進行 TCP/IP 連線 #

PostgreSQL 內建支援使用SSL連線來加密客戶端/伺服器通訊,以提高安全性。這要求在客戶端和伺服器系統上都安裝了 OpenSSL,並且在編譯時啟用了 PostgreSQL 的支援(請參見 第 17 章)。

術語SSLTLS通常可以互換使用,表示使用TLS協議的安全加密連線。SSL協議是TLS協議的前身,即使SSL協議不再受支援,SSL術語仍然用於表示加密連線。SSLPostgreSQL 中與TLS互換使用。

18.9.1. 基本設定 #

SSL支援被編譯進來後,可以透過在 postgresql.conf 中將 ssl 引數設定為 on 來啟動 PostgreSQL 伺服器,從而支援使用TLS協議進行加密連線。伺服器將在相同的 TCP 埠上監聽普通連線和SSL連線,並與任何連線的客戶端協商是否使用SSL。預設情況下,這是由客戶端選擇的;請參見 第 20.1 節,瞭解如何設定伺服器以強制對某些或所有連線使用SSL

要在SSL模式下啟動,必須存在包含伺服器證書和私鑰的檔案。預設情況下,這些檔案應命名為 server.crtserver.key,位於伺服器的資料目錄中,但可以使用配置引數 ssl_cert_filessl_key_file 指定其他名稱和位置。

在 Unix 系統上,server.key 的許可權必須禁止對任何人或組的訪問;透過命令 chmod 0600 server.key 實現。或者,該檔案可以由 root 擁有並具有組讀取許可權(即 0640 許可權)。這種設定適用於證書和金鑰檔案由作業系統管理的安裝。執行 PostgreSQL 伺服器的使用者應成為有權訪問這些證書和金鑰檔案的組的成員。

如果資料目錄允許組讀取許可權,那麼為了符合上述安全要求,證書檔案可能需要存放在資料目錄之外。通常,啟用組訪問是為了允許非特權使用者備份資料庫,在這種情況下,備份軟體將無法讀取證書檔案,並可能報錯。

如果私鑰受密碼保護,伺服器將提示輸入密碼,並且在輸入之前不會啟動。預設情況下,使用密碼會停用在伺服器重新啟動而不重啟伺服器的情況下更改伺服器 SSL 配置的能力,但請參見 ssl_passphrase_command_supports_reload。此外,在 Windows 上完全無法使用受密碼保護的私鑰。

server.crt 中的第一個證書必須是伺服器的證書,因為它必須與伺服器的私鑰匹配。還可以將“中間”證書頒發機構的證書附加到該檔案中。這樣做可以避免在客戶端儲存中間證書的必要性,前提是根證書和中間證書是用 v3_ca 擴充套件建立的。(這會將證書的 CA 基本約束設定為 true。)這使得中間證書的過期更容易。

無需將根證書新增到 server.crt。相反,客戶端必須擁有伺服器證書鏈的根證書。

18.9.2. OpenSSL 配置 #

PostgreSQL 讀取系統範圍的 OpenSSL 配置檔案。預設情況下,該檔名為 openssl.cnf,位於 openssl version -d 報告的目錄中。可以透過將環境變數 OPENSSL_CONF 設定為所需配置檔案的名稱來覆蓋此預設值。

OpenSSL 支援各種密碼和認證演算法,強度各不相同。雖然可以在 OpenSSL 配置檔案中指定密碼列表,但您可以透過修改 postgresql.conf 中的 ssl_ciphers 來指定供資料庫伺服器專用的密碼。

注意

可以透過使用 NULL-SHANULL-MD5 密碼來實現無加密開銷的認證。然而,中間人可能會讀取和傳遞客戶端與伺服器之間的通訊。此外,與認證開銷相比,加密開銷很小。由於這些原因,不推薦使用 NULL 密碼。

18.9.3. 使用客戶端證書 #

要強制客戶端提供受信任的證書,請將您信任的根證書頒發機構(CA)的證書放在資料目錄中的一個檔案中,在 postgresql.conf 中將 ssl_ca_file 引數設定為新檔名,並在 pg_hba.conf 的適當 hostssl 行中新增認證選項 clientcert=verify-caclientcert=verify-full。然後在 SSL 連線啟動時會向客戶端請求證書。(有關如何在客戶端設定證書的說明,請參見 第 32.19 節。)

對於具有 clientcert=verify-cahostssl 條目,伺服器將驗證客戶端證書是否由受信任的證書頒發機構之一簽名。如果指定了 clientcert=verify-full,伺服器不僅會驗證證書鏈,還會檢查使用者名稱或其對映是否與提供的證書的 cn(公用名)匹配。請注意,當使用 cert 認證方法時(參見 第 20.12 節),始終確保證書鏈的驗證。

如果您希望避免在客戶端儲存中間證書,可以將連結到現有根證書的中間證書頒發機構也包含在 ssl_ca_file 檔案中(前提是根證書和中間證書是用 v3_ca 擴充套件建立的)。如果設定了 ssl_crl_filessl_crl_dir 引數,還會檢查證書吊銷列表(CRL)條目。

clientcert 認證選項可用於所有認證方法,但僅限於 pg_hba.conf 中指定為 hostssl 的行。當未指定 clientcert 時,如果提供了客戶端證書並且配置了 CA,伺服器才會根據其 CA 檔案驗證客戶端證書。

有兩種方法可以強制使用者在登入時提供證書。

第一種方法利用 pg_hba.confhostssl 條目的 cert 認證方法,這樣證書本身就可以用於認證,同時提供 SSL 連線安全。有關詳細資訊,請參見 第 20.12 節。(在使用 cert 認證方法時,無需顯式指定任何 clientcert 選項。)在這種情況下,證書中提供的 cn(公用名)會與使用者名稱或適用的對映進行比較。

第二種方法將 hostssl 條目的任何認證方法與透過將 clientcert 認證選項設定為 verify-caverify-full 來驗證客戶端證書相結合。前一個選項僅強制證書有效,而後者還確保證書中的 cn(公用名)與使用者名稱或適用的對映匹配。

18.9.4. SSL 伺服器檔案使用 #

表 18.2 總結了與伺服器上的 SSL 設定相關的檔案的資訊。(顯示的檔名是預設名稱。本地配置的名稱可能不同。)

表 18.2. SSL 伺服器檔案使用

檔案 目錄 效果
ssl_cert_file$PGDATA/server.crt 伺服器證書 傳送給客戶端以指示伺服器的身份
ssl_key_file$PGDATA/server.key 伺服器私鑰 證明伺服器證書由所有者傳送;不表示證書所有者值得信賴
ssl_ca_file 受信任的證書頒發機構 檢查客戶端證書是否由受信任的證書頒發機構簽名
ssl_crl_file 證書頒發機構吊銷的證書 客戶端證書不得在此列表中

伺服器在啟動時以及每次伺服器配置重新載入時都會讀取這些檔案。在 Windows 系統上,每次為新的客戶端連線生成新的後端程序時也會重新讀取它們。

如果在伺服器啟動時檢測到這些檔案中的錯誤,伺服器將拒絕啟動。但如果在配置重新載入期間檢測到錯誤,則會忽略這些檔案,並繼續使用舊的 SSL 配置。在 Windows 系統上,如果在後端啟動時檢測到這些檔案中的錯誤,則該後端將無法建立 SSL 連線。在所有這些情況下,錯誤情況都會在伺服器日誌中報告。

18.9.5. 建立證書 #

要為伺服器建立簡單的自簽名證書,有效期為 365 天,請使用以下 OpenSSL 命令,將 dbhost.yourdomain.com 替換為伺服器的主機名

openssl req -new -x509 -days 365 -nodes -text -out server.crt \
  -keyout server.key -subj "/CN=dbhost.yourdomain.com"

然後執行

chmod og-rwx server.key

因為如果檔案的許可權過於寬鬆,伺服器將拒絕該檔案。有關如何建立伺服器私鑰和證書的更多詳細資訊,請參閱 OpenSSL 文件。

雖然自簽名證書可用於測試,但在生產環境中應使用由證書頒發機構(CA)組成的證書(通常是企業級的根證書CA)。

要建立一個可以由客戶端驗證身份的伺服器證書,首先建立一個證書籤名請求(CSR)和一個公鑰/私鑰檔案

openssl req -new -nodes -text -out root.csr \
  -keyout root.key -subj "/CN=root.yourdomain.com"
chmod og-rwx root.key

然後,使用金鑰對請求進行簽名以建立根證書頒發機構(使用 Linux 上的預設 OpenSSL 配置檔案位置)

openssl x509 -req -in root.csr -text -days 3650 \
  -extfile /etc/ssl/openssl.cnf -extensions v3_ca \
  -signkey root.key -out root.crt

最後,建立一個由新的根證書頒發機構簽名的伺服器證書

openssl req -new -nodes -text -out server.csr \
  -keyout server.key -subj "/CN=dbhost.yourdomain.com"
chmod og-rwx server.key

openssl x509 -req -in server.csr -text -days 365 \
  -CA root.crt -CAkey root.key -CAcreateserial \
  -out server.crt

server.crtserver.key 應儲存在伺服器上,而 root.crt 應儲存在客戶端上,以便客戶端可以驗證伺服器的葉子證書是否由其受信任的根證書籤名。root.key 應離線儲存,用於建立將來的證書。

也可以建立包含中間證書的信任鏈

# root
openssl req -new -nodes -text -out root.csr \
  -keyout root.key -subj "/CN=root.yourdomain.com"
chmod og-rwx root.key
openssl x509 -req -in root.csr -text -days 3650 \
  -extfile /etc/ssl/openssl.cnf -extensions v3_ca \
  -signkey root.key -out root.crt

# intermediate
openssl req -new -nodes -text -out intermediate.csr \
  -keyout intermediate.key -subj "/CN=intermediate.yourdomain.com"
chmod og-rwx intermediate.key
openssl x509 -req -in intermediate.csr -text -days 1825 \
  -extfile /etc/ssl/openssl.cnf -extensions v3_ca \
  -CA root.crt -CAkey root.key -CAcreateserial \
  -out intermediate.crt

# leaf
openssl req -new -nodes -text -out server.csr \
  -keyout server.key -subj "/CN=dbhost.yourdomain.com"
chmod og-rwx server.key
openssl x509 -req -in server.csr -text -days 365 \
  -CA intermediate.crt -CAkey intermediate.key -CAcreateserial \
  -out server.crt

server.crtintermediate.crt 應連線成一個證書檔案包並存儲在伺服器上。server.key 也應儲存在伺服器上。root.crt 應儲存在客戶端上,以便客戶端可以驗證伺服器的葉子證書是否是由連結到其受信任根證書的證書鏈簽名的。root.keyintermediate.key 應離線儲存,用於建立將來的證書。

提交更正

如果您在文件中發現任何不正確之處、與您對特定功能的體驗不符或需要進一步闡明的內容,請使用 此表格 報告文件問題。