SSLHandshakeException오류에 대해 질문드립니다.

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

SSLHandshakeException오류에 대해 질문드립니다.

sieun
This post was updated on .
안녕하세요

ngrinder에서 https로 POST요청을 하기 위해 스크립트를 작성하였는데, 다음과 같은 SSLHandshakeException 오류가 발생하였습니다.

다른 포스트의 답변으로 달아주신것처럼
java.lang.System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
를 스크립트에 포함하였는데 똑같은 오류가 발생합니다.

혹시 다른 방법이 있을까요?


<오류 내용>
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at HTTPClient.HTTPConnection.sendRequest(HTTPConnection.java:3147)
        at HTTPClient.HTTPConnection.handleRequest(HTTPConnection.java:2883)
        at HTTPClient.HTTPConnection.setupRequest(HTTPConnection.java:2675)
        at HTTPClient.HTTPConnection.Post(HTTPConnection.java:1177)
        at net.grinder.plugin.http.HTTPRequest$8.doRequest(HTTPRequest.java:923)
        at net.grinder.plugin.http.HTTPRequest$AbstractRequest.getHTTPResponse(HTTPRequest.java:1276)
        at net.grinder.plugin.http.HTTPRequest.POST(HTTPRequest.java:918)
        at net.grinder.plugin.http.HTTPRequest.POST(HTTPRequest.java:896)
        at net.grinder.plugin.http.HTTPRequest$POST$0.call(Unknown Source)
        at TestRunner.test(mongo-log-api_trial.groovy:73)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at net.grinder.scriptengine.groovy.junit.GrinderRunner.run(GrinderRunner.java:172)
        at net.grinder.scriptengine.groovy.GroovyScriptEngine$GroovyWorkerRunnable.run(GroovyScriptEngine.java:147)
        at net.grinder.engine.process.GrinderThread.run(GrinderThread.java:118)
Reply | Threaded
Open this post in threaded view
|

Re: SSLHandshakeException오류에 대해 질문드립니다.

junoyoon
Administrator
현재 어떤 버전을 사용하시고 계신지요?
아래 에러 메시지를 보니, 구 HttpClient 를 사용중이신것 같습니다.
최신 ngrinder 로 스크립트를 생성하시면 신 HttpClient 를 사용하실 수 있으므로,
테스트 해보시기 바랍니다.
Reply | Threaded
Open this post in threaded view
|

Re: SSLHandshakeException오류에 대해 질문드립니다.

sieun
This post was updated on .
빠른 답변 감사합니다😃

확인해보니 ngrinder-3.5.3를 설치하였었고

최신 버전인 3.5.6으로 재설치해보았는데, 여전히 같은 오류가 나옵니다.



(위가 ngrinder controller 의 버전이고 아래가 agent의 버전입니다.)


혹시 아래 스크립트에서 잘못 작성된 부분이 있는지 확인 가능할까요..? 단순히 request body에 넣은 정보를 POST하는 테스트입니다.

감사합니다.

------스크립트-------
@RunWith(GrinderRunner)
class TestRunner {

        public static GTest test
        public static HTTPRequest request
        public static Map<String, String> headers = [:]
        public static Map<String, Object> params = [:]
        public static List<Cookie> cookies = []
        public static String body = "{\"transaction_id\":\"5db44b4bfa0219ddd138fc2eb21327ed\",\"timestamp\":\"2022-10-05 17:50:26\",\"client_id\":\"ngrinder_test\"}"

        @BeforeProcess
        public static void beforeProcess() {
                java.lang.System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
                HTTPRequestControl.setConnectionTimeout(300000)
                test = new GTest(1, "https post test")
                request = new HTTPRequest()

                // Set header data
                headers.put("Content-Type", "application/x-www-form-urlencoded")
                //headers.put("Content-Type", "application/json")
                grinder.logger.info("before process.")
        }

        @BeforeThread
        public void beforeThread() {
                test.record(this, "test")
                grinder.statistics.delayReports = true
                grinder.logger.info("before thread.")
        }

        @Before
        public void before() {
                request.setHeaders(headers)
                CookieManager.addCookies(cookies)
                grinder.logger.info("before. init headers and cookies")
        }

        @Test
        public void test() {
                HTTPResponse response = request.POST("[공개 불가능한 uri]", body.getBytes())

                if (response.statusCode == 301 || response.statusCode == 302) {
                        grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", response.statusCode)
                } else {
                        assertThat(response.statusCode, is(200))
                }
        }
}

-------오류 내용--------

