PostgreSQL SSL连接报错:主机名无法验证问题求助
这个主机名验证失败的问题我之前帮不少开发者排查过,本质是SSL证书中的主机标识(Common Name/Subject Alternative Name)和你实际连接的PostgreSQL服务器地址不匹配,PostgreSQL客户端在默认的verify-full严格验证模式下会拒绝这种不匹配的连接。咱们一步步来修复:
1. 检查现有证书的主机标识是否匹配
首先得确认你在CentOS上生成的server.crt里是否包含了连接时用的主机名/IP地址:
- 如果还能访问CentOS机器,执行以下命令查看证书详情:
openssl x509 -in server.crt -text -noout - 如果你只有Windows环境,安装OpenSSL后也可以在命令行执行同样的命令(把路径换成
C:\Users\xxxx\AppData\Roaming\postgresql\server.crt)。
在输出里找两个关键部分:
Subject字段里的CN=(Common Name),看是否和你连接PostgreSQL时用的主机名/IP一致;X509v3 Subject Alternative Name字段,如果有这个扩展,里面的DNS:或IP:条目是否包含目标地址。
如果这两个地方都没有匹配你实际用的连接地址,那证书就是问题根源,需要重新生成。
2. 重新生成包含正确主机标识的Server证书
如果证书的主机标识不对,回到CentOS机器重新生成server.crt:
方法1:仅指定Common Name(适用于单地址场景)
执行以下命令生成新的证书请求和证书:
# 生成证书签名请求(CSR),替换your_postgres_host为实际的主机名/IP openssl req -new -key server.key -out server.csr -subj "/CN=your_postgres_host" # 用根证书签发新的server证书 openssl x509 -req -in server.csr -CA root.crt -CAkey root.key -CAcreateserial -out server.crt -days 365
方法2:添加Subject Alternative Name(适用于多地址场景)
如果你的PostgreSQL服务器需要用多个地址访问(比如同时支持localhost和内网IP),需要修改OpenSSL配置文件:
- 复制系统默认的
openssl.cnf(通常在/etc/pki/tls/openssl.cnf)为临时配置文件,比如my_openssl.cnf; - 找到
[req]段,添加或修改:req_extensions = v3_req - 找到
[v3_req]段,添加:subjectAltName = @alt_names - 在文件末尾添加:
[alt_names] DNS.1 = your_postgres_hostname IP.1 = your_postgres_server_ip # 可以添加更多条目,比如DNS.2、IP.2 - 用修改后的配置生成证书:
openssl req -new -key server.key -out server.csr -config my_openssl.cnf openssl x509 -req -in server.csr -CA root.crt -CAkey root.key -CAcreateserial -out server.crt -days 365 -extensions v3_req -extfile my_openssl.cnf
生成完成后,把新的server.crt替换Windows客户端目录和PostgreSQL服务器(Windows上的data目录,比如C:\Program Files\PostgreSQL\15\data)里的旧证书,确保server.key的权限在服务器上设置为仅管理员可读。
3. 临时绕过主机名验证(不推荐用于生产环境)
如果暂时无法重新生成证书,也可以降低SSL验证级别来临时解决:
在连接PostgreSQL时,把sslmode参数设置为verify-ca而不是默认的verify-full。比如用psql连接:
psql "host=your_postgres_host dbname=your_db user=your_user sslmode=verify-ca"
或者在你的应用连接字符串里添加这个参数,这样客户端只会验证证书是否由信任的CA(你的root.crt)签发,而不会检查主机名是否匹配。但注意这个方法会降低安全性,生产环境还是建议修复证书。
4. 确认证书路径和权限
最后再检查一遍:
- Windows客户端的
root.crt、server.crt确实在C:\Users\xxxx\AppData\Roaming\postgresql目录下; - PostgreSQL服务器上的
server.crt和server.key放在正确的data目录,且server.key的权限设置为仅PostgreSQL服务账户可读(Windows上可以右键文件→属性→安全,移除其他用户的读取权限)。
内容的提问来源于stack exchange,提问作者ashish chauhan

