尚拙

一个分享技术、学习成长的个人博客网站

0%

Ubuntu 系统中配置 PostgreSQL IP 访问白名单详解

在服务器部署 PostgreSQL 时,出于安全考虑,通常不会直接允许所有公网 IP 连接数据库,而是通过 IP 白名单 的方式,只允许指定服务器或指定网段访问。

本文以 Ubuntu 系统为例,介绍如何配置 PostgreSQL 的 IP 访问白名单,并重点说明如何允许类似 58.123.34.* 这样的 IP 段访问数据库。

一、PostgreSQL 的 IP 白名单在哪里配置?

PostgreSQL 的客户端访问控制主要由以下文件负责:

pg_hba.conf

其中 hba 是:

Host-Based Authentication

也就是基于主机的身份验证配置。

通过该文件,可以控制:

  • 哪些 IP 可以访问 PostgreSQL
  • 哪些数据库可以访问
  • 哪些 PostgreSQL 用户可以访问
  • 使用哪种认证方式
  • 是否允许整个 IP 网段访问

在 Ubuntu 中,常见路径为:

/etc/postgresql/14/main/pg_hba.conf

或者:

/etc/postgresql/15/main/pg_hba.conf
/etc/postgresql/16/main/pg_hba.conf

具体路径取决于安装的 PostgreSQL 版本。


二、查看 pg_hba.conf 的实际路径

如果不确定 PostgreSQL 的配置文件路径,可以直接进入 PostgreSQL:

sudo -u postgres psql

然后执行:

SHOW hba_file;

例如返回:

/etc/postgresql/16/main/pg_hba.conf

退出 PostgreSQL:

\q

然后编辑:

sudo vim /etc/postgresql/16/main/pg_hba.conf

也可以使用 nano:

sudo nano /etc/postgresql/16/main/pg_hba.conf

三、允许单个 IP 访问 PostgreSQL

假设需要允许下面这个 IP:

58.123.34.56

可以在 pg_hba.conf 中增加:

host    all    all    58.123.34.56/32    scram-sha-256

其中:

host

表示 TCP/IP 网络连接。

第一个:

all

表示允许访问所有数据库。

第二个:

all

表示允许所有 PostgreSQL 用户。

而:

58.123.34.56/32

表示仅允许 58.123.34.56 这一个 IP。

最后:

scram-sha-256

表示使用 SCRAM-SHA-256 密码认证。

如果是较老版本 PostgreSQL,也可能看到:

host    all    all    58.123.34.56/32    md5

四、如何允许 58.123.34.* 访问?

这是实际服务器配置中非常常见的需求。

例如希望允许:

58.123.34.0
58.123.34.1
58.123.34.2
...
58.123.34.255

也就是:

58.123.34.*

需要注意:

PostgreSQL 的 pg_hba.conf 不能直接使用 * 通配符。

下面这种写法是错误的:

host    all    all    58.123.34.*    scram-sha-256

正确方式是使用 CIDR 网段表示法:

host    all    all    58.123.34.0/24    scram-sha-256

其中:

58.123.34.0/24

就相当于:

58.123.34.*

也就是说允许:

58.123.34.0 - 58.123.34.255

范围内的 IP 连接 PostgreSQL。


五、CIDR 中的 /24 是什么意思?

PostgreSQL 使用 CIDR 表示 IP 范围。

IPv4 地址一共有:

32 bit

例如:

58.123.34.56

可以分成 4 段:

58 . 123 . 34 . 56

每段占:

8 bit

因此:

/24

表示前 24 位固定。

也就是前三段固定:

58.123.34

最后一段可以变化。

因此:

58.123.34.0/24

等价于:

58.123.34.*

六、常见 IP 通配范围对应关系

如果习惯使用 * 理解 IP 范围,可以按照下面的方式转换。

想要允许的范围 PostgreSQL CIDR 写法 IP 数量
58.123.34.56 58.123.34.56/32 1
58.123.34.* 58.123.34.0/24 256
58.123.*.* 58.123.0.0/16 65536
58.*.*.* 58.0.0.0/8 16777216
所有 IPv4 0.0.0.0/0 全部

例如:

58.123.*.*

应该写成:

host    all    all    58.123.0.0/16    scram-sha-256

而:

58.*.*.*

则对应:

host    all    all    58.0.0.0/8    scram-sha-256

七、推荐限制数据库和用户

虽然下面这种配置很方便:

host    all    all    58.123.34.0/24    scram-sha-256

但是它意味着:

58.123.34.0/24 网段中的机器,可以尝试连接所有数据库和所有用户。

生产环境中,更推荐进一步限制数据库和用户。

例如数据库名:

history_db

数据库用户:

history_user

可以配置为:

host    history_db    history_user    58.123.34.0/24    scram-sha-256

这样只有:

58.123.34.0 - 58.123.34.255

范围内的机器,才能使用:

history_user

访问:

history_db

安全性更高。


八、确认 PostgreSQL 是否允许远程连接

仅修改 pg_hba.conf 还不一定能远程访问 PostgreSQL。

还需要检查:

postgresql.conf

查看配置文件路径:

sudo -u postgres psql -c "SHOW config_file;"

例如:

/etc/postgresql/16/main/postgresql.conf

编辑:

sudo vim /etc/postgresql/16/main/postgresql.conf

找到:

#listen_addresses = 'localhost'

如果 PostgreSQL 需要接受其他服务器连接,可以修改为:

listen_addresses = '*'

表示监听所有网络接口。

也可以只监听指定地址,例如:

listen_addresses = 'localhost,192.168.1.100'

相比直接使用 *,指定具体服务器 IP 会更加严格。


九、确认 PostgreSQL 端口

