I'm using Netty 4.1.14.Final
for my application's framework. I want to implement that the server can check the SNI information when the clients request using netty-tcnative-boringssl-static
.
But my application crashes once as I specify the -servername
as svc.v1
, and I got this message:
java: ../ssl/handshake_server.c:541: negotiate_version: Assertion `!ssl->s3->have_version' failed.
with the OpenSSL command:
openssl s_client -cert service.crt -key service.key -CAfile root_ca.pem -connect 127.0.0.1:8080 -servername svc.v1_1
CONNECTED(00000003)
write:errno=0
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 210 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1532336403
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
---
However, it works well if I specify the -servername
as svc.v1
, without the underline _
.
// define ssl provider
private static final SslProvider SSL_PROVIDER = SslProvider.OPENSSL;
// factory method for creating ssl context
public SslContext serverCtx(InputStream certificate, InputStream privateKey) {
try {
return SslContextBuilder.forServer(certificate, privateKey)
.sslProvider(SSL_PROVIDER)
.clientAuth(ClientAuth.REQUIRE)
.trustManager(TwoWayTrustManagerFactory.INSTANCE)
.build();
} catch (Exception e) {
throw new RuntimeException("failed to create ssl context", e);
}
}
// SNI Matcher implementation
@Slf4j
public class MySNIMatcher extends SNIMatcher {
private final byte[] hostIdentifier;
public MySNIMatcher(Identifier hostIdentifier) {
super(0);
this.hostIdentifier = hostIdentifier.idDistKey().getBytes(StandardCharsets.US_ASCII);
}
@Override
public boolean matches(SNIServerName sniServerName) {
return Arrays.equals(sniServerName.getEncoded(), hostIdentifier);
}
}
// Netty bootstrap
bootstrap.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
if (conf.logEnable())
pipeline.addLast("logging", new LoggingHandler());
if (conf.sslEnable()) {
// conf.sslCtx() will actually use serverCtx() to create context
SSLEngine engine = conf.sslCtx().newEngine(ch.alloc());
SSLParameters s = engine.getSSLParameters();
s.setSNIMatchers(new MySNIMatcher(...));
s.setEndpointIdentificationAlgorithm("HTTPS");
engine.setSSLParameters(s);
pipeline.addLast("ssl", new SslHandler(engine, true));
}
codec(pipeline);
int idleTimeout = (int) TimeUnit.MILLISECONDS.toSeconds(conf.idleTimeout());
if (0 < idleTimeout)
pipeline.addLast("idle", new IdleStateHandler(0, 0, idleTimeout));
pipeline.addLast("handler", handler);
}
})
Version: netty -> 4.1.14.Final netty-tcnative-boringssl-static -> 2.0.5.Final
Hostnames are not allowed to contain an underscore character, per the original RFC 952, and modified by RFC 1123. The following is from the Wikipedia page for Hostname.
The Internet standards (Requests for Comments) for protocols mandate that component hostname labels may contain only the ASCII letters 'a' through 'z' (in a case-insensitive manner), the digits '0' through '9', and the minus sign ('-'). The original specification of hostnames in RFC 952, mandated that labels could not start with a digit or with a minus sign, and must not end with a minus sign. However, a subsequent specification (RFC 1123) permitted hostname labels to start with digits. No other symbols, punctuation characters, or white space are permitted.