언어 : java
안녕하세요. 얼마전, WAS서버에서 프록시를 태워, 타사의 API서버로 연결하는데 있어 많은 어려움을 겪었었는데요, 딱 맞는 해답을 찾을 수 없어서 많은 고생을 했던 기억이 납니다.(불과 몇일전) 그 과정에서 제가 알게된 내용에 대해 말씀을 드리려고 합니다.
먼저 HTTPS의 기초, 프록시란 무엇인지에 대해 설명을 드리고, 문제 상황과 해결방법에 대해 말씀드리겠습니다.
HTTPS와 HTTP는 무엇이 다를까요?
HTTP는 HyperText Transfer Protocol의 약어입니다. HTML문서를 주고받는 통신 방식이라는 의미입니다. HTTPS는 Secure가 붙은것으로, 보안이 적용된 통신방식이라고 할 수 있겠네요. 보안을 유지하기 위해서 HTTPS는 추가적인 설정이 필요합니다. 가장 먼저 알아야 할 것은 SSL인증입니다.
SSL인증
인터넷 통신을 위한 HTTP와 HTTPS는 TCP연결을 기반으로 연결이 됩니다. TCP 연결은 handShake라는 과정을 통해서 연결을 수립하고 종료하는 과정을 거칩니다.(1번째 링크 참고) HTTPS는 handShake과정에서 SSL인증서를 검증합니다.(2번째 링크 참고) 이때문에 WAS서버(SSL인증서가 없는 서버)에서 HTTPS사이트에 요청을 보내기 위해서는 SSL인증을 거치지 않도록 설정하는 것이 필요합니다.(3번째 링크 참고) TrustManager를 사용하여 SSL인증서를 무시하도록 설정해야합니다. 아래의 소스 코드를 확인해주세요.
//SSL인증확인과정 무시
SSLContext sc;
try {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts , new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
throw new Exception("HTTPS 통신에 실패하였습니다.", e);
}
//호스트 검증 없음
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
위의 소스에서 뜬금없이 HostnameVerifier가 등장하는데요, 이를 통해서 호스트 이름을 확인하는 과정도 무시하도록 설정합니다. HostnameVerifier를 설정하지 않는경우도 있었기 때문에 자세히 설명하지 않겠습니다.
링크1) https://jee-goo.tistory.com/entry/Web-HTTP%EB%9E%80
링크2) https://aws-hyoh.tistory.com/39
링크3) https://ram2ram2.tistory.com/16
링크4) https://blog.cpming.top/p/httpurlconnection-post-raw
HTTPS연결시 주의사항
- 도메인을 사용하자
HTTPS통신을 위한 준비는 마쳤습니다. 그럼 추가적으로 알아야 할 사항을 말씀드리겠습니다. HTTPS통신을 위해서는 필수적으로 도메인을 사용해야합니다. SSL인증서를 발급 받을 때에는 IP주소가 아닌, 도메인으로 인증받기 때문입니다.
바로 이점 때문에 프록시 통신에서 문제가 발생하였습니다. 당시의 상황와 해결방법에 대해 이야기 해보겠습니다.
프록시에서의 발생한 문제
HTTPS 연결 상황
- 개발중인 로컬서버(노트북) 에서 직접 API호출하면 정상 응답
- 단말에서 ajax요청 시 CORS에러 발생
- 개발서버에 있는 어플리케이션에서 프록시를 거쳐 연결시 handShake 문제발생(SSL인증 우회하도록함)
- 개발서버에서 curl -k 옵션으로 프록시를 거쳐 연결시 정상 응답
프록시 연결 상황
프록시 서버에서는 haproxy를 사용하여, 프록시의 특정 포트로 요청이 오면, API 도메인 주소로 연결되어 있는 상황이었습니다.
해결
위와 같은 설정을 했을 때 발생하는 문제점은 HTTPS요청을 보내는 클라이언트가 프록시의 IP주소로 보낸다는 것이였습니다. SSL인증을 거치기 위한 아주 기본적인 조건이 도메인을 사용해야 한다는 것인데, 이 점이 지켜지지 않았기 때문에 SSLHandshakeException이 발생했던 것입니다.
이는 WAS서버의 host파일에 API서버의 도메인으로 요청보내면, 프록시 서버의 아이피로 요청이 전달되도록 설정해주어 해결 할 수 있었습니다.
프록시를 거쳐 통신하시는 분들에게 도움이 되었으면 좋겠습니다.
감사합니다^^
'개발관련 > JAVA' 카테고리의 다른 글
JAVA) 메모리 누수 OutOfMemory: MetaSpace (0) | 2023.09.05 |
---|---|
JAVA) Apache Poi 엑셀다운로드 - 페이지 레이아웃 설정하기 (0) | 2023.08.03 |
JAVA) apache poi - SXSSF NullPointer Exception 오류 해결방법 (0) | 2021.08.02 |
JAVA) apache poi, 엑셀 파일 생성 및 다운로드 하기 (0) | 2021.06.26 |
JAVA) 배포란 무엇이고 어떻게 할까? jar? war? (0) | 2020.07.02 |
댓글