Я хочу защитить TCP-соединение между бэкэндом и внешним интерфейсом. Мы используем Netty для установления TCP-соединения, которое работает довольно хорошо. Теперь мы хотим защитить это соединение с помощью SSL / TLS. По этой причине я создал запрос сертификата:
openssl req -newkey rsa:2048 -keyout key.pem -out request.pem -subj '/C=DE/O=XX/ST=XX/L=XX/O=XX/OU=XX/CN=someaddress.de/emailAddress=support@xxx.de'
Сертификат был создан ЦС.
Хранилище ключей было создано с:
keytool -import -alias xxx -keystore xxx.keystore -file cert-xxx.pem
Сервер с Netty на сервере:
public StatefulTcpServer(MessageHandler messageHandler, int port, KeyStore keyStore, String keyStorePassword) {
this.messageHandler = messageHandler;
factory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool());
allChannels = new DefaultChannelGroup("clients");
initTLS(keyStore, keyStorePassword);
ServerBootstrap bootstrap = new ServerBootstrap(factory);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline();
if (sslContext != null) {
SSLEngine sslEngine = sslContext.createSSLEngine();
sslEngine.setUseClientMode(false);
sslEngine.setEnabledCipherSuites(new String[] {
"TLS_RSA_WITH_AES_128_CBC_SHA"
});
pipeline.addLast("ssl", new SslHandler(sslEngine));
}
pipeline.addLast("compressor", new ZlibEncoder());
pipeline.addLast("decompressor", new ZlibDecoder());
pipeline.addLast("decoder", new JBossSerializationDecoder());
pipeline.addLast("encoder", new JBossSerializationEncoder());
pipeline.addLast("handler", StatefulTcpServer.this);
return pipeline;
}
});
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.keepAlive", true);
bootstrap.bind(new InetSocketAddress(port));
}
private void initTLS(KeyStore keyStore, String keyStorePassword) {
try {
if (keyStore != null) {
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, keyStorePassword.toCharArray());
sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
}
}
catch (GeneralSecurityException e) {
logger.error("TLS connection could not be established", e);
sslContext = null;
}
}
Сервер с Netty во внешнем интерфейсе:
public void init(String backendHost, int backendPort, int timeOutSecs, boolean useTLS,
boolean acceptOnlyTrustworthyCertsForTLS) throws ConnectionFailedException {
channelFactory = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
if (useTLS) {
initTLS(acceptOnlyTrustworthyCertsForTLS);
}
ClientBootstrap bootstrap = new ClientBootstrap(channelFactory);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline();
if (sslContext != null) {
SSLEngine sslEngine = sslContext.createSSLEngine();
sslEngine.setUseClientMode(true);
sslEngine.setEnabledCipherSuites(new String[] {
"TLS_RSA_WITH_AES_128_CBC_SHA"
});
pipeline.addLast("ssl", new SslHandler(sslEngine));
}
pipeline.addLast("compressor", new ZlibEncoder());
pipeline.addLast("decompressor", new ZlibDecoder());
pipeline.addLast("decoder", new JBossSerializationDecoder());
pipeline.addLast("encoder", new JBossSerializationEncoder());
pipeline.addLast("handler", StatefulTcpBackendCommunicator.this);
return pipeline;
}
});
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("keepAlive", true);
channelFuture = bootstrap.connect(new InetSocketAddress(backendHost, backendPort));
try {
boolean connected = channelFuture.await(timeOutSecs * 1000);
if (!connected || !channelFuture.isSuccess()) {
throw new ConnectionFailedException();
}
}
catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
private void initTLS(boolean acceptOnlyTrustworthyCertsForTLS) {
try {
TrustManager[] trustManagers;
if (acceptOnlyTrustworthyCertsForTLS) {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory
.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
trustManagers = trustManagerFactory.getTrustManagers();
}
else {
trustManagers = new TrustManager[] {
new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
return;
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
return;
}
}
};
}
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, new SecureRandom());
}
catch (GeneralSecurityException e) {
logger.error("TLS connection could not be established. TLS is not used!", e);
sslContext = null;
}
}
При попытке установить связь между внешним и внутренним интерфейсами я получаю исключение:
javax.net.ssl.SSLHandshakeException: no cipher suites in common
Этот пост , к сожалению, не помог. Что-то не так с конфигурацией серверов? Или я использую неправильный тип сертификата?