實測環境與硬體規格
| 項目 | 實際測試配置 |
| 測試日期 | 2026-10-02 |
| 作業系統 | Ubuntu 24.04.5 LTS |
| 主機數量 | 2 台新建隔離 VM;下列資源為每台配置 |
| CPU | 2 vCPU |
| 記憶體 | 4 GiB |
| 系統磁碟 | 32 GiB;HDD 儲存、VirtIO、ext4 |
| Linux 核心 | 6.8.0-139-generic |
| PostgreSQL | psql (PostgreSQL) 16.15 (Ubuntu 16.15-0ubuntu0.24.04.1) |
讓遠端資料庫連線同時具備加密、伺服器身分驗證與來源限制,並實測錯誤憑證、錯誤密碼、明文及不允許來源的拒絕結果。
文章目錄
本文以全新 Ubuntu 24.04 隔離主機和合成資料實測。套件來自經過簽章驗證、符合 Noble 的套件來源;沒有使用正式資料庫或正式網站的帳號。讀者請依自己的環境確認來源與版本。
圖中是測試主機實際 bash PTY 的執行紀錄,由瀏覽器呈現;提示符統一為 lab$,執行結果未改寫。文字命令另行保留,方便複製。
開始前需完成 PostgreSQL 16 的原生安裝與叢集啟動,可先閱讀 Ubuntu 24.04 安裝篇。本系列使用 demo 範例資料庫;需要既有 sample 表的篇章,依 搬機篇的資料建立步驟 準備 100 筆合成資料。請在獨立教學環境操作。
一、先分清楚三道控制
| 控制 | 用途 |
| TLS + verify-full | 加密,並驗證 CA 和資料庫主機名稱 |
| SCRAM | 驗證資料庫帳號與密碼 |
| pg_hba.conf | 限制哪個來源、資料庫與角色可以使用哪種認證 |
伺服器 ssl=on 代表提供 TLS,並不代表同一個埠上的所有連線都被強制加密。是否接受明文必須由 HBA 規則明確決定。伺服器 TLS 文件
本文用 db.example.test、伺服器 192.0.2.10、客戶端 192.0.2.11 作文件範例。這些位址不是可直接連入的公開服務;測試 VM 使用隔離路由,讀者須換成自己可達的位址及有權管理的名稱。
二、建立短期教學 CA 與伺服器憑證
在資料庫主機的私有工作目錄執行。CA 私鑰只留在管理端;只把 CA 公開憑證交給客戶端。正式環境應採用受管理的憑證生命週期,不能把本篇兩天效期的教學憑證拿去長期運作。
umask 077
mkdir -p ~/demo-tls && cd ~/demo-tls
openssl req -x509 -newkey rsa:2048 -nodes -days 2 \
-keyout ca.key -out ca.crt -subj '/CN=Tutorial Test CA'
openssl req -new -newkey rsa:2048 -nodes \
-keyout server.key -out server.csr -subj '/CN=db.example.test'
cat > server.ext <<'EOF'
subjectAltName=DNS:db.example.test
extendedKeyUsage=serverAuth
EOF
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 2 -extfile server.ext
sudo install -o postgres -g postgres -m 0600 server.key /etc/postgresql/16/main/server.key
sudo install -o postgres -g postgres -m 0644 server.crt /etc/postgresql/16/main/server.crt
三、設定 PostgreSQL 與最小 HBA 規則
先備份既有設定。以下是空白隔離主機的完整示範;有其他應用的正式主機應逐條審查,保留必要管理與復原通道。listen_addresses 的位址要確實存在於伺服器網路介面。
# /etc/postgresql/16/main/conf.d/demo-tls.conf
listen_addresses = '127.0.0.1,192.0.2.10'
ssl = on
ssl_cert_file = '/etc/postgresql/16/main/server.crt'
ssl_key_file = '/etc/postgresql/16/main/server.key'
password_encryption = 'scram-sha-256'
# /etc/postgresql/16/main/pg_hba.conf
local all postgres peer
local all all peer
hostssl demo app_user 192.0.2.11/32 scram-sha-256
hostnossl all all 0.0.0.0/0 reject
host all all 0.0.0.0/0 reject
host all all ::/0 reject
HBA 由上往下取第一條符合規則。這份配置只允許指定客戶端以 TLS 登入 demo/app_user,明文和其他來源被明確拒絕;若已有更前面的寬鬆規則,後面的限制不會補救它。HBA 規則順序
sudo -u postgres psql -X -d postgres
\password app_user
\q
sudo systemctl restart postgresql@16-main
sudo -u postgres psql -X -d postgres -c 'SHOW ssl;'
openssl x509 -in /etc/postgresql/16/main/server.crt -noout -ext subjectAltName

四、從另一台客戶端使用 verify-full
先將 CA 公開憑證放在客戶端,並確認 db.example.test 的 DNS 指向資料庫位址。若測試用 hosts 對應由 Cloud-Init 管理,需修改其 hosts 範本或使用受管理 DNS;本次找出開機覆寫後已補驗名稱持續有效。
psql -X -W \
'host=db.example.test port=5432 user=app_user dbname=demo sslmode=verify-full sslrootcert=/path/to/ca.crt connect_timeout=5' \
-c 'SELECT current_user, ssl, version, inet_client_addr() FROM pg_stat_ssl WHERE pid=pg_backend_pid();'
verify-full 同時核對信任鏈與主機名稱,不能用 sslmode=require 取代這兩項檢查。上面 -W 讓密碼互動輸入,命令中沒有密碼值。libpq 憑證驗證

截圖的 check-demo-tls 是測試專用包裝程式:在客戶端本機讀取權限 0600 的私有密碼,以同一套 libpq 連線參數執行查詢,只列出角色、TLS 與文件用 IP;不是將密碼放在畫面或命令參數。
五、一定要做拒絕測試
| 測試 | 實際結果 |
| 正確 CA、名稱、密碼與來源 | 連線成功;TLS 啟用 |
| sslmode=disable | HBA 拒絕明文 |
| 錯誤主機名稱 | 憑證名稱驗證失敗 |
| 不信任該 CA | 憑證驗證失敗 |
| 錯誤密碼 | SCRAM 認證失敗 |
| 其他來源位址 | HBA 拒絕 |
本次重新啟動資料庫與客戶端 VM,再確認範例名稱解析、verify-full、TLS 狀態及來源位址均正確。HBA 是資料庫層限制;網路邊界仍應依實際環境限制 5432 的可達來源。
這次驗證了什麼
| 驗證項目 | 結果 |
| 跨兩台 VM 的 verify-full 連線成功 | 通過 |
| 明文、錯誤名稱、CA、密碼與來源皆被拒絕 | 通過 |
| 查詢確認 TLS 啟用與指定來源 | 通過 |
| 兩台 VM 重新開機後仍正常 | 通過 |
實測範圍:使用短期教學 CA 與兩台隔離 VM;驗證資料庫認證與來源限制,未測正式 CA 簽發、憑證自動續期、雙向 TLS 或跨 Internet 的 5432 開放。