微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Netty 客户端中配置的密码列表未发送到服务器

如何解决Netty 客户端中配置的密码列表未发送到服务器

我有下面的代码来配置密码列表并发送到 Netty 客户端中的服务器。

Pair<String,String> config = Pair.of(keyStore,keyStorePassword);
if (!filters.containsKey(config)) {
    HttpClient securedClient = this.httpClient.secure(sslContextSpec -> {
        SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();
        sslContextBuilder.keyManager(loadKeyStore(keyStore,keyStorePassword));
        sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
        if(!StringUtils.isBlank(ciphers)) {
            sslContextBuilder.ciphers(getCiphersList(ciphers));
        }
        sslContextSpec.sslContext(sslContextBuilder);
    });
    filters.put(config,new NettyRoutingFilter(securedClient,headersFilters,properties));
}
return filters.get(config).filter(exchange,chain);

这段代码运行良好。最近升级了spring boot和云版本,之后出现SSL握手失败。

根据服务器端 SSL 调试日志,此失败是由于 no ciphers suites in common 错误

我进一步检查并发现客户端正在尝试与 TLSv1.2 发起握手,并在我看来 Netty 被过滤掉了配置的密码 (TLS_DHE_DSS_WITH_AES_256_GCM_SHA384)。

我可以在客户端的 SSL 日志中看到以下两个日志部分,只有第二部分到达服务器。 (没有TLS_DHE_DSS_WITH_AES_256_GCM_SHA384

javax.net.ssl|DEBUG|34|es-writer-6|2021-03-25 10:48:25.081 SGT|ClientHello.java:651|Produced ClientHello handshake message (
"ClientHello": {
  "client version"      : "TLSv1.2","random"              : "47 5B 0F EB C7 9C 1B A1 21 C0 60 15 AC FD 5B 88 67 07 F9 2B 04 4A 74 ED 9B 37 CD 84 81 65 87 F8","session id"          : "33 FD 38 2C 7D 71 62 79 2E F1 99 7D FB 5F 69 F6 04 23 9A 31 04 9B 5D 0A 16 B2 76 10 A3 C5 74 E6","cipher suites"       : "[TLS_AES_128_GCM_SHA256(0x1301),TLS_AES_256_GCM_SHA384(0x1302),TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(0xC02C),TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256(0xC02B),TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(0xC030),TLS_RSA_WITH_AES_256_GCM_SHA384(0x009D),TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384(0xC02E),TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384(0xC032),TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(0x009F),TLS_DHE_DSS_WITH_AES_256_GCM_SHA384(0x00A3),TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(0xC02F),TLS_RSA_WITH_AES_128_GCM_SHA256(0x009C),TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256(0xC02D),TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256(0xC031),TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(0x009E),TLS_DHE_DSS_WITH_AES_128_GCM_SHA256(0x00A2),TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384(0xC024),TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384(0xC028),TLS_RSA_WITH_AES_256_CBC_SHA256(0x003D),TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384(0xC026),TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384(0xC02A),TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(0x006B),TLS_DHE_DSS_WITH_AES_256_CBC_SHA256(0x006A),TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA(0xC00A),TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA(0xC014),TLS_RSA_WITH_AES_256_CBC_SHA(0x0035),TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA(0xC005),TLS_ECDH_RSA_WITH_AES_256_CBC_SHA(0xC00F),TLS_DHE_RSA_WITH_AES_256_CBC_SHA(0x0039),TLS_DHE_DSS_WITH_AES_256_CBC_SHA(0x0038),TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256(0xC023),TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(0xC027),TLS_RSA_WITH_AES_128_CBC_SHA256(0x003C),TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256(0xC025),TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256(0xC029),TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(0x0067),TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(0x0040),TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(0xC009),TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(0xC013),TLS_RSA_WITH_AES_128_CBC_SHA(0x002F),TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA(0xC004),TLS_ECDH_RSA_WITH_AES_128_CBC_SHA(0xC00E),TLS_DHE_RSA_WITH_AES_128_CBC_SHA(0x0033),TLS_DHE_DSS_WITH_AES_128_CBC_SHA(0x0032),TLS_EMPTY_RENEGOTIATION_INFO_SCSV(0x00FF)]",javax.net.ssl|DEBUG|2D|reactor-http-nio-1|2021-03-25 10:48:25.275 SGT|ClientHello.java:651|Produced ClientHello handshake message (
"ClientHello": {
  "client version"      : "TLSv1.2","random"              : "48 3A 89 68 7F CE 49 83 FE EF 12 81 2D E3 EE 54 47 90 A8 33 EE 95 F6 16 76 B9 81 41 E9 DA B6 2E","session id"          : "69 CC E2 A3 BA 6A AF 47 8B 3E 83 53 4E 5F 62 90 B3 91 F3 E3 9D 5C 1A 2D C3 F7 F7 6D 2E EA 38 7C","cipher suites"       : "[TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(0xC02C),TLS_AES_128_GCM_SHA256(0x1301),TLS_AES_256_GCM_SHA384(0x1302)]",

如何发送配置的密码,即使它们已经过时(弱)?此处的 SslContextBuilder 配置有问题吗?

更新

进一步分析有助于找出错过配置密码的实际原因。

作为 Spring boot 版本升级的一部分,reactor Netty 版本已从 0.9.12 升级到 1.0.3。

我可以看到 reactor.netty.tcp.SslProvider

逻辑的以下差异

0.9.12

void updateDefaultConfiguration() {
switch(this.type) {
case H2:
    this.sslContextBuilder.sslProvider(io.netty.handler.ssl.SslProvider.isAlpnSupported(io.netty.handler.ssl.SslProvider.OPENSSL) ? io.netty.handler.ssl.SslProvider.OPENSSL : io.netty.handler.ssl.SslProvider.JDK).ciphers(Http2SecurityUtil.CIPHERS,SupportedCipherSuiteFilter.INSTANCE).applicationProtocolConfig(new ApplicationProtocolConfig(Protocol.ALPN,SelectorFailureBehavior.NO_ADVERTISE,SelectedListenerFailureBehavior.ACCEPT,new String[]{"h2","http/1.1"}));
    break;
case TCP:
    this.sslContextBuilder.sslProvider(OpenSsl.isAvailable() ? io.netty.handler.ssl.SslProvider.OPENSSL : io.netty.handler.ssl.SslProvider.JDK);
case NONE:
}

}

1.0.3

void updateDefaultConfiguration() {
    switch(this.type) {
    case H2:
        this.sslContextBuilder.sslProvider(io.netty.handler.ssl.SslProvider.isAlpnSupported(io.netty.handler.ssl.SslProvider.OPENSSL) ? io.netty.handler.ssl.SslProvider.OPENSSL : io.netty.handler.ssl.SslProvider.JDK).ciphers(HTTP2_CIPHERS,"http/1.1"}));
        break;
    case TCP:
        this.sslContextBuilder.sslProvider(OpenSsl.isAvailable() ? io.netty.handler.ssl.SslProvider.OPENSSL : io.netty.handler.ssl.SslProvider.JDK).ciphers((Iterable)null,IdentityCipherSuiteFilter.INSTANCE).applicationProtocolConfig((ApplicationProtocolConfig)null);
    case NONE:
    }

}

在 1.0.3 中,它强制将密码覆盖为 null,并且不再能够手动设置密码。

我该如何解决这个问题?

解决方法

最后,我发现在分配给新反应器 Netty 版本中的上下文规范之前需要构建 SSL 上下文。

工作代码:

HttpClient securedClient = this.httpClient.secure(sslContextSpec -> {
 SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();
 sslContextBuilder.keyManager(loadKeyStore(keyStore,keyStorePassword));
 sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
 if (!StringUtils.isBlank(ciphers)) {
    sslContextBuilder.ciphers(getCiphersList(ciphers));
 }
 try {
    sslContextSpec.sslContext(sslContextBuilder.build());
 } catch (SSLException e) {
   log.error("Error in building the SSL context ",e);
 }
});

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。