PostgreSQL 默认端口为:

5432

在 postgresql.conf 中通常可以看到:

port = 5432

可以通过下面命令确认 PostgreSQL 是否正在监听:

sudo ss -lntp | grep 5432

如果看到类似:

0.0.0.0:5432

说明 PostgreSQL 正在监听所有 IPv4 网络接口。

如果只有:

127.0.0.1:5432

说明 PostgreSQL 目前只允许本机连接。


十、配置 Ubuntu UFW 防火墙

除了 PostgreSQL 自身的白名单外,如果 Ubuntu 开启了 UFW 防火墙,还需要允许对应 IP 或网段访问 5432 端口。

例如允许:

58.123.34.*

可以执行:

sudo ufw allow from 58.123.34.0/24 to any port 5432 proto tcp

查看规则:

sudo ufw status numbered

可能看到:

5432/tcp    ALLOW IN    58.123.34.0/24

这样只有这个网段能够通过 UFW 访问 PostgreSQL。


十一、不建议直接开放 PostgreSQL 端口

有些教程为了省事,会直接执行:

sudo ufw allow 5432

或者在 pg_hba.conf 中写:

host    all    all    0.0.0.0/0    scram-sha-256

这意味着 PostgreSQL 会对整个互联网开放。

生产环境中并不推荐这么做。

尤其是数据库服务器拥有公网 IP 时,很容易出现:

  • PostgreSQL 端口扫描
  • 用户名暴力破解
  • 密码爆破
  • 数据库漏洞扫描
  • 大量异常连接
  • 日志快速增长

因此建议同时在两个层面限制访问:

UFW / 云服务器安全组
↓
PostgreSQL pg_hba.conf
↓
数据库用户权限

形成多层防护。


十二、修改配置后如何生效?

修改 pg_hba.conf 后,可以执行:

sudo systemctl reload postgresql

通常不需要重启数据库。

也可以直接在 PostgreSQL 中执行:

SELECT pg_reload_conf();

如果修改的是:

listen_addresses

则需要重启 PostgreSQL:

sudo systemctl restart postgresql

然后检查状态:

sudo systemctl status postgresql

十三、查看 pg_hba.conf 是否存在配置错误

PostgreSQL 提供了一个非常实用的视图:

pg_hba_file_rules

可以进入 PostgreSQL:

sudo -u postgres psql

执行:

SELECT * FROM pg_hba_file_rules;

如果某一条规则存在格式错误,可以通过:

error

字段看到具体问题。

也可以执行:

SELECT line_number, type, database, user_name, address, auth_method, error
FROM pg_hba_file_rules;

用于快速检查配置。


十四、一个完整的生产环境配置示例

假设服务器情况如下:

PostgreSQL 数据库:
history_db

数据库用户:
history_user

允许访问的 IP:
58.123.34.*

PostgreSQL 端口:
5432

那么推荐配置如下。

pg_hba.conf

host    history_db    history_user    58.123.34.0/24    scram-sha-256

postgresql.conf

listen_addresses = '*'
port = 5432

Ubuntu UFW

sudo ufw allow from 58.123.34.0/24 to any port 5432 proto tcp

重新加载 PostgreSQL:

sudo systemctl reload postgresql

如果修改了 listen_addresses:

sudo systemctl restart postgresql

检查监听:

sudo ss -lntp | grep 5432

最后可以从远程服务器测试:

psql -h 数据库服务器IP -p 5432 -U history_user -d history_db

十五、常见问题

1. 配置了 /24 还是连接不上

首先检查 PostgreSQL 是否监听外部网络:

sudo ss -lntp | grep 5432

如果只有:

127.0.0.1:5432

需要检查:

listen_addresses

2. 出现 no pg_hba.conf entry

例如:

FATAL: no pg_hba.conf entry for host ...

通常说明客户端 IP 没有匹配到 pg_hba.conf 中允许的规则。

检查:

host    all    all    客户端IP或网段    scram-sha-256

是否正确。

同时确认修改之后执行了:

sudo systemctl reload postgresql

3. Connection refused

如果出现:

Connection refused

一般不是数据库密码问题,而可能是:

  • PostgreSQL 没有监听公网 IP
  • PostgreSQL 服务没有运行
  • 5432 端口没有开放
  • UFW 拦截
  • 云服务器安全组拦截
  • Docker 没有映射端口

可以依次检查:

sudo systemctl status postgresql
sudo ss -lntp | grep 5432
sudo ufw status

4. Connection timed out

如果是:

Connection timed out

通常更可能是网络层被拦截,例如:

云服务器安全组
UFW
iptables
运营商网络
服务器路由

需要从网络层排查,而不仅仅是检查 PostgreSQL。


十六、总结

Ubuntu 中 PostgreSQL 的 IP 白名单主要通过:

pg_hba.conf

进行配置。

如果需要允许:

58.123.34.*

不要使用:

58.123.34.*

而应该使用 CIDR:

58.123.34.0/24

例如:

host    all    all    58.123.34.0/24    scram-sha-256

如果是生产环境,更推荐限制到具体数据库和用户:

host    history_db    history_user    58.123.34.0/24    scram-sha-256

同时配合 Ubuntu 防火墙:

sudo ufw allow from 58.123.34.0/24 to any port 5432 proto tcp

整体上,可以把 PostgreSQL 远程访问安全理解为三层:

第一层:云服务器安全组 / UFW
↓
第二层:PostgreSQL pg_hba.conf
↓
第三层:数据库用户及权限控制

生产环境尽量遵循 最小权限原则:只开放必要的 IP、数据库、用户和端口,而不要直接将 PostgreSQL 的 5432 端口暴露给整个公网。