Development Logs/Spring Ecosystem

[Spring GW] Netty HttpClient SSL/TLS Custom 설정하기

유뱅유뱅뱅 2024. 11. 17. 11:49

2024.11.17 - [Development Logs] - [Spring GW] Netty HttpClient TLS 버전 추가 설정

 

[Spring GW] Netty HttpClient TLS 버전 추가 설정

더보기Java17 버전을 이용해, Spring Cloud GW로 내재화 개발을 진행하다가, Provider서버 중 TLSv1 Protocol 만 연결 가능한 케이스가 있어 문제가 발생하였고, 이를 해결하기위해 쓴 글입니다. JVM의 HTTPS 설

yubh1017.tistory.com

위의 글과 연결된 글입니다.

더보기

Spring Cloud GW로 내재화 개발을 진행하다가, The server selected protocol version TLS10 is not accepted by client preferences [TLS13, TLS12] 라는 에러를 Provider 서버에서 받아, Spring Cloud GW에서 기본적으로 TLS1.2, TLS1.3만 제공한다는 것을 알게되었고 모든 Provider 서버를 지원해줘야하는 요구사항이 있어, Netty HttpClient의 https 통신시 필요한 Protocol들을 여는 설정을 Custom하게 되었고 그에 대한 코드 설명입니다.


1. Java System Property 적용 및 JVM Option 적용

  • Java17을 사용하고 있는데, TLSv1, TLSv1.1은 기본적으로 비활성화 설정이 되어있어서 수동으로 활성화가 필요했다.
  • System.setProperty("https.protocols", "TLSv1"); 설정
  • -Djdk.tls.client.protocols=TLSv1,TLSv1.1,TLSv1.2
  • -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2,TLSv1.3

→ Netty HttpClient에 적용 안됨

📍 Netty Http Client에 Java System Property 적용 및 JVM Option 사용이 안되는 이유

 

[Spring GW] Netty Http Client에 Java System Property 적용 및 JVM Option 사용이 안되는 이유

요약 설명System.setProperty("https.protocols", "TLSv1"); 설정이 Netty의 HttpClient에 영향을 미치지 않는 이유는, Netty의 HttpClient는 JVM의 기본 HTTPS 설정을 사용하지 않고, 자체적으로 SSL/TLS 연결을 구성하기 때

yubh1017.tistory.com

 

2. Netty HttpClient SSL Custom 설정

1) application.yml의 httpClient 설정 부분

spring:
  cloud:
    gateway:
      httpclient:
        pool:
          max-idle-time: 300000
          max-life-time: 60000
        ssl:
          use-insecure-trust-manager: true
          support-protocols: # custom으로 추가된 부분
            - SSLv2Hello
            - SSLv3
            - TLSv1
            - TLSv1.1
            - TLSv1.2
            - TLSv1.3
        max-header-size: 128000
  • 기존에는 support-protocols 부분을 제외하고는 yml 파일의 속성 세팅하는걸 이용하여, Spring Cloud의 httClient인 Netty를 설정했었습니다.
  • 하지만, Netty의 기본 설정으로 되어있었던 SSL Protocol은 TLSv1.2, TLSv1.3 이였고 yml 파일의 속성 세팅을 지원하지 않았습니다.
  • 그래서 ssl부분의 Protocol을 문제가 있었던 TLSv1 부터 대부분 지원하도록 하기 위해 custom할 속성으로 ssl하위에 support-protocols를 추가하였습니다.
  • ssl 하위 값들은 코드로 구현하여 따로 명시 안해줘도 되나, 한 눈에 속성을 알아 볼 수 있도록 명시해놓았습니다.

 

2) Netty httpClient의 SSL 부분만 설정한 코드

@Component
@Getter
@Setter
@ConfigurationProperties(prefix = "spring.cloud.gateway.httpclient.ssl")
public class NettyHttpClientSslConfig {

    private Boolean useInsecureTrustManager;
    private List<String> supportProtocols = new ArrayList<>();

    @Bean
    public HttpClientCustomizer nettyHttpClientSslCustomizer() {
        return httpClient -> {
            try {
                SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();
                sslContextBuilder.protocols(supportProtocols);
                if (useInsecureTrustManager) {
                    sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
                }
                SslContext sslContext = sslContextBuilder.build();

                return httpClient.secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));

            } catch (SSLException e) {
                throw new RuntimeException("Failed to create SSL Context for TLS\n", e);
            }
        };
    }
}
  • spring.cloud.gateway.httpclient 하위의 ssl 부분의 config만 custom하는 코드이며, application.yml으로 설정해준 use-insecure-trust-manager: true 코드로 구현해줘야합니다.
    • 이외 ssl 하위의 수정할 부분이 있다면 코드에 추가 구현해줘야합니다.

 

📍 주의할 점

  • Netty Http Client에서 custom하게 수정할 부분이 application.yml을 이용하여 적용해준 것과 같은 범위에 있다면 같이 반영을 해줘야합니다.
    • 예를 들어 yml파일에 spring.cloud.gateway.httpclient.ssl하위가 아닌 custom한 속성에 값을 정의하여 그 값을 sslContextBuilder.protocols 수정할때 사용했는데, sslContextBuilder가 spring.cloud.gateway.httpclient.ssl의 하위를 건드리게 되므로, 기존의 application.yml 속성에 있던 use-insecure-trust-manager: true 속성 값을 무시하게 되어 아래와 같은 에러가 발생하였습니다
PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed