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