配置Nginx作为PostgreSQL TCP连接的SSL反向代理后,客户端报错‘SSL is not allowed on the server’的问题排查
我来帮你拆解这个问题的核心,你遇到的错误本质是客户端、Nginx、PostgreSQL三者之间的SSL期望不匹配,咱们一步步理清楚:
问题根源分析
你的架构是:外部客户端 ←SSL→ Nginx(SSL终止) ←明文TCP→ PostgreSQL。但目前的问题出在:
当你用DBeaver连接Nginx的5430端口时,客户端可能默认/被配置为先向PostgreSQL发起“是否支持SSL”的请求(PostgreSQL客户端协议会先发一个0x01的字节询问),而你的PostgreSQL并没有开启SSL支持,所以PostgreSQL直接返回了“SSL is not allowed on the server”的错误,这个错误被Nginx透传给了客户端,就出现了你看到的提示。
同时你的Nginx配置是强制SSL终止的(配置了ssl_certificate等参数),意味着连接5430端口的客户端必须先完成SSL握手才能发送后续数据,但如果DBeaver的SSL模式配置不对,就会出现“客户端发的请求不符合Nginx/PostgreSQL预期”的矛盾。
具体解决步骤
根据你的需求(在Nginx层实现SSL加密,后端PostgreSQL保持明文连接),推荐以下方案:
1. 调整DBeaver的SSL连接配置
因为你已经通过Nginx实现了客户端到网关的SSL加密,客户端不需要再和后端PostgreSQL谈SSL,只需要确保和Nginx完成SSL握手即可:
- 打开DBeaver的连接编辑窗口,切换到「SSL」标签页
- 将「SSL模式」设置为Require(必须使用SSL):这个模式下,客户端会直接和Nginx发起SSL握手,不会先发那个询问PostgreSQL的0x01字节
- 如果你的Nginx证书是自签的,记得勾选「信任服务器证书」,或者把证书导入DBeaver的信任存储中
2. 优化Nginx的Stream配置
把你的配置稍作调整,明确端口的SSL属性,避免歧义:
stream{ upstream pg{ server [postgresql server ip]:5432; } server{ listen 5430 ssl; # 明确标记这个端口是SSL端口 ssl_protocols TLSv1.2 TLSv1.3; # 建议只保留高版本协议,更安全 ssl_ciphers HIGH:!aNULL:!MD5; # 替换成更安全的加密套件 ssl_certificate /etc/nginx/cert/server.crt; ssl_certificate_key /etc/nginx/cert/server.key; ssl_session_timeout 2h; ssl_verify_client off; proxy_pass pg; } }
修改后重启Nginx:systemctl restart nginx
3. 验证PostgreSQL的连接权限
确保PostgreSQL的pg_hba.conf允许Nginx服务器的IP连接:
host all all [nginx服务器IP]/32 scram-sha-256
修改后重载PostgreSQL配置:pg_ctl reload
备选方案(如果需要端到端SSL)
如果你希望Nginx和PostgreSQL之间也用SSL连接,可以开启PostgreSQL的SSL,并调整Nginx配置:
- 修改PostgreSQL的
postgresql.conf:ssl = on ssl_cert_file = '/var/lib/postgresql/14/main/server.crt' # 替换成你的证书路径 ssl_key_file = '/var/lib/postgresql/14/main/server.key' # 替换成你的密钥路径 - 在Nginx的stream server块中添加SSL上游配置:
# 在proxy_pass之前添加 proxy_ssl on; proxy_ssl_protocols TLSv1.2 TLSv1.3; proxy_ssl_ciphers HIGH:!aNULL:!MD5;
这样就能实现客户端→Nginx→PostgreSQL的全链路SSL加密,同时避免错误。
备注:内容来源于stack exchange,提问作者George Y

