安裝postgresql是一件很簡單的事,但是當我第一次安裝了postgresql以後,它的安全設置曾經讓我困擾過一陣,現在我將以我的經歷為線索來講述如何配置postgresql的訪問認證,postgresql的版本是7.3.1,老一點的版本在配置文件上會有稍許不同,請自己注意區別。另外,在閱讀中,請注意區分數據庫用戶和系統用戶的區別,以免混淆。
postgresql的訪問認證配置主要涉及到兩個主要的配置文件:postgresql.conf和pg_hba.conf。
postgresql.conf包含了許多的選項,這些選項控制了postgresql.conf的方方面面,中間影響訪問認證的選項是:
unix_socket_group
設置 Unix 域套接字的組所有人,(套接字的所有權用戶總是啟動 postmaster 的用戶)與 UNIX_SOCKET_PERMISSIONS 選項一起使用可以給這種套接字類型增加額外的訪問控制機制,缺省時是一個空字串,也就是使用當前用戶的缺省的組, 這個選項只能在服務器啟動時設置。
unix_socket_permissions
給 Unix 域套接字設置訪問權限,Unix 域套接字使用通常的 Unix 文件系統權限集。可選的值可以是一個 chmod 和 umask 系統調用可以接受的數字模式。(要使用客戶化的八進制格式,該數字必須以 0 (零)開頭)
缺省權限是 0777,意即任何人都可以聯接,合理的選則可能是0770 (只有用戶和組, 參閱UNIX_SOCKET_GROUP)和 0700 (只有用戶)。(請注意對於 Unix 套接字而言,實際上只有寫權限有意義,而且 也沒有辦法設置或者取消讀或執行權限)
這個選項只能在服務器啟動時設置。
pg_hba.conf是設置訪問認證的主要文件,格式為每條記錄一行,每行指定一條訪問認證。設定一條訪問認證包含了7個部分:連接方式(type)、數據庫(database)、用戶名(user)、ip地址(ip-address)、子網掩碼(ip-mask)、認證方法(authentication method)、認證配置(authentication-option),以下是這7個部分的詳細說明:
連接方式(type)
連接方式共有三種:local、host、hostssl
local
這條記錄匹配通過 Unix 域套接字進行的聯接企圖, 沒有這種類型的記錄,就不允許 Unix 域套接字的聯接。
host
這條記錄匹配通過 TCP/IP 網絡進行的聯接嘗試,請注意,除非服務器是 帶著 -i 選項或者打開了 postgresql.conf 裡面的 tcpip_socket 配置參數集啟動的,否則 TCP/IP 聯接是被禁止掉的。
hostssl
這條記錄匹配通過在 TCP/IP 上進行的 SSL 聯接企圖, host 記錄可以匹配 SSL 和非 SSL 的聯接企圖, 但 hostssl 記錄需要 SSL 聯接。
數據庫(database)
聲明記錄所匹配的數據庫。值 all 表明該記錄匹配所有數據庫, 值 sameuser表示如果被請求的數據庫和請求的用戶同名,則匹配。 samegroup 表示請求的用戶必須是一個與數據庫同名的組中的成員。 在其他情況裡,這就是一個特定的 PostgreSQL 的名字。我們可以通過用逗號分隔的方法聲明多個數據庫。 一個包含數據庫名的文件可以 通過對該文件前綴 @ 來聲明.該文件必需和 pg_hba.conf 在同一個目錄。
用戶名(user)
為這條記錄聲明所匹配的 PostgreSQL 用戶,值 all 表明它匹配 於所有用戶。否則,它就是特定 PostgreSQL 用戶的名字,多個用戶名可以通過用逗號分隔的方法聲明,組名字 可以通過用 + 做組名字前綴來聲明。一個包含用戶名的文件可以 通過在文件名前面前綴 @ 來聲明,該文件必需和 pg_hba.conf 在同一個目錄。
ip地址(ip-address)
子網掩碼(ip-mask)
這兩個字段包含標准的點分十進制表示的 IP地址/掩碼值。 (IP地址只能用數字的方式聲明,而不能用域名或者主機名)它們倆放在一起,聲明了這條記錄匹配的客戶機的 IP 地址。 准確的邏輯是:
(actual-IP-address xor IP-address-field) and IP-mask-field
對於要匹配的記錄必需為零。
如果連接方式是host或者hostssl的話,這兩項必須指定,否則可以不填。
認證方法(authentication method)
trust
無條件地允許聯接,這個方法允許任何可以與PostgreSQL 數據庫聯接的用戶以他們期望的任意 PostgreSQL 數據庫用戶身份進行聯接,而不需要口令。
reject
聯接無條件拒絕,常用於從一個組中"過濾"某些主機。
md5
要求客戶端提供一個 MD5 加密的口令進行認證,這個方法是允許加密口令存儲在pg_shadow裡的唯一的一個方法。
crypt
類似 md5 方法,只是用的是老式的 crypt 加密認證, 用於 7.2 以前的客戶端,對於 7.2 以及以後的客戶端,我們建議使用 md5。
password
和"md5"一樣,但是口令是以明文形式在網絡上傳遞的,我們不應該在不安全的網絡上使用這個方式。
krb4
用 Kerberos V4 認證用戶,只有在進行 TCP/IP 聯接的時候才能用。(譯注:Kerberos,"克爾波洛斯",故希臘神話冥王哈得斯的多頭看門狗。Kerberos 是 MIT 開發出來的基與對稱加密算法的認證協議和/或密鑰 交換方法,其特點是需要兩個不同用途的服務器,一個用於認證身份,一個用於通道兩端用戶的密鑰交換。同時 Kerberos 對網絡時間同步 要求比較高,以防止回放攻擊,因此通常伴隨 NTP 服務。)
krb5
用 Kerberos V5 認證用戶.只有在進行 TCP/IP 聯接的時候才能用。(譯注:Kerberos V5 是上面 V4 的改良,主要是不再依賴 DES 算法, 同時增加了一
些新特性。)
ident
獲取客戶的操作系統名(對於 TCP/IP 聯接,用戶的身份是通過與運行在客戶端上的 ident 服務器聯接進行判斷的,對於本地聯接,它是從操作系統獲取的。) 然後檢查一下,看看用戶是否允許以要求的數據庫用戶進行聯接, 方法是參照在 ident 關鍵字後面聲明的映射。
如果你使用了 sameuser 映射,那麼假設用戶名 是相等的。如果沒有聲明這個關鍵字,則在 $PGDATA/pg_ident.conf 文件中找出映射名。如果這個文件裡包含一條記錄標識著ident提供的用戶名 和請求的 PostgreSQL 用戶名的映射, 那麼聯接被接受。
對於本地聯接,只有在系統支持Unix域套接字信任證的情況下 才能使用(目前是 Linux, FreeBSD, NetBSD, 和 BSD/OS)。
pam
使用操作系統提供的可插入的認證模塊服務 (Pluggable Authentication Modules) (PAM)來認證。
認證配置(authentication-option)
這個可選的字段的含義取決與選擇的認證方法。
了解了以上的內容以後,我們可以開始設置自己的訪問認證。和mysql一樣,postgresql默認安裝的訪問認證是不安全的,當我第一次安裝好我的postgresql以後,我發現只要輸入`psql -U pgsql -d template1`就可以不需要任何密碼的進入我的數據庫,並且使用的是pgsql用戶(數據庫的最高權限),即使在我使用ALTER USER為我的數據庫用戶添加了密碼以後情況也沒有得到改善,經過一番查找,我發現我的pg_hba.conf內容如下:
local all all trust
host all all 0.0.0.0 0.0.0.0 trust
這說明無論在本地還是通過tcp/ip,任何人都可以不加任何限制的使用任何他想用的身份訪問我的數據庫,於是我為所有的訪問都使用了md5認證方法,我的pg_hba.conf變為:
local all all md5
host all all 0.0.0.0 0.0.0.0 md5
事情似乎得到了解決,任何人想訪問我的數據庫都需要通過密碼這一關,我的數據庫安全了。但是當我有一天重新啟動計算機的以後發現我的 postgresql並沒有被正常的啟動,在終端前我發現啟動到postgresql服務啟動腳本時,提示需要輸入密碼,原來在設置了md5認證方式以後我的pgsql需要密碼才能夠啟動服務,為了不每次啟動都跑到終端前去輸入一次密碼,我的pgsql用戶的認證方法必須為trust:
local pgsql all trust
local all all md5
host all all 0.0.0.0 0.0.0.0 md5
在隨後的檢測中我發現,雖然通過網絡得到了保護,但是如果在本地通過Unix域套接字進行連接的話,任何人都還是可以使用`psql -U pgsql -d template1`的方式輕松的進入我的數據庫,這樣做顯而易見不是我想要的結果,現在我需要unix_socket_permissions的協助,當我把這個項設置為0700以後,就只有套接字的所有人,即系統用戶pgsql可以使用套接字進行連接,另外如果我的數據庫有幾個管理員需要最高權限的話,0770也是一個選擇,不過暫時只有我一個管理員,所以我選擇了0700,現在我的pg_hba.conf改變為:
local pgsql all trust
host all all 0.0.0.0 0.0.0.0 md5
結合了unix_socket_permissions以後,現在只有系統用戶pgsql可以無任何限制的連接(當然,偉大的root例外),並且我也不用每次啟動的時候都跑到終端前去輸入一次密碼了,而其他人只能通過網絡連接,即使登錄到了本地計算機上,其他用戶也只能使用`psql -U xx -d template1 -h 127.0.0.1`的方式連接,這種連接是受到密碼認證的保護的,這一切正是我想要的。
以上就是我的設置過程,我們還可以使用pam等認證方法實現更加復雜的訪問認證,不過那些內容已經不在本文的討論范圍以內了。