Postgresql无法接受SSL连接:sslv3警告证书未知。

4

我正在使用SpringBoot,配置数据源的URL为jdbc:postgresql://...../mydb?ssl=true&sslFactory=....nonValidating...

我的application.yml文件中有这个配置。

port: 8443
ssl:
 enabled: true
 key-alias: PGSQLServerHostNameHere
 key-store: keystore.jks
 key-store-password:....
 key-store-type: JKS
 trust-store: #this one is irrelevant, it's just a...
 ### ... trust store for other restTemplate stuff
 trust-store-password: ....
 key-password: ....
 ciphers: "TLSv1.2"
 protocol: TLS

然而,Postgresql也已经设置并运行了SSL=on。ssl_ciphers='TLSv1.2'

但是,在PGSQL日志中我得到了以下内容:

Postgresql could not accept SSL connection: sslv3 alert certificate unknown

我的Spring Boot应用在生产环境中出现了错误(但是在本地使用自签名证书时不会发生此错误):

org.postgresql...PSQLException: SSL error: sun.security.validator.ValdiatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

SSL证书配置

我在 root.crt 文件中拥有已签名的 Postgresql 服务器证书(包括正确别名的 Java 应用服务器的签名证书)。

我已将 Postgresql 服务器的签名证书(别名:PGSQLServerHostNameHere)作为“trustEntry”存储在 keystore.jks 中,用于我的私钥条目 privateKeyEntry。

我已在 keystore.jks 中添加了根 CA。

SpringBoot 应用程序在我的本地机器上使用自签名 JKS 可以正常工作。

但是 Postgresql 是个问题……拒绝来自 Java 应用服务器的通信。

postgresql.conf:

ssl = on
ssl_ciphers = 'TLSv1.2'

(everything else is default)

pg_hba.conf

hostssl all all md5

“我在我的keystore.jks中有privateKeyEntry,用于我的自己的服务器。”<=听起来像是罪魁祸首。你确定客户端没有将证书作为客户端验证器发送,而Postgres服务器因无法处理客户端证书验证而出现问题? - dhke
@dhke 不确定(我不是SSL专家)。我有另一个网站的客户端RestTemplate内容,我只需要一个trustStore。对于Java Spring Boot连接到自己的PGSQL,我认为我需要一个私钥+签名证书(使用openssl创建pkcs12文件),然后将pkcs12导入keytool jks与私钥一起,并将签名证书用于PGSQL(使用keytool import)导入到我的keystore.jks文件中。我对客户端认证一无所知。 - Dexter
1
您所拥有的SSL配置仅适用于HTTPS部分,不会用于其他任何内容(据我所知)。 - M. Deinum
@M.Deinum,您是在说SpringBoot不能通过-Djavax.net.ssl.keyStore=/path/to/keystore/keystore.jks自动配置它吗?我还需要额外添加这些命令行选项吗? - Dexter
1
这正是我想说的。那些SSL设置是用于配置servlet容器的HTTPS连接器,而不是一般的SSL。因此,这些属性在“server”命名空间中。 - M. Deinum
2个回答

2
Postgresql could not accept SSL connection: sslv3 alert certificate unknown
....
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
这意味着客户端无法接受服务器发出的证书,可能是因为颁发该证书的CA不在信任存储中。客户端将此问题作为警报发送给服务器,以便服务器知道连接失败的原因。
但是Postgresql存在问题...拒绝从Java应用程序服务器接收我的通信。
不,你的Java应用程序拒绝与Postgresql通信,因为它不信任该证书。您从Postgresql的错误消息中看到的只是您的Java应用程序作为不继续TLS握手的原因发送的内容。

是的,我同意,我认为错误显示的方式有点模糊。我认为你是对的。然而,我不知道该如何修复它。我在“keystore.jks”中拥有Java服务器的公共签名证书和私钥。我在“keystore.jks”中拥有PGSQL服务器的公共签名证书。PGSQL服务器在root.crt(信任CA)中包含Java服务器的公共签名证书,包括根+中间件。还需要什么?双方都拥有彼此签名的公共证书。双方都配置了自己的私钥。双方都有RootCA+Intermediary。这就是全部...我需要理论。 - Dexter
1
@Dexter:我不熟悉JDBC的要求(比如证书是否必须具有特定主题)。此外,从您的描述中,我无法确定证书的确切外观。您确定您正在使用正确的密钥库吗? - Steffen Ullrich
这就是我找不到文档的地方。我有一个用于客户端与另一台服务器通信的trustStore。还有一个用于与Postgresql进行SSL通信的keystore。但也许这两个会互相冲突。不清楚在哪里可以放置我的keystore+truststore(假设它是ssl.key-store),但也许这只适用于HTTPS而不是JDBC。也许教程/文档总是假定人们使用JDK的默认CA证书。 - Dexter
我目前也遇到了同样的问题,我可以在postgresql自己的控制台中看到它抱怨:“无法接受SSL连接:sslv3警报证书未知”;我的观点是问题不能归咎于客户端,甚至不归咎于postgresql - 它可能是这两者之一...要么客户端使用了错误的证书进行身份验证,要么postgresql没有正确配置(如果客户端证书是自签名的,则应该将证书放在ca文件中)。 - Jaroslav Záruba
1
@JaroslavZáruba:没错,TLS握手(因此PostgreSQL中的SSL_accept)失败是因为客户端无法验证证书。客户端因此以错误结束握手,并在TLS警报中告诉服务器出现了这个问题。服务器记录了这个问题。 - Steffen Ullrich
显示剩余3条评论

2
我想唯一的方法是查看JSSE实现并将“-Djavax.net.ssl”类型的命令添加到命令行或将其添加到“System.setProperty()”中。
此外,您可以将其添加到JDBC的url中,“ssl_cert = ...&ssl_key = ...”等等。
必须找到postgresql的正确命令。它没有很好的文档记录。
“application.yml”中的“ssl”属性与“javax.net.ssl”无关。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接