Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Future-proof and flexible hostname verification #12343

@chrisvest

Description

@chrisvest

In Netty 4.2 we changed the default endpoint identification algorithm to “HTTPS”, thereby enabling hostname verification by default.
This has no effect on gRPC-Java, because it was already always enabling hostname verification:

@Override
@IgnoreJRERequirement
protected void handlerAdded0(ChannelHandlerContext ctx) {
sslEngine = sslContext.newEngine(ctx.alloc(), host, port);
SSLParameters sslParams = sslEngine.getSSLParameters();
sslParams.setEndpointIdentificationAlgorithm("HTTPS");
sslEngine.setSSLParameters(sslParams);
ctx.pipeline().addBefore(ctx.name(), /* name= */ null, this.executor != null
? new SslHandler(sslEngine, false, this.executor)
: new SslHandler(sslEngine, false));
}

Unfortunately, the above means gRPC-Java doesn’t offer any nice way to disable hostname verification in situations where the client expects a non-DNS identity from the server, such as a SPIFFE in a URI SAN.
A client that wishes to authenticate non-DNS identities needs to implement a custom TrustManager that nerfs out the endpoint identification algorithm in the provided SSLEngine, before proceeding with the authentication procedure. When we use the OPENSSL provider, this adds an extra JNI call per handshake that could otherwise be avoided.

A better approach would be to configure the endpoint identification algorithm in the SslContextBuilder. Since Netty 4.1.112, we’ve been exposing this as a configuration method:
https://netty.io/4.1/api/io/netty/handler/ssl/SslContextBuilder.html#endpointIdentificationAlgorithm-java.lang.String-

The GrpcSslContexts class in gRPC-Java already provides ssl context builder objects with sane defaults that people are encouraged to use. It makes sense that it would provide instances to clients that have the “HTTPS” endpoint identification algorithm pre-configured. Clients could then choose to opt out of hostname verification if they need to.

Now, with the above proposed change, if people don’t use the GrpcSslContexts class but instead create their own SslContextBuilder, then it’s possible that they were previously protected by hostname verification but now no longer are.
It is possible to issue or log a warning, in that case. There are two ways to disable hostname verification: 1) the endpoint identification algorithm can be null (the default in 4.1), or 2) the algorithm can be the empty string. In gRPC-Java, we can use these to distinguish between a poor default, null, and intentionally opting out of hostname verification with the empty string.
Alternatively, gRPC-Java can overwrite the null values to preserve the default safety it currently enjoy, and then accept the empty string as an intentional choice to opt out.

By removing the code in the ClientTlsHandler and instead relying on the setter in the SslContextBuilder, we can get the authentication flexibility that certain clients need for dealing with non-DNS identities, while preserving the safe defaults we currently have.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions