
몇 시간 전, 아무 문제 없던 자바 애플리케이션에서 메일 서버와의 통신이 갑자기 실패하기 시작했습니다.
로그를 보니 SSL 관련 예외가 발생하고 있었고, 이전까지는 없던 이슈였기 때문에 원인을 파악하는 데 시간이 걸렸습니다.
운영 환경에서 이런 SSL 이슈는 장애로 이어졌고 후에 인증서와 관련된 오류 처리를 빠르게 하기 위해 정리해봅니다.
해당 애플리케이션은 메일 서버와 HTTPS 통신을 하고 있었습니다.
그런데 몇 시간 전부터 메일 발송 및 상태 확인 요청이 전부 실패하기 시작했고 로그에는 다음과 같은 에러 메시지가 찍히고 있었습니다.
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
자바 환경에서 볼 수 있는 SSL 에러로, 서버가 제공한 인증서를 신뢰할 수 없을 때 발생하는 예외입니다.
처음엔 인증서 만료를 의심했지만, 메일 서버 인증서는 여전히 유효한 상태였습니다.
알고 보니 메일 서버 앞단에 새로운 보안 솔루션 장비(SSL 프록시) 가 추가되었고, 이 장비가 메일 서버의 앞단을 수행하고 있었습니다.
문제는 이 솔루션이 사용하는 인증서가 공인 루트 CA가 아닌, 해당 솔루션 자체에서 발급한 인증서였다는 점입니다.
JVM은 기본적으로 $JAVA_HOME/lib/security/cacerts 내 truststore에 등록된 인증서만을 신뢰하기 때문에 자바 애플리케이션은 이 인증서를 신뢰하지 않았고, SSL 핸드셰이크에 실패했던 것입니다.
우선 문제가 된 도메인에서 사용 중인 인증서를 직접 추출해야 했습니다.
다음 명령어로 서버가 제공하는 인증서를 저장할 수 있습니다:
echo | openssl s_client -connect mail.server.domain:443 | openssl x509 -outform PEM > ssl-mail.crt
mail.server.domain:443 < 실제 서버 도메인과 포트를 입력해야 합니다.ssl-mail.crt 파일이 생성되며, 바로 이 인증서를 등록해야 합니다.이제 인증서를 자바의 truststore(cacerts)에 등록합니다.
keytool을 사용해 다음과 같이 등록할 수 있습니다:
sudo keytool -import -trustcacerts \
-keystore $JAVA_HOME/lib/security/cacerts \
-storepass changeit \
-alias ssl-mail.crt \
-file ssl-mail.crt
changeit입니다.-alias는 등록된 인증서를 식별하기 위한 이름으로, 중복되지 않게 설정합니다.yes 입력.등록이 정상적으로 되었는지 확인하려면 다음 명령어를 사용합니다:
sudo keytool -list \
-keystore $JAVA_HOME/lib/security/cacerts \
-storepass changeit \
-alias ssl-mail.crt
또는 전체 목록을 보고 싶다면:
sudo keytool -list \
-keystore $JAVA_HOME/lib/security/cacerts \
-storepass changeit | grep ssl-mail
JVM은 truststore를 애플리케이션 시작 시점에 로딩하기 때문에,
등록 후에는 반드시 애플리케이션을 재시작해야 변경 사항이 적용됩니다.
# 예: systemd 서비스인 경우
sudo systemctl restart my-java-service
# 단순 jar 파일이면
Ctrl + C 로 종료 후 다시 실행
재시작 후 SSL 통신이 정상적으로 이루어지는 것을 확인했습니다.
이전까지 실패하던 메일 발송, 수신 API가 모두 정상 동작했고
더 이상 SSLHandshakeException이 발생하지 않았습니다.
일정 기간 후 더 이상 해당 인증서가 필요 없어졌거나, 테스트용으로 임시 등록한 경우 삭제가 필요할 수 있습니다.
sudo keytool -delete \
-alias ssl-mail.crt \
-keystore $JAVA_HOME/lib/security/cacerts \
-storepass changeit
삭제 후에도 역시 JVM이나 애플리케이션 재시작이 필요합니다.
이슈를 겪으면서 다음과 같은 점들을 다시 한 번 확인하게 되었습니다:
PKIX path building failed → 인증서 체인 문제를 의미합니다.