2022-10-07 18:17:20,669 ERROR Received fatal alert: handshake_failure
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at HTTPClient.HTTPConnection.sendRequest(HTTPConnection.java:3147)
        at HTTPClient.HTTPConnection.handleRequest(HTTPConnection.java:2883)
        at HTTPClient.HTTPConnection.setupRequest(HTTPConnection.java:2675)
        at HTTPClient.HTTPConnection.Post(HTTPConnection.java:1177)
        at net.grinder.plugin.http.HTTPRequest$8.doRequest(HTTPRequest.java:923)
        at net.grinder.plugin.http.HTTPRequest$AbstractRequest.getHTTPResponse(HTTPRequest.java:1276)
        at net.grinder.plugin.http.HTTPRequest.POST(HTTPRequest.java:918)
        at net.grinder.plugin.http.HTTPRequest.POST(HTTPRequest.java:896)
        at net.grinder.plugin.http.HTTPRequest$POST$0.call(Unknown Source)
        at TestRunner.test(mongo-log.groovy:75)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at net.grinder.scriptengine.groovy.junit.GrinderRunner.run(GrinderRunner.java:164)
        at net.grinder.scriptengine.groovy.GroovyScriptEngine$GroovyWorkerRunnable.run(GroovyScriptEngine.java:147)
        at net.grinder.engine.process.GrinderThread.run(GrinderThread.java:118)
Reply | Threaded
Open this post in threaded view
|

Re: SSLHandshakeException오류에 대해 질문드립니다.

sieun
죄송합니다
오류내용을 잘못 첨부했습니다.

버전 업그레이드 이후의 오류는 아래와 같습니다!
그리고
2022-10-11 11:43:41,727 INFO  Running "postLog.groovy" using GroovyScriptEngine running with groovy version: 3.0.5
을 보니 Groovy버전이 낮은걸로 실행되고 있는 것 같아 수정해보고있습니다.

<오류 내용>
2022-10-11 11:43:42,083 ERROR java.util.concurrent.ExecutionException: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at org.apache.hc.core5.reactor.ssl.SSLIOSession.doUnwrap(SSLIOSession.java:278)
        at org.apache.hc.core5.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:338)
        at org.apache.hc.core5.reactor.ssl.SSLIOSession.access$300(SSLIOSession.java:71)
        at org.apache.hc.core5.reactor.ssl.SSLIOSession$1.inputReady(SSLIOSession.java:175)
        at org.apache.hc.core5.reactor.InternalDataChannel.onIOEvent(InternalDataChannel.java:124)
        at org.apache.hc.core5.reactor.InternalChannel.handleIOEvent(InternalChannel.java:51)
        at org.apache.hc.core5.reactor.SingleCoreIOReactor.processEvents(SingleCoreIOReactor.java:179)
        at org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:128)
        at org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:85)
        at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44)
Reply | Threaded
Open this post in threaded view
|

Re: SSLHandshakeException오류에 대해 질문드립니다.

junoyoon
Administrator
grooovy 와는 상관 없구요.
여러 http client 로도 동일한 에러가 발생하는 것을 보아하니..
해당 타겟의 https 인증서가 오류가 있는 모양입니다.
ngrinder 의 문제로 보이지 않습니다.
Reply | Threaded
Open this post in threaded view
|

Re: SSLHandshakeException오류에 대해 질문드립니다.

sieun
답변 감사합니다!

인증서에는 문제가 없어보여, 원인을 계속 찾아보고 있습니다 ㅜㅜ

현재 서버에서는 TLS1.2 이하를 지원하지 않는데, ngrinder의 HTTPClient 에서 내보내는 request packet 을 까보니 TLSv1 로 요청을 먼저 보내고 있는 것 같습니다.



java.lang.System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2"); 를 추가도 해보고
여기에서 TLS1.2만 남기고 실행해보았는데도 똑같았습니다.

혹시 테스트 HTTPClient의 TLS 버전을 1.2 로 고정하여 요청하는 방법은 없을까요?

감사합니다😃
Reply | Threaded
Open this post in threaded view
|

Re: SSLHandshakeException오류에 대해 질문드립니다.

junoyoon
Administrator
기본 구현체로는 딱히 없어 보이구요. 직접 http client 를 선언하셔서 호출하시면 될것 같습니다. httpclient4 같은 것을 import 하셔서..

그런데.. 이 이슈를 github 쪽에 올려주시면, 저희가 해당 이슈를 옵션으로 뺄 수 있도록 하겠습니다. github 쪽에 이슈 생성 부탁드립니다.
Reply | Threaded
Open this post in threaded view
|

Re: SSLHandshakeException오류에 대해 질문드립니다.

sieun
빠른 답변 감사드립니다 😊

그렇군요~ 안내해주신 방향으로 수정해보겠습니다.

github에 이슈 생성하였습니다.

감사합니다.
Reply | Threaded
Open this post in threaded view
|

Re: SSLHandshakeException오류에 대해 질문드립니다.

gseok
https  형태의 테스트시, 테스트의 최종 타겟 서버가, http2(h2) 을 사용하는 경우 stream 형태로 connect되서 구동되는데, ngrinder 테스트 코드상 HttpRequestControl 부분의 기본 예제가 30000 이여서 connect을 close하지 않아서, 해당 에러 (SSLHandshakeException)이 발생하는 케이스가 존재합니다.!!


즉, 위 다른 내용들과 같이 TLSv1 TLSv1.1 TLSv1.2 와 같은 버전 문제일수도 있고, ngrinder 의 테스트 코드 문제일 수도 있습니다.


