如果你的資料庫應用,全都只能讓伺服器本機上的應用程式連線使用,那麼就太過暴殄天物了。RDBMS 原本就是設計來讓多人同時使用的,我們評比一個資料庫系統的良莠,有一個評定的標準就是同時連線的數目,看看這套資料庫管理系統,同時可以服務多少使用者。所以從網路上連上資料庫就變成相當稀鬆平常的應用。但是,一旦資料在網路上傳遞,就有資料外洩的考量。如果你存放的資料不怕被外人窺視也就算了,但是這是不可能的事,一般公司存放在資料庫中的資料,絕對都是機密性高的資料,所以當你的應用程式和資料庫間,一旦有人得以偷窺資料封包時,恐怕資料外洩是勢必難避免的。
那麼,我們所安裝的 PostgreSQL 在網路上傳遞資料的安全性是如何呢?如果是預設安裝,那麼很抱歉,在 FreeBSD 上的 PostgreSQL port 是極不安全的,連密碼都是以明碼的方式在網路上傳遞的。很不幸的,Windows 版本也是。Ubuntu 比較好,預設已把 SSL 支援加上,但是它也有缺點,缺點和 Debian 一樣,改版的速度太過緩慢,慢到會讓人抓狂,尤其是安全性更新。我不清楚 Fedora 版本的 PostgreSQL 是如何,但是我猜和 FreeBSD 及 Windows port 是一樣的,沒有。所以,當你甫安裝好 PostgreSQL port 後,事實上要做的動作還很多呢,把加密的需求完成就是前三件事之一。
要讓資料傳輸時加密,最簡單也是效率最高的方法是使用 SSL,其次是 SSH tunnel 技術,但是後者的效能比較差,而且手續複雜,我認為只適用於管理者在管理資料庫時適用,過一陣子我會寫一篇利用 SSH tunnel 遠端管理 MySQL 的文章,目前這個主題先跳過,我們來談談如何讓 PostgreSQL 加上 SSL 支援。
PostgreSQL 有一個內建的,可以透過 SSL 進行客戶端與伺服器端間的加密通訊功能,但是必須先在設定檔 postgresql.conf 中打開。除了 postgresql.conf 的設定要修改以外,還得加上兩個檔案:server.crt 和 server.key 才行,否則即使你要求以 SSL 加密,PostgreSQL 還是會以明碼傳遞你的資料。server.key 和 server.crt 這兩個檔案中,分別包含伺服器的公鑰和認証。我們在 FreeBSD 和 Linux 中,想要產生這兩個檔案,當然是使用 OpenSSL,所以請先把 OpenSSL 安裝好。產生這兩個檔案的過程,如手冊中所說,須要幾個步驟。至於比較詳盡的 OpenSSL 的說明,還是請各位到 OpenSSL 官方網站查看。
首先是建立一個自我認證的認證。為什麼說是自我認證?那是因為通常 SSL 的認證,是由 CA,也就是認證中心發行。但是這樣的認證必須付費的,而且有效期限通常只有一年。如果這個認證是你自己的網站需要,那麼最好是付費請 CA 發給你認證,這樣當你使用 HTTPS 時,瀏覽器才不會出現不明認證的警告。但是當我們是為了自己資料庫連線用的編碼用,那麼何必要請 CA 發認證?自己自我認證即可。要建立這麼一個自我認證,可以用下面的命令:
# openssl req -new -text -out server.req
這樣會先生成一份認證申請書 server.req 以及一份私鑰,通常這份 .req 就是你給 CA 讓 CA 產生 .crt 用的。當你下達這個命令後,openssl 會問你一串問題,其中也有私鑰密碼:
Loading 'screen' into random state - done
Generating a 1024 bit RSA private key
...............++++++
.....................++++++
writing new private key to 'privkey.pem'
Enter PEM pass phrase: <請輸入你的密碼,不要小於四個字元>
Verifying - Enter PEM pass phrase: <請再重新輸入你的密碼一次>
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:TW <-- 除非你不在台灣,比如香港,就是 HK
State or Province Name (full name) [Some-State]:Taiwan <-- 跟上面一樣,如果你不在台灣就打當地州或省名
Locality Name (eg, city) []:Taipei <-- 如果你不在台北,那麼打你的地名
Organization Name (eg, company) [Internet Widgits Pty Ltd]:XXXXXXXXXXXX <-- 公司或機構名
Organizational Unit Name (eg, section) []:<-- 組織名,我沒打,直接按 Enter
Common Name (eg, YOUR name) []:XXXXXXX <-- 輸入自己的名字,但是 PostgreSQL 手冊建議你輸入伺服器主機名稱
Email Address []:xxxxxxx@xxx.xxx.com <-- Email 帳號,可以不輸入直接按 Enter
Please enter the following 'extra' attributes <-- 以下這兩個問題是額外的,主要是給 CA 認證時多一些資訊用的,所以你可以一路按 Enter 到底
to be sent with your certificate request
A challenge password []:
An optional company name []:
接著請輸入下列命令自己產生一對金鑰(不用經過 CA),openssl 會詢問私鑰密碼:
# openssl rsa -in privkey.pem -out server.key
Enter pass phrase for privkey.pem:
writing RSA key
接著把私鑰砍掉,因為用不到,而且如果你擺了它就得每次開機時輸入你的私鑰密碼一次:
# rm privkey.pem
然後利用剛才生成的公鑰和認證申請要求來產生自己簽名的認證:
# openssl req -x509 -in server.req -text -key server.key -out server.crt
如果你在 FreeBSD 或 Linux 或其它 Unix 上,工作還沒完,記得把公鑰的讀寫權限縮小到只有擁有者可以讀:
# chmod og-rwx server.key
接著把這兩個檔移到(千萬不可以用複製的,最好這個世界上只有這一份獨一無二的) PostgreSQL 的 data 目錄下,比如在 FreeBSD 就在 /usr/local/pgsql/data 下。接著把權限改成 postgres 的:
# chown postgres:postgres server.*
接著修改 postgresql.conf,找出 #ssl = off 那一行,先把該行最前面的註解符號 # 去掉,然後把 off 改成 on,接著存起來。然後把 PostgreSQL 重新啟動:
# /usr/local/etc/rc.d/postgresql restart
這是 FreeBSD 的重新啟動方式,其它系統有其它系統的做法。
至於 Windows 上,微軟也有產生這兩個檔案的工具,從前是附在 IIS 和他們家的產品 Commerce Server 上,理論上已經併到 Windows 2003 Server 中了,但是我已經快十年沒碰微軟的東西了,所以並不確定。如果你想試一下 OpenSSL,除了很辛苦的找出 Visual C++ 來 make source code 以外,你也可以直接到 Shining Light Productions - Win32 OpenSSL 下載 binary 安裝程式。建議下載 lite 版本就夠了。安裝的方法很簡單,下一步、下一步、下一步就 OK 了。但是安裝時你在輸入安裝目錄時,千萬不要自找麻煩,選一個目錄名稱很長、很討厭的位置,建議越簡單越好,比如 C:\openssl。剛才那幾個產生 server.key 和 server.crt 這兩個檔案的指令完全都一樣,請從 開始功能表→附屬應用程式→命令提示字元 叫出 DOS console,然後切到你安裝的目錄下的 bin 目錄下,比如 C:\openssl\bin,然後就按照上述的命令照本宣科即可。產生的檔案你可以用檔案總管,把它們「移到」PostgreSQL 的安裝目錄下,比如說:C:\Program Files\PostgreSQL\8.3\data。記得要修改 postgresql.conf 以及重新啟動 PostgreSQL,要重新啟動 PostgreSQL,最簡單的方法,你可以用開始功能表內的 PostgreSQL 的 stop service 和 start service 來完成。
你可以用 pgAdmin III 來測試是不是成功,首先,先在原來登錄在 pgAdmin III 的伺服器 icon 上,按下滑鼠右鍵,跳出下拉式選單,選「屬性(P) ...」,然後出現屬性對話方塊,在 SSL 中選「偏好」或「必須」:
接著把 pgAdmin III 闗掉重開,這時候你應該可以看到:
如果是這樣,那麼恭喜你,加密連線完成。最後還有一個步驟,就是修改 pg_hba.conf,把所有非本機的客戶端全部把型式從 host 改成 hostssl,這樣就可以強制所有只要通過網路連線的客戶端都必須經用 SSL 編碼來傳送資料。但是在做這個動作前,請先確認一下你目前已有的客戶端都能使用 SSL 安全連線連上伺服器,否則你只好先按兵不動。當然,這樣還沒做完,客戶端的設定,還有相當多的事要做呢。