在io.netty.handler.ssl.Sslcontext中禁用主机名验证

4

有没有一种方法可以禁用io.netty.handler.ssl.Sslcontext的主机名验证?

我有这段代码:

sslContext = SslContextBuilder
        .forClient()
        .sslProvider(SslProvider.JDK)
        .trustManager(InsecureTrustManagerFactory.INSTANCE)
        .build();

DefaultAsyncHttpClientConfig.Builder builder = new DefaultAsyncHttpClientConfig.Builder();
builder.setSslContext(sslContext);
AsyncHttpClientConfig asyncHttpClientConfig = builder.build();

这在本地主机信任所有证书的情况下运行良好,但我需要连接到本地IP以测试某个服务,但我遇到了以下异常:

java.util.concurrent.CompletionException: java.net.ConnectException: General SSLEngine problem
    at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
    at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
    at java.util.concurrent.CompletableFuture.uniApply(CompletableFuture.java:593)
    at java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:577)
    at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
    at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1977)
    at org.asynchttpclient.netty.NettyResponseFuture$1.run(NettyResponseFuture.java:269)
    at org.asynchttpclient.netty.NettyResponseFuture$2.execute(NettyResponseFuture.java:277)
    at org.asynchttpclient.future.ExecutionList.executeListener(ExecutionList.java:125)
    at org.asynchttpclient.future.ExecutionList.execute(ExecutionList.java:115)
    at org.asynchttpclient.future.AbstractListenableFuture.runListeners(AbstractListenableFuture.java:80)
    at org.asynchttpclient.netty.NettyResponseFuture.abort(NettyResponseFuture.java:252)
    at org.asynchttpclient.netty.channel.NettyConnectListener.onFailure(NettyConnectListener.java:162)
    at org.asynchttpclient.netty.channel.NettyConnectListener$1.onFailure(NettyConnectListener.java:131)
    at org.asynchttpclient.netty.SimpleFutureListener.operationComplete(SimpleFutureListener.java:26)
    at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:514)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:507)
    at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:486)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:427)
    at io.netty.util.concurrent.DefaultPromise.tryFailure(DefaultPromise.java:129)
    at io.netty.handler.ssl.SslHandler.notifyHandshakeFailure(SslHandler.java:1235)
    at io.netty.handler.ssl.SslHandler.setHandshakeFailure(SslHandler.java:1230)
    at io.netty.handler.ssl.SslHandler.setHandshakeFailure(SslHandler.java:1205)
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1060)
    at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:900)
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:411)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:611)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:552)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:466)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:140)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.ConnectException: General SSLEngine problem
    at org.asynchttpclient.netty.channel.NettyConnectListener.onFailure(NettyConnectListener.java:160)
    ... 29 common frames omitted
    Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1431)
    at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:535)
    at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:813)
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781)
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1094)
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:966)
    ... 18 common frames omitted
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1728)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:304)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
    at sun.security.ssl.Handshaker$1.run(Handshaker.java:919)
    at sun.security.ssl.Handshaker$1.run(Handshaker.java:916)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1369)
    at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1120)
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1005)
    ... 18 common frames omitted
Caused by: java.security.cert.CertificateException: No subject alternative names present
    at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:144)
    at sun.security.util.HostnameChecker.match(HostnameChecker.java:93)
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)
    at sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(SSLContextImpl.java:998)
    at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:937)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
    ... 26 common frames omitted

谢谢


禁用主机名验证几乎与禁用任何类型的验证相同,因为攻击者现在所需的仅是由受信任的CA签名的证书,无论主题是什么。这通常很容易获得。如果您需要访问某个具有不匹配证书的站点,则应使用固定来通过预期的证书标识该站点,或者使用自定义主机名验证器来检查您所期望的主机名。 - Steffen Ullrich
谢谢,那我该如何添加自定义主机名验证器? - Ana Franco
请参考 https://tersesystems.com/2014/03/23/fixing-hostname-verification/ 获取示例代码。 - Steffen Ullrich
1
我也找到了那篇文章,但它是针对javax.net.ssl.SSLContext的。我正在使用io.netty.handler.ssl.Sslcontext,这就是为什么我无法更改主机名验证器的原因。 - Ana Franco
抱歉,我无法再提供帮助了。我并不真正熟悉Java处理SSL的各种方式,这取决于特定的库(看起来是同一件事情的太多不同方式),但我熟悉SSL的安全方面。 - Steffen Ullrich
2个回答

6

我发现在clientConfig构建器中添加setAcceptAnyCertificate(true)可以以这种方式解决问题:

sslContext = SslContextBuilder
    .forClient()
    .sslProvider(SslProvider.JDK)
    .trustManager(InsecureTrustManagerFactory.INSTANCE)
    .build();

DefaultAsyncHttpClientConfig.Builder builder = new DefaultAsyncHttpClientConfig.Builder();
builder.setSslContext(sslContext)
    .setAcceptAnyCertificate(true);

AsyncHttpClientConfig asyncHttpClientConfig = builder.build();

感谢大家。

0

1
证书被忽略了,问题是主机名不同。 - Ana Franco

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