?
This document uses PHP Chinese website manual Release
PostgreSQL本機(jī)支持使用SSL連接對(duì)客戶端/服務(wù)器通訊進(jìn)行加密, 以增強(qiáng)安全性。參閱Section 17.8獲取有關(guān)服務(wù)器端SSL功能的細(xì)節(jié)。
libpq讀取全系統(tǒng) OpenSSL配置文件,默認(rèn)情況下,文件命名 為openssl.cnf并且存放在openssl version -d 目錄報(bào)告中,此默認(rèn)可以通過設(shè)置環(huán)境變量OPENSSL_CONF覆蓋配置名稱文件名稱。
缺省,PostgreSQL不會(huì)執(zhí)行任何服務(wù)器證書驗(yàn)證。 這就意味著可以在客戶端沒有察覺的情況下騙過服務(wù)認(rèn)證(如,通過修改一個(gè)DNS記錄或接管服務(wù)IP)。 為了避免這種情況,必須使用SSL證書認(rèn)證。
如果sslmode參數(shù)設(shè)置為verify-ca,libpq將通過檢查受信任的證書頒發(fā)機(jī)構(gòu)的證書鏈(CA)來通過 服務(wù)是可信任的。如果sslmode設(shè)置為verify-full,libpq會(huì)通過驗(yàn)證服務(wù)主機(jī)名匹配認(rèn)證來認(rèn)為服務(wù)是可信任的。 如果服務(wù)驗(yàn)證不能被通過,那么SSL連接會(huì)失敗。在大多數(shù)對(duì)安全要求較高的環(huán)境中,建議使用verify-full。
在verify-full模式下,認(rèn)證的cn(Common Name)屬性與主機(jī)名進(jìn)行匹配。 如果cn以*開始,會(huì)被看做是一個(gè)通配符,并且會(huì)匹配除了.之外的所有字符。 這就意味著認(rèn)證不會(huì)匹配子域名。如果是使用IP而不是主機(jī)名進(jìn)行連接,會(huì)進(jìn)行IP匹配檢查(不會(huì)做DNS檢查)。
為了允許服務(wù)器認(rèn)證通過,一個(gè)或多個(gè)信任的CA認(rèn)證必須放在用戶的home目錄下的~/.postgresql/root.crt文件中。 Windows下的文件名是%APPDATA%\postgresql\root.crt。
如果存在~/.postgresql/root.crl文件(Windows下是%APPDATA%\postgresql\root.crl文件),同樣也會(huì)檢查CRL。
root認(rèn)證文件和CRL的位置可以通過設(shè)置sslrootcert和sslcrl連接參數(shù),或PGSSLROOTCERT和PGSSLCRL環(huán)境變量進(jìn)行修改。
如果服務(wù)器要求一個(gè)信任的客戶端認(rèn)證,libpq將發(fā)送存儲(chǔ)在~/.postgresql/postgresql.crt文件中的 證書。該認(rèn)證必須通過一個(gè)或多個(gè)服務(wù)器信任的CA認(rèn)證。 同時(shí)也必須出示一個(gè)匹配的私鑰文件~/.postgresql/postgresql.key。 私鑰文件不允許任何對(duì)世界或組的訪問;通過chmod 0600 ~/.postgresql/postgresql.key命令可以實(shí)現(xiàn)。 在Windows上,這個(gè)文件是%APPDATA%\postgresql\postgresql.crt和%APPDATA%\postgresql\postgresql.key, 同時(shí)沒有特定的權(quán)限檢查,因?yàn)槟夸洷徽J(rèn)為是安全的。證書和key文件的位置可以通過sslcert和sslkey連接參數(shù), 或PGSSLCERT和PGSSLKEY環(huán)境變量進(jìn)行覆蓋重寫。
在一些情況下,客戶端認(rèn)證可能會(huì)被一個(gè)"intermediate"的證書認(rèn)證來標(biāo)記, 而不是一個(gè)能直接被服務(wù)信任的。為了使用一個(gè)這種認(rèn)證,向postgresql.crt文件 追加標(biāo)記認(rèn)證權(quán),并且直到"root"都可以被服務(wù)器信任。root認(rèn)證應(yīng)該被包含在任何一種情況(postgresql.crt包含一個(gè)或多個(gè)認(rèn)證)下。
需要注意的是,root.crt列出了最高級(jí)別的CA,被認(rèn)為對(duì)標(biāo)記服務(wù)認(rèn)證中是可信任的。 原則上,不需要列出標(biāo)記客戶端認(rèn)證的CA,盡管在大多數(shù)情況下,CA仍會(huì)被認(rèn)為對(duì)服務(wù)器認(rèn)證是可信任的。
sslmode參數(shù)的不同值提供了不同的保護(hù)級(jí)別。SSL可以提供為三種攻擊提供保護(hù):
Table 31-2. SSL的攻擊
類型 | 描述 |
---|---|
Eavesdropping(竊聽) | 如果一個(gè)第三方可以在客戶端與服務(wù)器端之間檢查網(wǎng)絡(luò)通信, 那么它就能讀取兩邊的連接信息(包括用戶名和密碼)以及傳遞的數(shù)據(jù)。對(duì)此, SSL通過加密進(jìn)行防護(hù)。 |
MITM | 如果客戶端和服務(wù)器端進(jìn)行傳遞數(shù)據(jù)的時(shí)候,第三方可以對(duì)其進(jìn)行修改,那么他就能偽裝成服務(wù)器, 然后查看或修改數(shù)據(jù)(即使是加密的)。第三方接著可以向原始服務(wù)器發(fā)出連接信息和數(shù)據(jù), 最終造成無法防護(hù)這種攻擊。這種攻擊常用的載體有DNS中毒或IP綁架,即客戶端被定向到預(yù)期之外的不同的服務(wù)器。 同樣還有幾種其他的方法也能做到這種攻擊。SSL通過服務(wù)器到客戶端的證書驗(yàn)證來阻止這種攻擊。 |
模擬 | 如果第三方可以偽裝成一個(gè)認(rèn)證了的客戶端,那么它就能輕松訪問到它本來不能訪問的數(shù)據(jù)。 典型的,如不安全的密鑰管理,就會(huì)造成這種情況。SSL通過客戶端認(rèn)證來阻止這種情況, 即確保只有知道有效認(rèn)證的人員才能訪問連接服務(wù)器。 |
對(duì)于一個(gè)被稱為安全的連接來說,進(jìn)行連接之前,必須在客戶端和服務(wù)器端都進(jìn)行SSL配置。 如果只在服務(wù)器端進(jìn)行配置,在它知道服務(wù)器端需要高級(jí)認(rèn)證之前不會(huì)發(fā)送敏感信息(如密碼等)。 在libpq中,可以通過將sslmode參數(shù)設(shè)置為verify-full或verify-ca來確保安全連接, 并且為系統(tǒng)提供一個(gè)root認(rèn)證以進(jìn)行安全認(rèn)證。類似于使用https和URL進(jìn)行加密網(wǎng)頁(yè)瀏覽。
一旦服務(wù)器已經(jīng)認(rèn)證,客戶端就可以發(fā)送敏感信息。 這就意味著知道這一刻,客戶端都不需要知道,是否認(rèn)證需要證書,只在服務(wù)器配置,對(duì)其安全地指定。
所有以加密和密鑰交換方式得SSL選項(xiàng)都會(huì)產(chǎn)生開銷, 因此在性能和安全之間需要進(jìn)行一個(gè)權(quán)衡。下表說明不同sslmode為值的安全風(fēng)險(xiǎn), 以及關(guān)于安全和開銷所做出的聲明:
Table 31-3. SSL模式說明
sslmode | 竊聽保護(hù) | MITM保護(hù) | 聲明 |
---|---|---|---|
disabled | 否 | 否 | 我不關(guān)心安全,我不想來支付加密的開銷 |
允許 | 可能 | 否 | 我不關(guān)心安全性,但我會(huì)支付的加密開銷 ,如果服務(wù)器的治持的話 |
喜歡 | 或許 | 否 | 我不關(guān)心加密,但我想支付加密開銷 ,如果服務(wù)器支持它。 |
要求 | 是 | 否 | 我想我的數(shù)據(jù)是加密的,我接受的開銷。我相信 該網(wǎng)絡(luò)將確保我始終連接到服務(wù)器,按我想象的。 |
驗(yàn)證CA | 是 | 取決于對(duì)CA規(guī)定 | 我希望我的數(shù)據(jù)加密,我接受的開銷。我想成為 確保連接到一個(gè)服務(wù)器,我堅(jiān)信。 |
全驗(yàn)證 | 是 | 是 | 我希望我的數(shù)據(jù)加密,我接受開銷。我想確定連接到一個(gè)服務(wù)器我相信,它是我 指定。 |
verify-ca和verify-full之間的不同是根據(jù)rootCA的規(guī)定。 如果使用的是一個(gè)公用CA,verify-ca允許那些帶有CA注冊(cè)的客戶端對(duì)服務(wù)器進(jìn)行連接訪問。 在這種情況下,應(yīng)該使用verify-full。如果使用的是一個(gè)本地CA, 甚至是一個(gè)自簽名證書,使用verify-ca通常會(huì)提供充分的保護(hù)。
sslmode缺省值是prefer。如在表中說明的那樣,從安全角度來看這樣做是沒有意義的, 并且如果可能的話,它只承諾性能的開銷。它僅提供了缺省向后兼容性,在安全部署中不建議使用。
Table 31-4. libpq/客戶端SSL文件的使用
文件 | 內(nèi)容 | 影響 |
---|---|---|
~/.postgresql/postgresql.crt | 客戶端證書 | 服務(wù)器要求 |
~/.postgresql/postgresql.key | 客戶端的私鑰 | 證明由所有者發(fā)送的客戶端證書,并不表示 證書擁有者是值得信賴 |
~/.postgresql/root.crt | 受信任的證書頒發(fā)機(jī)構(gòu) | 檢查服務(wù)器證書是由受信任的證書機(jī)關(guān)簽署。 |
~/.postgresql/root.crl | 證書頒發(fā)機(jī)構(gòu)吊銷證書 | 服務(wù)器證書必須不在這個(gè)名單 |
如果應(yīng)用程序初始化libssl和/或libcrypto庫(kù)以及libpq編譯為支持SSL,
應(yīng)該調(diào)用PQinitOpenSSL
來告訴libpq說libssl和/或libcrypto已經(jīng)被應(yīng)用程序初始化了,
因此libpq將不會(huì)在初始化這些庫(kù)。
參閱http://h71000.www7.hp.com/doc/83final/BA554_90007/ch04.html
PQinitOpenSSL
允許應(yīng)用程序選擇安全庫(kù)初始化。
void PQinitOpenSSL(int do_ssl,int do_crypto);
當(dāng)do_ssl為非0時(shí),在第一次打開一個(gè)數(shù)據(jù)庫(kù)連接之前,libpq將初始化OpenSSL庫(kù)。
當(dāng)do_crypto為非0時(shí),libcrypto庫(kù)將被初始化。
缺省(如果PQinitOpenSSL
沒有被調(diào)用),兩個(gè)庫(kù)都會(huì)被初始化。
如果沒有編譯SSL支持,會(huì)提供該函數(shù),但不會(huì)做任何事情。
如果應(yīng)用程序使用并初始化OpenSSL,或其底層libcrypto庫(kù),那么 在第一次打開一個(gè)數(shù)據(jù)庫(kù)連接之前,必須調(diào)用這個(gè)函數(shù)(帶有適當(dāng)0值的參數(shù))。 同樣要確保在打開一個(gè)數(shù)據(jù)庫(kù)連接之前做過初始化。
PQinitSSL
允許應(yīng)用程序選擇安全庫(kù)初始化。
void PQinitSSL(int do_ssl);
此功能相當(dāng)于PQinitOpenSSL(do_ssl,do_ssl) 它的應(yīng)用是足夠的同時(shí)初始化或都不初始化OpenSSL和libcrypto。
從8.0之后的版本就提供了PQinitSSL
函數(shù),然而PQinitOpenSSL
函數(shù)是在8.4中才添加的,
因此對(duì)老版本的libpq的使用,PQinitSSL
是對(duì)應(yīng)用程序的不錯(cuò)的選擇。