W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
PostgreSQL本地支持使用SSL連接加密客戶端/服務(wù)器通信以提高安全性。關(guān)于服務(wù)器端的SSL功能詳見第 18.9 節(jié)。
libpq讀取系統(tǒng)范圍的OpenSSL配置文件。默認(rèn)情況下,這個文件被命名為openssl.cnf
并且位于openssl version -d
所報告的目錄中??梢酝ㄟ^設(shè)置環(huán)境變量OPENSSL_CONF
把這個默認(rèn)值覆蓋為想要的配置文件的名稱。
默認(rèn)情況下,PostgreSQL將不會執(zhí)行服務(wù)器證書的任何驗證。這意味著可以在不被客戶端知曉的情況下偽造服務(wù)器身份(例如通過修改一個 DNS 記錄或者接管服務(wù)器的 IP 地址)。為了阻止哄騙,客戶端必須能夠通過一條信任鏈驗證服務(wù)器的身份。信任鏈可以這樣建立:在一臺計算機上放置一個根(自簽名的)證書機構(gòu)(CA)的證書并且在另一臺計算機上放置一個由根證書 簽發(fā) 的葉子證書。還可以使用一種“中間”證書,它由根證書簽發(fā)并且可以簽發(fā)葉子證書。
為了允許客戶端驗證服務(wù)器的身份,在客戶端上放置一份根證書并且在服務(wù)器上放置由根證書簽發(fā)的葉子證書。為了允許服務(wù)器驗證客戶端的身份,在服務(wù)器上放置一份根證書并且在客戶端上放置由根證書簽發(fā)的葉子證書。也可以使用一個或者更多個中間證書(通常與葉子證書存在一起)來將葉子證書鏈接到根證書。
一旦信任鏈被建立起來,客戶端有兩種方法驗證服務(wù)器發(fā)過來的葉子證書。如果參數(shù)sslmode
被設(shè)置為verify-ca
,libpq將通過檢查該證書是否鏈接到存儲在客戶端上的根證書來驗證服務(wù)器。如果sslmode
被設(shè)置為verify-full
,libpq還將驗證服務(wù)器的主機名匹配存儲在服務(wù)器證書中的名稱。如果服務(wù)器證書無法被驗證,則SSL連接將失敗。在大部分對安全性很敏感的環(huán)境中,推薦使用
verify-full
。
在verify-full
模式中,主機名被拿來與證書的主體別名屬性 匹配,或者在不存在類型dNSName
的主體別名時與通用名稱屬性匹配。 如果證書的名稱屬性以一個星號(*
)開始,這個星號將被 視作一個通配符,它將匹配所有除了句點(.
)
之外的字符。這意味著該證書將不會匹配子域。如果連接是使用一個 IP 地址而不是一個主機名創(chuàng)建的,該 IP 地址將被匹配(不做任何 DNS 查找)。
要允許服務(wù)器證書驗證,必須將一個或者更多個根證書放置在用戶主目錄下的~/.postgresql/root.crt
文件中(在Microsoft Windows上該文件名為%APPDATA%\postgresql\root.crt
)。如果需要把服務(wù)器發(fā)來的證書鏈鏈接到存儲在客戶端的根證書,還應(yīng)該將中間證書加到該文件中。
如果文件~/.postgresql/root.crl
存在(微軟 Windows 上的%APPDATA%\postgresql\root.crl
),證書撤銷列表(CRL)項也會被檢查。
根證書文件和 CRL 的位置可以通過設(shè)置連接參數(shù)sslrootcert
和sslcrl
或環(huán)境變量PGSSLROOTCERT
和PGSSLCRL
改變。
為了與 PostgreSQL 的早期版本達(dá)到向后兼容,如果存在一個根 CA 文件,sslmode
=require
的行為將與verify-ca
相同,即服務(wù)器證書根據(jù) CA 驗證。我們鼓勵依賴這種行為,并且需要證書驗證的應(yīng)用應(yīng)該總是使用verify-ca
或者verify-full
。
如果服務(wù)器嘗試通過請求客戶端的葉子證書來驗證客戶端的身份,libpq將發(fā)送用戶主目錄下文件~/.postgresql/postgresql.crt
中存儲的證書。該證書必須鏈接到該服務(wù)器信任的根證書。也必須存在一個匹配的私鑰文件~/.postgresql/postgresql.key
。該私鑰文件不能允許全部用戶或者組用戶的任何訪問,可以通過命令
chmod 0600 ~/.postgresql/postgresql.key
實現(xiàn)。在微軟 Windows 上這些文件被命名為%APPDATA%\postgresql\postgresql.crt
和%APPDATA%\postgresql\postgresql.key
,不會有特別的權(quán)限檢查,因為該目錄已經(jīng)被假定為安全。證書和密鑰文件的位置可以使用連接參數(shù)
sslcert
和sslkey
或者環(huán)境變量PGSSLCERT
和PGSSLKEY
覆蓋。
postgresql.crt
中的第一個證書必須是客戶端的證書,因為它必須匹配客戶端的私鑰。可以選擇將“中間”證書追加到該文件 — 這樣做避免了在服務(wù)器上存放中間證書的要求(ssl_ca_file)。
證書和密鑰可能是 PEM 或 ASN.1 DER 格式。
密鑰可以以明文存儲,也可以使用OpenSSL支持的任何算法(例如AES-128)使用密碼進(jìn)行加密。 如果密鑰是加密存儲的,那么可以在sslpassword連接選項中提供密碼。 如果提供了加密密鑰,而且sslpassword
選項不存在或為空,如果TTY可用,那么OpenSSL將交互式地以
Enter PEM pass phrase:
提示輸入密碼。 應(yīng)用程序可以越過客戶端證書提示和sslpassword
參數(shù)的處理,通過提供它們自己的密鑰密碼回調(diào);參見PQsetSSLKeyPassHook_OpenSSL
。
創(chuàng)建證書的指令請參考第 18.9.5 節(jié)。
sslmode
參數(shù)的不同值提供了不同級別的保護(hù)。SSL 能夠針對三類攻擊提供保護(hù):
如果一個第三方能夠檢查客戶端和服務(wù)器之間的網(wǎng)絡(luò)流量,它能讀取連接信息(包括用戶名和口令)以及被傳遞的數(shù)據(jù)。SSL使用加密來阻止這種攻擊。
如果一個第三方能對客戶端和服務(wù)器之間傳送的數(shù)據(jù)進(jìn)行修改,它就能假裝是服務(wù)器并且因此能看見并且修改數(shù)據(jù),即使這些數(shù)據(jù)已被加密。然后第三方可以將連接信息和數(shù)據(jù)轉(zhuǎn)送給原來的服務(wù)器,使得它不可能檢測到攻擊。這樣做的通常途徑包括 DNS 污染和地址劫持,借此客戶端被重定向到一個不同的服務(wù)器。還有幾種其他的攻擊方式能夠完成這種攻擊。SSL使用證書驗證讓客戶端認(rèn)證服務(wù)器,就可以阻止這種攻擊。
如果一個第三方能假裝是一個授權(quán)的客戶端,它能夠簡單地訪問它本不能訪問的數(shù)據(jù)。通常這可以由不安全的口令管理所致。SSL使用客戶端證書來確保只有持有合法證書的客戶端才能訪問服務(wù)器,這樣就能阻止這種攻擊。
對于一個已知的SSL-secured連接,在連接被建立之前,SSL 使用必須被配置在客戶端和服務(wù)器之上。如果只在服務(wù)器上配置,客戶端在知道服務(wù)器要求高安全性之前可能會結(jié)束發(fā)送敏感信息(例如口令)。在 libpq 中,要確保連接安全,可以設(shè)置sslmode
參數(shù)為verify-full
或verify-ca
并且為系統(tǒng)提供一個根證書用來驗證。這類似于使用一個
https
URL進(jìn)行加密網(wǎng)頁瀏覽。
一旦服務(wù)器已經(jīng)被認(rèn)證,客戶端可以傳遞敏感數(shù)據(jù)。這意味著直到這一點,客戶端都不需要知道是否證書將被用于認(rèn)證,這樣只需要在服務(wù)器配置中指定就比較安全。
所有SSL選項都帶來了加密和密鑰交換的負(fù)荷,因此必須在性能和安全性之間做出平衡。表 33.1不同sslmode
值所保護(hù)的風(fēng)險,以及它們是怎樣看待安全性和負(fù)荷的。
表 33.1. SSL 模式描述
sslmode
|
竊聽保護(hù) | MITM保護(hù) | 聲明 |
---|---|---|---|
disable
|
No | No | 我不關(guān)心安全性,并且我不想為加密增加負(fù)荷。 |
allow
|
可能 | No | 我不關(guān)心安全性,但如果服務(wù)器堅持,我將承擔(dān)加密帶來的負(fù)荷。 |
prefer
|
可能 | No | 我不關(guān)心安全性,但如果服務(wù)器支持,我希望承擔(dān)加密帶來的負(fù)荷。 |
require
|
Yes | No | 我想要對數(shù)據(jù)加密,并且我接受因此帶來的負(fù)荷。我信任該網(wǎng)絡(luò)會保證我總是連接到想要連接的服務(wù)器。 |
verify-ca
|
Yes | Depends on CA policy | 我想要對數(shù)據(jù)加密,并且我接受因此帶來的負(fù)荷。我想要確保我連接到的是我信任的服務(wù)器。 |
verify-full
|
Yes | Yes | 我想要對數(shù)據(jù)加密,并且我接受因此帶來的負(fù)荷。我想要確保我連接到的是我信任的服務(wù)器,并且就是我指定的那一個。 |
verify-ca
和verify-full
之間的區(qū)別取決于根CA
的策略。如果使用了一個公共CA
,verify-ca
允許連接到那些可能已經(jīng)被其他人注冊到該
CA
的服務(wù)器。在這種情況下,總是應(yīng)該使用verify-full
。如果使用了一個本地CA
或者甚至是一個自簽名的證書,使用verify-ca
常常就可以提供足夠的保護(hù)。
sslmode
的默認(rèn)值是prefer
。如表中所示,這在安全性的角度來說沒有意義,并且它只承諾可能的性能負(fù)荷。提供它作為默認(rèn)值只是為了向后兼容,并且我們不推薦在安全部署中使用它。
表 33.2總結(jié)了與客戶端 SSL 設(shè)置相關(guān)的文件。
表 33.2. Libpq/客戶端 SSL 文件用法
文件 | 內(nèi)容 | 效果 |
---|---|---|
~/.postgresql/postgresql.crt
|
客戶端證書 | 發(fā)送到服務(wù)器 |
~/.postgresql/postgresql.key
|
客戶端私鑰 | 證明客戶端證書是由擁有者發(fā)送;不代表證書擁有者可信 |
~/.postgresql/root.crt
|
可信的證書機構(gòu) | 檢查服務(wù)器證書是由一個可信的證書機構(gòu)簽發(fā) |
~/.postgresql/root.crl
|
被證書機構(gòu)撤銷的證書 | 服務(wù)器證書不能在這個列表上 |
如果你的應(yīng)用初始化libssl
或libcrypto
庫以及帶有SSL支持的libpq, 你應(yīng)該調(diào)用 PQinitOpenSSL
來告訴
libpq:libssl
或libcrypto
庫已經(jīng)被你的應(yīng)用初始化,這樣libpq將不會也去初始化那些庫。
PQinitOpenSSL
允許應(yīng)用選擇要初始化哪個安全性庫。
void PQinitOpenSSL(int do_ssl, int do_crypto);
當(dāng)do_ssl
是非零時,libpq將在第一次打開數(shù)據(jù)庫連接前初始化OpenSSL庫。當(dāng)do_crypto
是非零時,libcrypto
庫將被初始化。默認(rèn)情況下(如果沒有調(diào)用
PQinitOpenSSL
),兩個庫都會被初始化。當(dāng) SSL 支持沒有被編譯時,這個函數(shù)也存在但是什么也不做。
如果你的應(yīng)用使用并且初始化OpenSSL或者它的底層libcrypto
庫,你必須在第一次打開數(shù)據(jù)庫連接前以合適的非零參數(shù)調(diào)用這個函數(shù)。同時要確保在打開一個數(shù)據(jù)庫連接前已經(jīng)完成了初始化。
PQinitSSL
允許應(yīng)用選擇要初始化哪個安全性庫。
void PQinitSSL(int do_ssl);
這個函數(shù)等效于PQinitOpenSSL(do_ssl, do_ssl)
。這對于要么初始化OpenSSL以及libcrypto
要么都不初始化的應(yīng)用足夠用了。
PQinitSSL
從PostgreSQL 8.0 就存在了, 而PQinitOpenSSL
直到
PostgreSQL8.4 才被加入,因此PQinitSSL
可能對那些需要與舊版本libpq一起工作的應(yīng)用來說更合適。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: