PostgreSQL连接被拒:客户端经Mikrotik dst-nat访问时呈公网IP无法连接
问题根因
该问题为跨子网内网访问DNAT暴露服务的典型配置错误,触发原因如下:
- PostgreSQL访问规则不匹配:默认配置下PostgreSQL的
postgresql.conf仅监听本地或同网段内网IP,pg_hba.conf也未放通客户端所在的其他内网子网的访问权限,同时未将对外暴露的公网IP加入监听列表,收到目标地址为公网IP的请求时会直接拒绝。 - Mikrotik回环NAT(Hairpin NAT)配置缺失:路由器仅配置了目标地址转换(DNAT)规则将公网IP请求转发到服务端内网IP,未配置对应的源地址伪装规则,跨子网内网客户端通过公网IP发起请求时,PostgreSQL服务端收到的请求目标地址仍为对外暴露的公网IP,匹配不到监听规则就会抛出公网IP无法连接的报错,和你在路由器日志中看到的客户端源IP为内网IP的现象完全吻合。
排查与解决方案
按照以下顺序操作即可解决问题:
- 调整PostgreSQL基础配置
- 编辑
postgresql.conf文件,修改listen_addresses参数为*或者同时填写服务端内网IP、对外暴露的公网IP,修改后保存:
也可以连接到PostgreSQL服务端执行以下命令验证当前配置:listen_addresses = '*'SHOW listen_addresses; - 编辑
pg_hba.conf文件,添加客户端所在内网子网的访问规则,示例如下(替换为你实际的客户端子网段):# 放通192.168.2.0/24子网的所有用户通过密码验证访问任意数据库 host all all 192.168.2.0/24 scram-sha-256 - 执行命令重载PostgreSQL配置使修改生效:
systemctl reload postgresql - 验证服务端防火墙是否放通5432端口的入站请求,以ufw为例:
ufw allow in from 192.168.0.0/16 to any port 5432
- 编辑
- 调整.NET应用连接配置
优先修改数据库连接字符串中的主机地址为PostgreSQL服务端的内网IP,避免不必要的NAT转换,示例配置:"ConnectionStrings": { "Default": "Host=192.168.1.100;Port=5432;Database=your_db;Username=postgres;Password=your_password;" } - 配置Mikrotik回环NAT规则(仅需在必须通过公网IP访问服务的场景下配置)
登录Mikrotik路由器终端,执行以下命令添加源地址伪装规则,替换参数为你的实际网段和服务端IP:
确认原有DNAT规则配置正确,示例如下:# 192.168.0.0/16替换为你内网所有子网的汇总段,192.168.1.100替换为PostgreSQL服务端内网IP /ip firewall nat add chain=srcnat action=masquerade protocol=tcp src-address=192.168.0.0/16 dst-address=192.168.1.100 dst-port=5432# 公网5432端口请求转发到内网服务端的5432端口 /ip firewall nat add chain=dstnat action=dst-nat protocol=tcp dst-port=5432 to-addresses=192.168.1.100 to-ports=5432
内容的提问来源于stack exchange,提问作者Ivo Pavlik
相关产品推荐
相关产品推荐

