AYEONG.DEV
모든 글 보기

Debug

Android와 iOS의 서로 다른 SSL 인증서 체인 검증 방식.ZIP (feat. React Native FETCH_ERROR)

SSL: 중간이 없잖아 중간이

·

문제 상황

최근 스프링부트 유지보수를 부탁받아 진행하고 있는 프로젝트에서 특이한 이슈를 만났다. 개발 서버에서는 로그인이 잘 되는데, 운영 서버에서는 간헐적으로 로그인이 안 되는 문제였다. 더 특이한 점은 iOS에서는 잘 되는데 Android에서만 문제가 발생한다는 점…ㅠㅠ

앱 개발자 분이 보내주신 오류 메시지

bash
{ "status": "FETCH_ERROR", "error": "TypeError: Network request failed" }

처음에는 당연히 클라이언트 쪽 문제일 거라고 생각했다. 하지만 앱 개발자분이 "개발 서버와 운영 서버는 엔드포인트만 다르고 호출 방식은 동일하다"고 하셨다.

🔍 원인 분석

백엔드 코드를 살펴보니 커스텀 에러 코드를 사용하고 있기 때문에

  • MsAP1xx: Business Error
  • MsAP4xx: Authentication Error
  • MsAP5xx: Server Error
  • FETCH_ERROR는 RN도 스프링부트도 정의하지 않은 에러 코드였다. 이 부분에서 힌트를 얻음!!

    💡 SSL 인증서 체인 확인

    운영 서버의 SSL 인증서를 확인해보니:

    bash
    verify error:num=20:unable to get local issuer certificate
    verify error:num=21:unable to verify the first certificate

    중간 인증서가 누락되어 있었다.

    반면 개발 서버는:

    bash
    depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
    depth=1 C = US, O = Let's Encrypt, CN = R10
    depth=0 CN = dev.e-paps.kr

    전체 인증서 체인이 정상적으로 구성되어 있었다.

    🤔 왜 iOS에서는 됐을까?

    출처: 나

    여기서 재미있는 부분을 발견했다. iOS와 Android의 SSL 인증서 체인 검증 방식이 달랐던 것이었다.:

  • iOS: 비교적 유연한 SSL 체인 검증
  • Android: 매우 엄격한 SSL 체인 검증 (중간 인증서 필수)
  • 🛠 해결 방법

    Sectigo 중간 인증서를 추가하여 전체 인증서 체인을 완성했다.:

  • 도메인 인증서와 중간 인증서를 하나의 파일로 결합중간 인증서 생성
  • bash
    sudo bash -c 'cat > intermediate.crt << "EOF"
    -----BEGIN CERTIFICATE-----
    MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB
    iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
    oUmGv38
    sbZXQm2V0TP2ORQGgkE49Y9Y3IBbpNV9lXj9p5v//cWoaasm56ekBYdbqbe4oyAL
    l6lFhd2zi+WJN44pDfwGF/Y4QA5C5BIG+3vzxhFoYt/jmPQT2BVPi7Fp2RBgvGQq
    6jG35LWjOhSbJuMLe/0CjraZwTiXWTb2qHSihrZe68Zk6s+go/lunrotEbaGmAhY
    LcmsJWTyXnW0OMGuf1pGg+pRyrbxmRE1a6Vqe8YAsOf4vmSyrcjC8azjUeqkk+B5
    yOGBQMkKW+ESPMFgKuOXwIlCypTPRpgSabuY0MLTDXJLR27lk8QyKGOHQ+SwMj4K
    00u/I5sUKUErmgQfky3xxzlIPK1aEn8=
    -----END CERTIFICATE-----
    EOF'
    bash
    # 병합
    sudo bash -c 'cat e-ensemble_kr.crt intermediate.crt > fullchain.crt'

    확인했을 때

    아래처럼 ----BEGIN CERTIFICATE ----- 가 두 번 나와야 정상.

    bash
    # 확인
    sudo cat fullchain.crt | grep "BEGIN CERTIFICATE"
    -----BEGIN CERTIFICATE-----
    -----BEGIN CERTIFICATE-----

    그리고 본인의 Nginx 설정 파일에

    /etc/nginx/sites-available << 이런 곳에

    요 설정을 추가해주면 된다.

    bash
    ssl_certificate /etc/nginx/e-ensemble.kr-ssl/fullchain.crt;

    Nginx 파일 수정했으니 -t 해주고 restart 해주면~

    🎉 결과

  • Android에서도 정상적으로 로그인 동작
  • SSL 체인 검증 오류 해결
  • FETCH_ERROR 해소
  • 📝 배운 점

  • FETCH_ERROR가 발생하면 SSL 인증서 체인도 의심해봐야 함
  • Android와 iOS의 보안 정책 차이를 이해하는 것이 중요
  • 개발/운영 서버의 설정 차이를 꼼꼼히 비교해봐야 함
  • 이런 경험을 통해 플랫폼별 특성과 보안 정책의 중요성을 다시 한번 실감했다.....

    특히 SSL 인증서 체인이 제대로 구성되어 있지 않으면 Android에서 문제가 발생할 수 있다는 점을 배웠다.

    조회 0

    댓글

    익명 캐릭터로 가볍게 이야기를 남겨 주세요.

    0/1000