无法在Java 7上启用SNI
问题描述:
我正在尝试使用TLS调用服务器,只接受具有SNI支持的客户端。无法在Java 7上启用SNI
我正在使用Java 7的客户:
$ java -version
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)
应该是默认启用,但是:
- “它不工作”
- 我不能把它看成日志中的扩展名
例如从我的日志中:
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Extension renegotiation_info, renegotiated_connection: <empty>
***
虽然我希望找到
Extension server_name, server_name: [host_name: my.servername.com]
我尝试添加该标志-Djsse.enableSNIExtension=true
可以肯定的,但没有成功。
我正在使用的Netty 4.0.37测试,并得到此异常:
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLException: Received fatal alert: handshake_failure
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:442)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
什么把戏上的Java 7 JVM启用SNI?
答
问题出在Netty/SSL引擎配置上。
它用来进行配置很喜欢这样的:
public void initChannel(SocketChannel ch) throws Exception {
SSLEngine sslEngine = SSLContext.getDefault().createSSLEngine();
sslEngine.setUseClientMode(true);
ch.pipeline()
.addLast("ssl", new SslHandler(sslEngine));
}
实际上,它的工作可以这样来配置时,明确设定目标服务器名称:
public void initChannel(SocketChannel ch) throws Exception {
SslContext sslContext = SslContextBuilder.forClient().build();
ch.pipeline()
.addLast(
sslContext.newHandler(
ch.alloc(),
host,
port
)
);
}
利用这种结构,应该有在日志中(与-Djavax.net.debug=all
标志集):
Extension server_name, server_name: [type=host_name (0), value=target.hostname.com]