# PostgreSQL 連線安全設定指南

最近在看資料庫的 log 時發現以下的 log 。

PostgreSQL 嘗試登入 log

這就表示有人在嘗試以 postgres 這個帳號登入,那當然這就是很典型的入侵攻擊,那透過程式可以暴力嘗試大量的密碼,最終就可以獲得 postgres 這個帳號的密碼,接著就會進行一系列的攻擊。

那可以藉由一些機制來調整 PostgreSQL 的設定,透過正確地調整設定可以減少被入侵攻擊的風險。

# postgresql.conf

其中有兩個設定 listen_addresses, port 是跟連線相關的。

# listen_addresses

listen_addresses = 'localhost'          # what IP address(es) to listen on;
                                        # comma-separated list of addresses;
                                        # defaults to 'localhost'; use '*' for all
                                        # (change requires restart)
port = 5432                             # (change requires restart)

listen_addresses 預設是 localhost,如果你的 Web Application 與 DB 是在同一台主機的話,用這樣的設定最好,PostgreSQL 就只會綁定在 localhost 上,所以也只能接受 localhost 的連線。

netstat 看會是這樣的狀態,PostgreSQL 就只有 LISTEN 127.0.0.1:5432

# netstat -na | grep LIST
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN

如果設定為 * 就會綁定到主機所有可用的 IP 上。

netstat 看會是這樣的狀態,PostgreSQL 會 LISTEN 0.0.0.0:5432:::5432

# netstat -na | grep LIST
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:5432            0.0.0.0:*               LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN
tcp6       0      0 :::5432                 :::*                    LISTEN

如果 Web Application 跟 DB 不在同一台主機,但是在同一個區網內,也可以設定 localhost, 192.168.0.1 這樣就會綁定在 localhost192.168.0.1 上面,這樣 DB 就可以接受同一個區網的連線。

netstat 看會是這樣的狀態,PostgreSQL 會 LISTEN 127.0.0.1:5432192.168.0.1:5432

# netstat -na | grep LIST
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 192.168.0.1:5432        0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN

如果你的 Web Application 與 DB 是在同一台主機或同個區網的話,基本上建議就綁在 localhost 或是區網的 IP 這樣就可以減少 PostgreSQL 受到嘗試登入的攻擊。

# port

如果 PostgreSQL 一定得綁在 Public IP 上面的話,建議可以更改 port ,這樣也可以減少受到嘗試登入的攻擊。因為無目的性的入侵大概就是用工具掃 IP 跟 port ,用PostgreSQL 預設 port 5432 就比較容易被掃到,雖然改 port 有點鴕鳥,不過對於這無差別攻擊還是有小小的防禦效果。😆

當然,如果你被針對,改 port 這招還是沒效,畢竟用工具也是可以很快掃出這個 IP 有開放哪些 port 。

# pg_hba.conf

pg_hba.conf 是 PostgreSQL Client Authentication Configuration File 可以設定 PostgreSQL 資料庫內帳號與資料庫存取的規則

設定檔大概長這樣

# DO NOT DISABLE!
# If you change this first entry you will need to make sure that the
# database superuser can access the database using some other method.
# Noninteractive access to all databases is required during automatic
# maintenance (custom daily cronjobs, replication, and similar tasks).
#
# Database administrative login by Unix domain socket
local   all             postgres                                peer

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
host    web_app         web_app         127.0.0.1/32            md5
host    all             admin_account   0.0.0.0/0               md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
host    all             admin_account   ::0/0                   md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            md5
host    replication     all             ::1/128                 md5

# 限制帳號只能連線某個資料庫

建議每個 web_app 最好都有帳號,不要共用,這樣就可以限制 web_app1 只能連線 web_app1 的資料庫,像下面的設定一樣。

host    web_app1         web_app1       127.0.0.1/32            md5

# 開放帳號可以透過網際網路連線資料庫

如果要開放某個帳號(例:admin_account)可以從網際網路連線資料庫可以這樣設定。

host    all             admin_account   0.0.0.0/0               md5
host    all             admin_account   ::0/0                   md5

這樣(admin_account)就可以從網際網路來連線到所有的資料庫,或是把 all 改為某個資料庫,這樣就只能連線那個資料庫。

不過這邊也是建議不要開放帳號可以透過網際網路的方式來連線資料庫,如果要的話可以用 over SSH 的方式,後面的段落會介紹 over SSH 的方式

# 不要使用 postgres 這個帳號

postgres 這個帳號是 PostgreSQL 預設的 superuser 帳號,基本上就很容易被針對,可以看到文章開始的 log 都是針對 postgres 帳號來進行嘗試登入,所以除了 shell 管理之外,都不要使用 postgres 這個帳號,application 及管理用途再額外開帳號就好。

# iptables

再來是透過防火牆的方式來限制連線,如果你的 Web Application 跟 DB 不在同一個區網內,但是有固定的 IP 那就可以用防火牆的方式來限制連線,Linux 系統可以用 iptables 來設定。

# iptables -A INPUT -i lo -p tcp --dport 5432 -j ACCEPT
# iptables -A INPUT -s your_ip -p tcp --dport 5432 -j ACCEPT
# iptables -A INPUT -p tcp --dport 5432 -j DROP

# ip6tables -A INPUT -i lo -p tcp --dport 5432 -j ACCEPT
# ip6tables -A INPUT -s your_ip -p tcp --dport 5432 -j ACCEPT
# ip6tables -A INPUT -p tcp --dport 5432 -j DROP

像是這樣就可以限制只有 localhostyour_ip 可以連線

# DB connection over SSH

前面提了很多方式來保護資料庫的連線安全,那管理人員要從網際網路登入管理就會受到很大的限制,那這邊有一個方式是官方也推薦的方式就是使用 SSH Tunnel 的方式來連線到要管理的資料庫

首先先建立 SSH Tunnel,利用 SSH 將 your_db_host 的 port 5432 轉到 localhost 的 port 54320 上。

# ssh -L 54320:your_db_host:5432 your_account@your_db_host

這時需要輸入主機上的帳號密碼,輸入後就會登入主機,接著保持這條連線不要關閉。

接著再用 psql 連到 localhost 的 port 5432 上面。

# psql -h localhost -p 54320 postgres

這樣就可以透過 SSH Tunnel 的方式來連線到 PostgreSQL 資料庫。

# GUI 工具

一般來說也會使用 GUI 工具來管理 PostgreSQL,院長是使用 Valentina Studio (opens new window)Postico (opens new window) 這兩套來管理資料庫。

這兩套 GUI 工具都有支援以 SSH Tunnel 的方式連線到 PostgreSQL 資料庫。

Valentina Studio

Valentina Studio over SSH

Postico

Postico via SSH

這樣一來就可以不用指令建 SSH Tunnel 直接透過 GUI 工具內的機制達成,可說是方便不少。

# 結語

資安的領域博大精深,除了本文介紹的連線安全之外,還有很多機制可以保護資料庫,那這部分就之後有機會再跟大家分享囉。

# 參考資料

Last Updated: 2021-11-26 16:02:26
贊助商連結
    贊助商連結
    (adsbygoogle = window.adsbygoogle || []).push({});