2010年5月6日 星期四

在 Ubuntu 上的 PostgreSQL 預設存取認證方式

在 FreeBSD 和 CentOS 上,第一次著手使用 PostgreSQL 非常容易,因為 root 的密碼你會知道,所以只需要以下列這兩個指令,就可以不用知道安裝程式到底替你的 pgsql 或者 postgres 指定了什麼複雜的密碼,你都可以切成 PostgreSQL 的系統帳號,來執行該有的管理命令:
$ su
# su - pgsql (這是在 FreeBSD ,或者)
# su - postgres (這是在 CentOS 上)
在 FreeBSD 上第一步更輕鬆,因為 FreeBSD 上的 PostgreSQL port 版的預設 pg_hba.conf 設定,把 localhost 和本機使用 Unix domain socket 的權限,設成最寬鬆的 trust,所以就算不用密碼,你還是可以很輕鬆的從本機上,用 postgres 這個資料庫成員進行管理和設定的工作;只是強烈建議你,在正式上線前這些設定都應該要修改,比較安全。只是,這些事情到了 Ubuntu 上就有一點點變得複雜了,原因有二:其一在於 Ubuntu 系統設計上,預設不想讓你知道 root 密碼,故意不讓你用 su 切成 root 來做管理工作,而是希望你利用任一個 wheel 群組的使用者登入後,再用 sudo 來執行 root 才能執行的管理命令。但是上面的第二個指令卻是使用 root 的權限才做得到,所以有些書或網路上的文章,會建議你直接替 postgres 系統帳號設定密碼;但是這種建議,我認為是很蠢的。其二就在 pg_hba.conf 這個檔案的預設值。其實我很反對替 postgresql 系統帳號設密碼,因為要設到又要你自己記得起來,又要複雜到 cracker 破解不了的密碼,實在不是件容易的事。那麼要怎麼著手第一步呢?剛裝好 PostgreSQL 時,我不但不知道 root 的密碼,連 postgres 系統帳號的密碼也不知道,更別說資料庫角色 postgres 的密碼了,那要怎麼進行?我們先從 pg_hba.conf 開始,這個檔案在 Ubuntu 的 PostgreSQL port 是放在 /etc/postgresql/8.4/main/pg_hba.conf [1]。總之,我們先看看預設值這個檔的內容,我只截取有義意的最後幾行:
......(上略)
# Database administrative login by UNIX sockets
local   all         postgres                          ident

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD

# "local" is for Unix domain socket connections only
local   all         all                               ident
# IPv4 local connections:
host    all         all         127.0.0.1/32          md5
# IPv6 local connections:
host    all         all         ::1/128               md5
加粗的四行才是有意義的,其餘只是備註;一般來說,實際應用上,大家最後應該還是會開放讓網路上其它主機連線;但是目前還沒有,所以我們目前只需先來討論一下這四條設定。第一條和第二條事實上重覆了,我猜 Ubuntu 的 PostgreSQL 維護者是希望你把第二條改掉;比如改成像 CentOS 預設的 md5[2];第三條和第四條其實指的也是同一件事,就是 IPv4 和 IPv6 的 127.0.0.1 或 ::1/128 這兩個協定的 localhost 會使用 md5 認證方式。看起來這四條都是設定本機連線,事實上有一點點不一樣,差別就在前端程式所使用的協定。如果你有裝 pgAdmin III,那它使用的協定是 TCP/IP,適用的是第三或第四條;但是 psql 用的卻是 Unix domain socket,則是參考第二條設定。在這裏你可以注意到 Unix domain socket 的認證方法是 ident,意思是要再查閱 pg_ident.conf,就可以免密碼直接用 psql 直接連上 PostgreSQL。所以你只需要在系統中切成 postgres,你就可以直接執行管理指令,不用密碼[4]。但是,如果你是用 pgAdmin III 呢?我們看第三條,認證方法是 md5,這代表你必須輸入密碼,只是前端程式不會將你的密碼以明碼在網路上傳送,而是先用 md5 編碼後,等到了伺服器,再比對兩者的 md5 簽章結果是否一致。md5 是比 7.4 版以前的 PostgreSQL 所提供的「password」認證方式更安全的一種認證方式,當然你還可以選 gss, sspi, krb5 這些第三方的認證方式,還可以選像 pam, ldap 這類由目錄服務或是其它 PAM 模組所提供的認證方式,這方面請自行參考手冊。但是一般使用來說,md5 已經夠安全了。
但是,問題出現了,我又不知道 postgres 的密碼,那我怎麼使用 pgAdmin III 管理?答案很簡單,就是直接用 psql 設定 postgres 的資料庫密碼。但是,postgres 的系統帳號密碼我根本就不知道,叫我怎麼執行 psql 呢?其實很簡單,只要一行就可以免密碼切成 postgres:
$ sudo su - postgres
沒錯,就是這麼簡單!接著你就可以執行 psql:

然後你就可以執行更改密碼的指令:
postgres=# alter user postgres with encrypted password '你的新密碼';
ALTER ROLE
postgres=#
來,我們來看看用 pgAdmin III 是不是可以連上?先新增一個伺服器連線:

請輸入剛才設定的密碼:


這時候一定會出現「建議」,不用理會它!


哇哈哈,連上了!


