Перенаправлять HTTP-запросы на HTTPS в netty

#elasticsearch #netty

#elasticsearch #netty

Вопрос:

Я модифицирую код elasticsearch для настройки HTTPS без x-pack и обратных прокси. Я изменил метод initchannel () в файле netty4HttpServerTransport, https работает нормально, но я хочу перенаправить http на https.. Код является,

 char[] password = "your5663".toCharArray();
        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(new FileInputStream("C:/OpenSSL-Win64/bin/keystore1.jks"),password);

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, password);

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(ks);
        TrustManager[] tm = tmf.getTrustManagers();

        SSLContext sslContext  = SSLContext.getInstance("TLSv1.3");
        sslContext .init( kmf.getKeyManagers(), tm, null);
        SSLEngine sslengine = sslContext .createSSLEngine();

        sslengine.setUseClientMode(false);

        String[] DEFAULT_PROTOCOLS = { "TLSv1", "TLSv1.1", "TLSv1.2","TLSv1.3" };
        String[] DEFAULT_CIPHERS = {"TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA"};

        sslengine.setEnabledProtocols(DEFAULT_PROTOCOLS);
        sslengine.setEnabledCipherSuites(DEFAULT_CIPHERS);

        SslHandler sslHandler = new SslHandler(sslengine);
        ch.pipeline().addLast("ssl", sslHandler);      
        ch.pipeline().addAfter("ssl","handshake",new StringEventHandler());
  

Как мне перенаправить http на https в этом коде.

Ответ №1:

Перенаправление работает на уровне полезной нагрузки (http), а не на транспортном уровне ssl. Вам нужно будет прослушивать оба протокола (http и https), а на http-канал вы можете ответить кодом состояния перенаправления. Короче говоря — в вашем коде нет прямого места, где вы могли бы это сделать.

Очень часто для этой задачи используется прокси-сервер. Я не уверен, что вы можете сделать это в elasticsearch, вы можете попробовать настроить сервлет фильтра, чтобы проверить, отвечает ли протокол перенаправлением. Это может быть полезно https://github.com/elastic/elasticsearch-transport-wares

Другой факт — если перенаправление предназначено для клиентов-служб (не для пользовательского интерфейса на основе браузера), клиенты могут / будут рассматривать ответ перенаправления как ответ ошибки. В зависимости от вашей среды — возможно, вы можете просто предоставить конечную точку ssl (без перенаправлений), и клиенты должны будут соответствовать

Ответ №2:

У Netty есть встроенный обработчик для этого, OptionalSslHandler.

Вы помещаете его в начало своего конвейера, и он определяет, зашифровано сообщение или нет. Если это так, то сообщение будет отправлено по обычному SSL-конвейеру, если нет, то вы можете указать другое место для его отправки, например, перенаправление 301 на https.

Вы могли бы либо использовать эту версию Netty, либо создать свой собственный обработчик, который выполняет нечто подобное.

Однако, чтобы использовать версию Netty, вам потребуется провести небольшой рефакторинг, чтобы создать Netty SSLContext io.netty.handler.ssl.SslContext вместо SSLEngine.

Что-то вроде этого:

 char[] password = "your5663".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("C:/OpenSSL-Win64/bin/keystore1.jks"),password);

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, password);

SslContext sslContext = SslContextBuilder.forServer(keyManagerFactory).build();

ch.pipeline().addLast("ssl", sslHandler);

// this is an imaginary handler you create that sends HTTP a 301 to HTTPS
// non-SSL can be detected easily because there is no SslHandler on this channel
ch.pipeline().addLast("redirectHandler", new RedirectHandler()); 

ch.pipeline().addLast("handshake",new StringEventHandler());