저의 경우 아래와 같이 테스트코드를 수정하고 에러없이 테스트 되었습니다.

 <code>
    @BeforeProcess
    public static void beforeProcess() {
        // 아래 부분 수정... 본인 (테스트 타겟 서버)의 평균 응답(ms) 가지고 적절히 조정...
        // 일단 30000 쓰면 무조건 발생하던  SSLHandshakeException 에러가, 아래와 같이 수정 이후 정상 테스트됨..
        // 500은 저의 테스트 케이스이고, 각자 자기 테스트 케이스에 따라서 connect out 되도록 조절하면 될듯요...
        HTTPRequestControl.setConnectionTimeout(500); // 여기 부분이 30000 인가로 되어 있는데, 500 수정
        test = new GTest(1, targetHost);
        request = new HTTPRequest();
        grinder.logger.info("before process.");
    }
</code>
Reply | Threaded
Open this post in threaded view
|

Re: SSLHandshakeException오류에 대해 질문드립니다.

gseok
자문자답 2...

이것저것 하다가 또 해당 케이스에 걸렸는데요... ngrinder 에서 제공하는 HTTPRequest 을 어떤걸 쓰느냐에 따라서 결과가 다르네요

- 신버전: "import org.ngrinder.http.HTTPRequest"
  - SSLHandshakeException 지속 발생.!!!!
  - 에러 나는걸 보니 org.ngrinder.http.HTTPRequest 내부에서 org.apache.hc.core5.http2 사용하는듯.
  - 내부 구현체를 보지는 않았는데. request이후 connection을 close하는게 이상한듯??

- 구버전: "import net.grinder.plugin.http.HTTPRequest"
  - SSLHandshakeException 발생 없이 https 주소관련 테스트 정상동작!!!!@
  - 내부 테스트 로직은 동일할때, "구버전" 사용기 오히려 아주 정상적으로 구동.....

---

- 해당 상태에 걸리면 일단 구버전 형태로 테스트 작성해보세요.....

Reply | Threaded
Open this post in threaded view
|

Re: SSLHandshakeException오류에 대해 질문드립니다.

imbyungjun
Administrator
"javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure" 오류는 인증서 혹은 암호화 알고리즘 문제로 인해 발생합니다.
Github 이슈에 올린 답변을 참고하여 문제를 해결하시기 바랍니다.

최신 버전의 nGrinder에는 신규 HTTP 클라이언트와 구버전 HTTP 클라이언트가 존재합니다.

신규 클라이언트
  - 스크립트 만들기 -> Groovy 선택으로 생성 가능
  - Apache HttpComponents5 기반
  - SSL 연결 수립을 JDK에서 제공되는 SSLEngine에 위임

구버전 클라이언트
  - 스크립트 만들기 -> Groovy (Legacy) 선택으로 생성 가능
  - The Grinder에서 사용하는 자체 개발 HTTP 클라이언트
  - SSL 연결 또한 자체 개발한 코드로 수립

신규 HTTP 클라이언트는 SSL 연결 수립을 JDK에서 제공하는 SSLEngine에 위임합니다.
SSLEngine은 서버측에서 SSL 연결 수립에 사용하려는 알고리즘과 클라이언트측에서 SSL 연결 수립에 사용하려는 알고리즘의 버전 차이가 있을 경우 HTTPS 연결을 실패 처리합니다.
즉, 서버와 클라이언트의 JDK 버전에 따라서 handshake_failure 오류가 발생할 수 있습니다.
또한, 서버의 인증서가 클라이언트의 trust store에 등록되어있지 않다면 동일하게 handshake_failure 오류가 발생할 수 있습니다.

구버전 HTTP 클라이언트는 자체 개발된 코드로 HTTPS 연결을 무조건 신뢰하도록 설정합니다. 그렇기 때문에 동일한 환경에서도 위와 같은 오류가 발생하지 않습니다.

근본적인 해결이 번거롭고, 구버전 HTTP 클라이언트로 부하 테스트를 수행해도 괜찮다면, 구버전 HTTP 클라이언트로 테스트 스크립트를 작성하여 handshake_failure 오류를 우회할 수 있습니다.
일반적으로 상당히 많은 부하를 만들어내야하거나 HTTP PATCH method를 사용해야하는 경우가 아니라면 구버전 HTTP 클라이언트로 테스트를 진행해도 괜찮습니다.
Reply | Threaded
Open this post in threaded view
|

Re: SSLHandshakeException오류에 대해 질문드립니다.

gseok
SSL 연결 수립에 사용하려는 알고리즘의 버전 차이 이라는 말씀이

> TLSv1 TLSv1.1 TLSv1.2

위와같은 버전 을 말씀하시는거 같은데.. 만약 해당 버전 문제라면, test상 모든 req에서 SSLHandshakeException가 발생할꺼 같은데요. 저의 경우 절반 이상은 성공하고, 절반 정도는 실패하는 현상이 있습니다. 이런경우에는 어떤 부분을 의심해야할까요?