Ошибка SSL / TLS («нет общих наборов шифров») с Netty при попытке установить безопасное соединение между внешним интерфейсом и внутренним сервером - PullRequest
1 голос
/ 02 марта 2012

Я хочу защитить 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

Этот пост , к сожалению, не помог. Что-то не так с конфигурацией серверов? Или я использую неправильный тип сертификата?

...