第一步算是完成。再來就要開放讓網路上其它的機器可以讀取。請注意,建議設定得越嚴格越好,不要「假設」防火牆會幫你阻檔攻擊,能在這裏先把關好,就先把關好。
要放啟網路連線,有兩個設定檔要先修改,一個就是剛才的 pg_hba.conf,另一個是 postgresql.conf,兩個檔案都放在 /etc/postgresql/8.4/main 之下[1]。postgresql.conf 要修改的地方只有一處,如下圖所示:

請把上圖那行 #listen_addresses = 'localhost' 前面的「#」號[3]拿掉,把 'losthost' 改成 '*';記住,單引號千萬不要漏掉;然後存起來。這個設定,是代表 PostgreSQL 的 listener 要監聽的網路介面。如果你的伺服器有超過一個以上的網路介面卡,那麼你可以指定只監聽某個介面的查詢請求。有時為了安全,我們常會將伺服器安裝兩個介面卡,其中一個對外連,另一個對內連,而且不轉交對外的那個介面來的任何封包(也就是不讓伺服器另做路由器或防火牆用)。為了安全,我們可以只讓 PostgreSQL 監聽來自內部的查詢請求, 而不理會對外那個介面來的請求。設成 '*' 星號是貪圖方便、偷懶,代表監聽所有的網路介面。通常如果你的伺服器只有唯一一個網路介面卡時,你就可以這樣偷懶。
pg_hba.conf 則是在最後面加上你要開放的 IP。設定的規則很簡單,就像前面那堆註解說明的,請自己參考,更詳細的說明請參考手冊。如果你沒有設定 SSL 連線,那麼第一欄請使用 host 即可,用不著設成 hostnossl。第三欄建議使用 CIDR 表示法,儘量不要再用傳統的 IP network-mask 的格式。也就是說,假如你的打算開放的是 192.168.1.1 ~ 192.168.1.126,以傳統的網路遮罩應該是 255.255.255.128,那麼你可以設成 192.168.1.0/25。如果這部份你看不懂,那麼請找一本 TCP/IP 的書籍,專門翻到 IP 定址的那部份看一下,應該很容易就會懂了。第五欄,如果你的系統沒有安裝其它的第三方認證方式,建議使用 md5,不要使用 trust 或 passwordindent 也儘量不要用,除非你的前端都是 Unix/Linux。以剛才這一個網段為例,這行可以參考第三條,設定成:
host    all         all         192.168.1.0/25          md5

如果是只打算開放給 192.168.2.1 這個 IP,那麼一個 IP 的網路遮罩是 255.255.255.255,CIDR 表示法是 192.168.2.1/32,可以設定成:
host    all         all         192.168.2.1/32          md5
設定好了之後,請重新啟動 PostgreSQL,重新啟動的方法是:
$ sudo service postgresql-8.4 restart
 * Restarting PostgreSQL 8.4 database server                             [ OK ]
$
如上出現 OK 就表示你的設定語法上沒有問題,但是你還是要到前端用 pgAdmin III 連線看看,如果可以連上,那麼恭喜你,成功了。
最後,特別提醒一下,pg_hba.conf 不要設定得太寬鬆。因為雖然 PostgreSQL 很安全,但是只要人做的,就無法保證完全不會出錯。我就見過兩次很嚴重的安全性 bug 的安全通告。有些高手就有辦法在短短一兩天內搞出零時差攻擊。所以這方面再小心也不為過。

[1] 這篇文章假定是在 Ubuntu 10.05 LTS - Lucid Lynx 上,所安裝的 PostgreSQL server 8.4.3_1。其它版本,像是 8.4 換成 9.0 之類的,請自行類推。Ubuntu 在這方面很討厭,把所有設定檔放在 /etc 下,把資料庫檔卻放在 /var/lib 下,不像原始的 PostgreSQL 使用 chroot,把所有檔案全放在一塊。Ubuntu 這樣的安排,卻使得一堆工具使用上出現不少困擾。
[2] 我感到納悶的是,那為何不乾脆預設值就設成 md5?因為已經有了第一行的設定,即使預設改成了 md5 又不會影響 postgres 這個預設 dba 的認證方式。目前這個樣子只是留了一條尾巴,讓使用者事後還要動手改,那何不一開始就設定好?實在令人百思不得其解!
[3] 「#」井字號代表其後是註解,PostgreSQL 會自動忽略其後的文字。
[4] 這裏我跳過了一堆細節。ident 認證方式有好幾種,比如只有單純的 ident 或是有附加的述詞;比如 same user;用以補充說明。這裏如果後面再加上 same user 述詞就代表著,只要你在系統中以某個系統帳號登入,那麼你就可以免密碼以同名的資料庫帳號直接登入資料庫。比如你在 Ubuntu 以 postgres 這個系統帳號登入,這時候你就可以直接執行 psql,而不用使用密碼即可登入資料庫,就像前面本文中的這個例子。但是如果後面沒有述詞來補充呢?預設資料庫會去找和 pg_hba.conf 同一目錄下的 pg_ident.conf。這個檔案列了一個清單,內容就是系統帳號和資料庫帳號的對照表。但是如果清單中沒列的資料庫帳號,就像是加了 same user 述句一樣的認證方式。





沒有留言:

張貼留言

用 Claude 在 PsotgreSQL 的 Docker Container 中建立一個 database

Claude 是一個很強的 AI 工具,大概是我用過唯一可以和 Gemini 挑戰的 AI 工具。 它對於程式設計的能力相當強大。我這個測試證明了,不止程式設計能力很強,連資料庫的整個架構能力也是很嚇人的。 之前,我不是在 Proxmox VE 上建了一個 Zorin OS 的 ...