gRPC SSL 不存在主题替代名称
gRPC SSL No subject alternative names present
如何禁用 gRPC 中的主机名验证器以避免以下异常?
java.security.cert.CertificateException: No subject alternative names present
在主机名不匹配的情况下使用测试证书的推荐方法是调用 ManagedChannelBuilder.overrideAuthority("test-hostname")
。这在功能上类似于将测试主机名添加到 /etc/hosts
。这允许您使用 forAddress()
/forTarget()
选择不同的 IPs/DNS 名称,而无需禁用安全性。
但您的证书似乎还是有点损坏。主题备用名称是必需的;使用证书的主题已被弃用数十年。
您可能也有兴趣使用 gRPC's test certificates. We provide TlsTesting
加载它们。
server = ServerBuilder.forPort(0)
// Use test cert on server-side
.useTransportSecurity(
TlsTesting.loadCert("server1.pem"),
TlsTesting.loadCert("server1.key"))
// ...
.build().start();
channel = NettyChannelBuilder
.forAddress("localhost", server.getPort())
// Trust test CA on client-side
.sslContext(
GrpcSslContexts.forClient()
.trustManager(TlsTesting.loadCert("ca.pem"))
.build())
// Change hostname to match certificate
.overrideAuthority("foo.test.google.fr")
.build();
只是为了详细说明@Eric Anderson 的回答。在 gRPC 的测试证书中,他指出有两种类型的 *.cnf 文件用于生成客户端和服务器证书
1.Generate 客户端证书:openssl.cnf
2.Generate 服务器证书:server1-openssl.cnf
在这两个文件的最底部,您会找到需要为客户端和服务器添加匹配条目的主机名
例如,如果您在 "localhost" 上对客户端和服务器进行本地测试,那么您需要 openssl.cnf 和服务器 1-openssl.cnf 都具有
[alt_names]
DNS.1 = localhost
之后您需要重新生成证书
这是一个基于 grpc-java 信息 here
的简单脚本
#!/bin/bash
SERVER_CN=localhost
CLIENT_CN=localhost # Used when doing mutual TLS
TLS_KEY_PSSWD=somepsswd
echo "When prompted for cert information, everything is default except the common name which is set to localhost"
echo Generate CA key:
openssl genrsa -passout pass:TLS_KEY_PSSWD -des3 -out ca.key 4096
echo Generate CA:
openssl req -passin pass:TLS_KEY_PSSWD -x509 -new -nodes -key ca.key -out ca.pem -config conf/ca-openssl.cnf -days 3650 -extensions v3_req -subj "/CN=${SERVER_CN}"
echo "Now that we’re a CA on all our devices, we can sign certificates for any new dev sites that need HTTPS"
echo Generate client key:
openssl genrsa -out client.key.rsa 1024
openssl pkcs8 -topk8 -in client.key.rsa -out client.key -nocrypt
rm client.key.rsa
echo Generate client signing request:
openssl req -passin pass:TLS_KEY_PSSWD -new -key client.key -out client.csr -subj "/CN=${CLIENT_CN}"
echo Generate client cert:
openssl ca -passin pass:TLS_KEY_PSSWD -in client.csr -out client.pem -keyfile ca.key -cert ca.pem -verbose -config conf/openssl.cnf -days 3650 -updatedb
openssl x509 -in client.pem -out client.pem -outform PEM
echo Generate server key:
openssl genrsa -passout pass:TLS_KEY_PSSWD -out server1.key.rsa 1024
openssl pkcs8 -topk8 -in server1.key.rsa -out server1.key -nocrypt
rm server1.key.rsa
echo Generate server signing request:
openssl req -passin pass:TLS_KEY_PSSWD -new -key server1.key -out server1.csr -config conf/server1-openssl.cnf -subj "/CN=${CLIENT_CN}"
echo Generate server cert:
openssl ca -passin pass:TLS_KEY_PSSWD -in server1.csr -out server1.pem -keyfile ca.key -cert ca.pem -verbose -config conf/server1-openssl.cnf -days 3650 -extensions v3_req -updatedb
openssl x509 -in server1.pem -out server1.pem -outform PEM
如何禁用 gRPC 中的主机名验证器以避免以下异常?
java.security.cert.CertificateException: No subject alternative names present
在主机名不匹配的情况下使用测试证书的推荐方法是调用 ManagedChannelBuilder.overrideAuthority("test-hostname")
。这在功能上类似于将测试主机名添加到 /etc/hosts
。这允许您使用 forAddress()
/forTarget()
选择不同的 IPs/DNS 名称,而无需禁用安全性。
但您的证书似乎还是有点损坏。主题备用名称是必需的;使用证书的主题已被弃用数十年。
您可能也有兴趣使用 gRPC's test certificates. We provide TlsTesting
加载它们。
server = ServerBuilder.forPort(0)
// Use test cert on server-side
.useTransportSecurity(
TlsTesting.loadCert("server1.pem"),
TlsTesting.loadCert("server1.key"))
// ...
.build().start();
channel = NettyChannelBuilder
.forAddress("localhost", server.getPort())
// Trust test CA on client-side
.sslContext(
GrpcSslContexts.forClient()
.trustManager(TlsTesting.loadCert("ca.pem"))
.build())
// Change hostname to match certificate
.overrideAuthority("foo.test.google.fr")
.build();
只是为了详细说明@Eric Anderson 的回答。在 gRPC 的测试证书中,他指出有两种类型的 *.cnf 文件用于生成客户端和服务器证书
1.Generate 客户端证书:openssl.cnf
2.Generate 服务器证书:server1-openssl.cnf
在这两个文件的最底部,您会找到需要为客户端和服务器添加匹配条目的主机名
例如,如果您在 "localhost" 上对客户端和服务器进行本地测试,那么您需要 openssl.cnf 和服务器 1-openssl.cnf 都具有
[alt_names]
DNS.1 = localhost
之后您需要重新生成证书 这是一个基于 grpc-java 信息 here
的简单脚本#!/bin/bash
SERVER_CN=localhost
CLIENT_CN=localhost # Used when doing mutual TLS
TLS_KEY_PSSWD=somepsswd
echo "When prompted for cert information, everything is default except the common name which is set to localhost"
echo Generate CA key:
openssl genrsa -passout pass:TLS_KEY_PSSWD -des3 -out ca.key 4096
echo Generate CA:
openssl req -passin pass:TLS_KEY_PSSWD -x509 -new -nodes -key ca.key -out ca.pem -config conf/ca-openssl.cnf -days 3650 -extensions v3_req -subj "/CN=${SERVER_CN}"
echo "Now that we’re a CA on all our devices, we can sign certificates for any new dev sites that need HTTPS"
echo Generate client key:
openssl genrsa -out client.key.rsa 1024
openssl pkcs8 -topk8 -in client.key.rsa -out client.key -nocrypt
rm client.key.rsa
echo Generate client signing request:
openssl req -passin pass:TLS_KEY_PSSWD -new -key client.key -out client.csr -subj "/CN=${CLIENT_CN}"
echo Generate client cert:
openssl ca -passin pass:TLS_KEY_PSSWD -in client.csr -out client.pem -keyfile ca.key -cert ca.pem -verbose -config conf/openssl.cnf -days 3650 -updatedb
openssl x509 -in client.pem -out client.pem -outform PEM
echo Generate server key:
openssl genrsa -passout pass:TLS_KEY_PSSWD -out server1.key.rsa 1024
openssl pkcs8 -topk8 -in server1.key.rsa -out server1.key -nocrypt
rm server1.key.rsa
echo Generate server signing request:
openssl req -passin pass:TLS_KEY_PSSWD -new -key server1.key -out server1.csr -config conf/server1-openssl.cnf -subj "/CN=${CLIENT_CN}"
echo Generate server cert:
openssl ca -passin pass:TLS_KEY_PSSWD -in server1.csr -out server1.pem -keyfile ca.key -cert ca.pem -verbose -config conf/server1-openssl.cnf -days 3650 -extensions v3_req -updatedb
openssl x509 -in server1.pem -out server1.pem -outform PEM