在服务器部署 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.* |
需要注意:
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 / 云服务器安全组 |
形成多层防护。
十二、修改配置后如何生效?
修改 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 |
用于快速检查配置。
十四、一个完整的生产环境配置示例
假设服务器情况如下:
PostgreSQL 数据库: |
那么推荐配置如下。
pg_hba.conf
host history_db history_user 58.123.34.0/24 scram-sha-256 |
postgresql.conf
listen_addresses = '*' |
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 |
通常更可能是网络层被拦截,例如:
云服务器安全组 |
需要从网络层排查,而不仅仅是检查 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 |
生产环境尽量遵循 最小权限原则:只开放必要的 IP、数据库、用户和端口,而不要直接将 PostgreSQL 的 5432 端口暴露给整个公网。