SSL 문제 해결

Tier: Free, Premium, Ultimate Offering: Self-managed

이 페이지는 GitLab 작업 중에 발생할 수 있는 일반적인 SSL 관련 오류 및 상황의 목록을 포함하고 있습니다. 이 페이지는 주요 SSL 문서의 추가 자료 역할을 합니다:

유용한 OpenSSL 디버깅 명령

가끔 SSL 인증서 체인을 직접 소스에서 확인하여 더 나은 그림을 얻는 것이 유용합니다. 이 명령은 진단 및 디버깅을 위한 표준 OpenSSL 도구 라이브러리의 일부입니다.

note
GitLab은 GitLab 라이브러리에 연결된 맞춤형 컴파일된 OpenSSL 버전을 포함합니다. 다음 명령을 이 OpenSSL 버전을 사용하여 실행하는 것이 중요합니다.
  • HTTPS를 통해 호스트에 테스트 연결을 수행합니다. HOSTNAME을 GitLab URL로 바꾸고(HTTPS 제외), port를 HTTPS 연결을 제공하는 포트(일반적으로 443)로 바꿉니다:

    echo | /opt/gitlab/embedded/bin/openssl s_client -connect HOSTNAME:port  
    

    echo 명령은 서버에 null 요청을 보내 연결을 닫게 하여 추가 입력을 기다리지 않게 합니다. HOSTNAME:port를 원격 호스트의 도메인 및 포트 번호로 바꾸어 이 명령을 원격 호스트를 테스트하는 데 사용할 수 있습니다.

    이 명령의 출력은 인증서 체인, 서버가 제공하는 모든 공개 인증서, 발생한 유효성 검사 또는 연결 오류를 보여줍니다. 이는 SSL 설정에 즉시 문제가 있는지 빠르게 확인하는 데 유용합니다.

  • x509를 사용하여 인증서의 세부정보를 텍스트 형식으로 봅니다. /path/to/certificate.crt를 인증서 경로로 바꾸는 것을 잊지 마세요:

    /opt/gitlab/embedded/bin/openssl x509 -in /path/to/certificate.crt -text -noout  
    

    예를 들어, GitLab은 Let’s Encrypt에서 획득한 인증서를 자동으로 /etc/gitlab/ssl/hostname.crt에 가져와 배치합니다. 이 경로를 사용하여 x509 명령으로 인증서 정보를 빠르게 표시할 수 있습니다(예: 호스트 이름, 발급자, 유효 기간 등).

    인증서에 문제가 있으면, 오류가 발생합니다.

  • 서버에서 인증서를 가져와 디코딩합니다. 이는 서버의 SSL 인증서를 가져오고 텍스트로 디코딩하는 두 명령을 결합합니다:

    echo | /opt/gitlab/embedded/bin/openssl s_client -connect HOSTNAME:port | /opt/gitlab/embedded/bin/openssl x509 -text -noout  
    

일반적인 SSL 오류

  1. SSL certificate problem: unable to get local issuer certificate

    이 오류는 클라이언트가 루트 CA를 가져올 수 없음을 나타냅니다. 이 문제를 해결하려면 연결하려는 서버의 루트 CA를 클라이언트에서 신뢰하거나, 연결하려는 서버에서 전체 체인 인증서를 제시하도록 인증서를 수정해야 합니다.

    note
    클라이언트가 연결할 때 SSL 오류를 방지하기 위해 전체 인증서 체인을 사용하는 것이 좋습니다. 전체 인증서 체인 순서는 서버 인증서가 먼저 오고, 그 뒤에 모든 중간 인증서, 마지막에 루트 CA가 오는 구성이어야 합니다.
  2. unable to verify the first certificate

    이 오류는 서버에서 불완전한 인증서 체인이 제시되고 있음을 나타냅니다. 이 오류를 해결하려면 서버의 인증서를 전체 체인 인증서로 교체해야 합니다. 전체 인증서 체인 순서는 서버 인증서가 먼저 오고, 그 뒤에 모든 중간 인증서, 마지막에 루트 CA가 오는 구성이어야 합니다.

    note
    /opt/gitlab/embedded/bin/openssl 유틸리티 대신 시스템 OpenSSL 유틸리티를 실행할 때 이 오류가 발생하면, 이를 해결하기 위해 OS 수준에서 CA 인증서를 업데이트해야 합니다.
  3. certificate signed by unknown authority

    이 오류는 클라이언트가 인증서 또는 CA를 신뢰하지 않음을 나타냅니다. 이 오류를 해결하려면 서버에 연결하는 클라이언트가 인증서 또는 CA를 신뢰해야 합니다.

  4. SSL certificate problem: self signed certificate in certificate chain

    이 오류는 클라이언트가 인증서 또는 CA를 신뢰하지 않음을 나타냅니다. 이 오류를 해결하려면 서버에 연결하는 클라이언트가 인증서 또는 CA를 신뢰해야 합니다.

  5. x509: certificate relies on legacy Common Name field, use SANs instead

    이 오류는 인증서에 SANs (subjectAltName)가 구성되어야 함을 나타냅니다. 자세한 내용은 이 문제를 참조하세요.

인증서로 인한 재구성 실패

ERROR: Not a certificate: /opt/gitlab/embedded/ssl/certs/FILE. /opt/gitlab/embedded/ssl/certs에서 다른 위치로 이동하고 다시 재구성하십시오.

/opt/gitlab/embedded/ssl/certs를 확인하고 유효한 X.509 인증서가 아닌 README.md 외의 모든 파일을 제거하십시오.

참고: gitlab-ctl reconfigure를 실행하면 커스텀 공개 인증서의 주 체적 해시에서 이름을 따서 심볼릭 링크가 생성되고 /opt/gitlab/embedded/ssl/certs/에 배치됩니다.

/opt/gitlab/embedded/ssl/certs/의 깨진 심볼릭 링크는 자동으로 제거됩니다.

/opt/gitlab/embedded/ssl/certs/에 저장된 cacert.pemREADME.md 외의 파일은 /etc/gitlab/trusted-certs/로 이동됩니다.

사용자 인증서 누락 또는 건너뜀

/opt/gitlab/embedded/ssl/certs/에 심볼릭 링크가 생성되지 않고 gitlab-ctl reconfigure를 실행한 후 “Skipping cert.pem” 메시지가 표시되면 다음 네 가지 문제 중 하나가 있을 수 있습니다:

  1. /etc/gitlab/trusted-certs/의 파일이 심볼릭 링크입니다.
  2. 파일이 유효한 PEM 또는 DER 인코딩 인증서가 아닙니다.
  3. c_rehash가 인증서를 제대로 심볼링하는 데 필요한 Perl이 운영 체제에 설치되지 않았습니다.
  4. 인증서에 문자열 TRUSTED가 포함되어 있습니다.

아래 명령어를 사용하여 인증서의 유효성을 확인하십시오:

/opt/gitlab/embedded/bin/openssl x509 -in /etc/gitlab/trusted-certs/example.pem -text -noout
/opt/gitlab/embedded/bin/openssl x509 -inform DER -in /etc/gitlab/trusted-certs/example.der -text -noout

유효하지 않은 인증서 파일은 다음 출력을 생성합니다:

  • unable to load certificate
    140663131141784:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:701:Expecting: TRUSTED CERTIFICATE
    
  • cannot load certificate
    PEM_read_bio_X509_AUX() failed (SSL: error:0909006C:PEM routines:get_name:no start line:Expecting: TRUSTED CERTIFICATE)
    

이 두 경우 모두, 그리고 인증서가 다음으로 시작하고 끝나지 않으면:

-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----

GitLab과 호환되지 않습니다. 인증서를 서버, 중간, 루트 등 인증서 구성 요소로 분리하고 호환 가능한 PEM 형식으로 변환해야 합니다.

c_rehash가 Perl 인터프리터가 없기 때문에 인증서를 심볼링하지 않는지 테스트하려면:

$ /opt/gitlab/embedded/bin/c_rehash /etc/gitlab/trusted-certs

bash: /opt/gitlab/embedded/bin/c_rehash: /usr/bin/perl: bad interpreter: No such file or directory

이 메시지가 표시되면 배포판의 패키지 관리자에서 Perl을 설치해야 합니다.

인증서 자체를 검사할 때 TRUSTED 문자열을 찾으십시오:

-----BEGIN TRUSTED CERTIFICATE-----
...
-----END TRUSTED CERTIFICATE-----

위와 같은 경우 TRUSTED 문자열을 제거한 후 gitlab-ctl reconfigure를 다시 실행해 보십시오.

사용자 정의 인증서가 감지되지 않음

gitlab-ctl reconfigure를 실행한 후:

  1. /opt/gitlab/embedded/ssl/certs/에 symlink가 생성되지 않음;
  2. /etc/gitlab/trusted-certs/에 사용자 정의 인증서를 배치했음;
  3. 건너뛰거나 symlink된 사용자 정의 인증서 메시지를 보지 못함

이런 문제가 발생할 수 있습니다. 이는 Linux 패키지 설치에서 사용자 정의 인증서가 이미 추가되었다고 판단하는 경우입니다.

해결 방법은 신뢰할 수 있는 인증서 디렉토리 해시를 삭제하는 것입니다:

rm /var/opt/gitlab/trusted-certs-directory-hash

이후 gitlab-ctl reconfigure를 다시 실행하세요. 이제 재구성이 사용자 정의 인증서를 감지하고 symlink해야 합니다.

알 수 없는 인증 기관에서 서명된 Let’s Encrypt 인증서

Let’s Encrypt 통합의 초기 구현은 인증서만 사용하고 전체 인증서 체인은 사용하지 않았습니다.

10.5.4부터 전체 인증서 체인이 사용됩니다. 이미 인증서를 사용 중인 설치의 경우, 갱신 로직이 인증서가 만료될 수 있다고 나타날 때까지 전환되지 않습니다. 더 빨리 전환하려면 다음을 실행하세요:

rm /etc/gitlab/ssl/HOSTNAME*
gitlab-ctl reconfigure

여기서 HOSTNAME은 인증서의 호스트 이름입니다.

재구성 시 Let’s Encrypt 실패

참고: Let’s Debug 진단 도구를 사용하여 도메인을 테스트할 수 있습니다. 이를 통해 Let’s Encrypt 인증서를 발급할 수 없는 이유를 파악할 수 있습니다.

재구성할 때 Let’s Encrypt가 실패할 수 있는 일반적인 시나리오는 다음과 같습니다:

  • 서버가 Let’s Encrypt 검증 서버에 접근할 수 없는 경우 Let’s Encrypt가 실패할 수 있습니다:

    letsencrypt_certificate[gitlab.domain.com] (letsencrypt::http_authorization line 3) had an error: RuntimeError: acme_certificate[staging]  (/opt/gitlab/embedded/cookbooks/cache/cookbooks/letsencrypt/resources/certificate.rb line 20) had an error: RuntimeError: [gitlab.domain.com] Validation failed for domain gitlab.domain.com
    

    Let’s Encrypt로 인해 GitLab을 재구성하는 데 문제가 발생하면 포트 80 및 443이 열려 있고 접근 가능한지 확인하세요.

  • 도메인의 인증 기관 권한(CAA) 레코드가 Let’s Encrypt가 도메인에 대한 인증서를 발급하는 것을 허용하지 않을 수 있습니다. 재구성 출력에서 다음 오류를 찾아보세요:

    letsencrypt_certificate[gitlab.domain.net] (letsencrypt::http_authorization line 5) had an error: RuntimeError: acme_certificate[staging]   (/opt/gitlab/embedded/cookbooks/cache/cookbooks/letsencrypt/resources/certificate.rb line 25) had an error: RuntimeError: ruby_block[create certificate for gitlab.domain.net] (/opt/gitlab/embedded/cookbooks/cache/cookbooks/acme/resources/certificate.rb line 108) had an error: RuntimeError: [gitlab.domain.com] Validation failed, unable to request certificate
    
  • gitlab.example.com와 같은 테스트 도메인을 사용하고 있으며 인증서가 없는 경우 위에 표시된 unable to request certificate 오류가 나타납니다. 이 경우 /etc/gitlab/gitlab.rb에서 letsencrypt['enable'] = false로 설정하여 Let’s Encrypt를 비활성화하세요.

  • Let’s Encrypt는 속도 제한을 시행합니다, 이는 최상위 도메인에 적용됩니다. 클라우드 제공업체의 호스트 이름을 external_url로 사용하는 경우, 예를 들어 *.cloudapp.azure.com, Let’s Encrypt는 azure.com에 대한 제한을 시행하여 인증서 생성이 불완전할 수 있습니다.

    이 경우, Let’s Encrypt 인증서를 수동으로 갱신할 수 있습니다:

    sudo gitlab-ctl renew-le-certs
    

GitLab에서 내부 CA 인증서 사용하기

내부 CA 인증서로 GitLab 인스턴스를 구성한 후, 여러 CLI 도구를 사용하여 액세스할 수 없을 수 있습니다. 다음과 같은 문제가 발생할 수 있습니다:

  • curl 실패:

    curl "https://gitlab.domain.tld"
    curl: (60) SSL certificate problem: unable to get local issuer certificate
    More details here: https://curl.haxx.se/docs/sslcerts.html
    
  • rails console를 사용하여 테스트할 때도 실패합니다:

    uri = URI.parse("https://gitlab.domain.tld")
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.verify_mode = 1
    response = http.request(Net::HTTP::Get.new(uri.request_uri))
    ...
    Traceback (most recent call last):
          1: from (irb):5
    OpenSSL::SSL::SSLError (SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate))
    
  • 이 GitLab 인스턴스에서 미러를 설정할 때 SSL certificate problem: unable to get local issuer certificate 오류가 표시됩니다.

  • openssl은 인증서의 경로를 지정할 때 정상 작동합니다:

    /opt/gitlab/embedded/bin/openssl s_client -CAfile /root/my-cert.crt -connect gitlab.domain.tld:443
    

위에서 설명한 문제가 발생하는 경우, 인증서를 /etc/gitlab/trusted-certs에 추가한 후 sudo gitlab-ctl reconfigure를 실행하세요.

X.509 키 값 불일치 오류

인증서 번들로 인스턴스를 구성한 후, NGINX는 다음과 같은 오류 메시지를 표시할 수 있습니다:

SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch

이 오류 메시지는 제공한 서버 인증서와 키가 일치하지 않음을 의미합니다. 다음 명령을 실행한 후 출력 결과를 비교하여 확인할 수 있습니다:

openssl rsa -noout -modulus -in path/to/your/.key | openssl md5
openssl x509 -noout -modulus -in path/to/your/.crt | openssl md5

다음은 일치하는 키와 인증서의 md5 출력 예시입니다. 일치하는 md5 해시 값을 확인하세요:

$ openssl rsa -noout -modulus -in private.key | openssl md5
4f49b61b25225abeb7542b29ae20e98c
$ openssl x509 -noout -modulus -in public.crt | openssl md5
4f49b61b25225abeb7542b29ae20e98c

다음은 비일치하는 키와 인증서의 반대 출력으로, 서로 다른 md5 해시 값을 보여줍니다:

$ openssl rsa -noout -modulus -in private.key | openssl md5
d418865077299af27707b1d1fa83cd99
$ openssl x509 -noout -modulus -in public.crt | openssl md5
4f49b61b25225abeb7542b29ae20e98c

위의 예시처럼 두 출력이 다르면, 인증서와 키 간에 불일치가 있는 것입니다. SSL 인증서 제공자에게 추가 지원을 요청하세요.

GitLab 인스턴스와 내부 CA 인증서 또는 자체 서명된 인증서로 GitLab Runner 사용하기

다음과 같은 오류를 겪고 있는 것 외에도,
GitLab과 함께 내부 CA 인증서 사용하기에서 언급된 오류를 겪고 있다면,
CI 파이프라인이 Pending 상태에 갇힐 수 있습니다.
러너 로그에서 다음 오류 메시지를 볼 수 있습니다:

Dec  6 02:43:17 runner-host01 gitlab-runner[15131]: #033[0;33mWARNING: Checking for jobs... failed
#033[0;m  #033[0;33mrunner#033[0;m=Bfkz1fyb #033[0;33mstatus#033[0;m=couldn't execute POST against
https://gitlab.domain.tld/api/v4/jobs/request: Post https://gitlab.domain.tld/api/v4/jobs/request:
x509: certificate signed by unknown authority

자체 서명된 인증서 또는 커스텀 인증 기관을 위한 GitLab Runner에서 자세한 내용을 참조하세요.

자체 서명된 SSL 인증서를 사용하는 원격 GitLab 저장소 미러링

자체 서명된 인증서를 사용하는 원격 GitLab 인스턴스에서
저장소를 미러링하기 위해
로컬 GitLab 인스턴스를 구성할 때, 사용자 인터페이스에서
SSL certificate problem: self signed certificate 오류 메시지를 볼 수 있습니다.

문제의 원인은 다음을 확인함으로써 확인할 수 있습니다:

  • curl이 실패하는 경우:

    $ curl "https://gitlab.domain.tld"
    curl: (60) SSL certificate problem: self signed certificate
    자세한 내용은 여기에서: https://curl.haxx.se/docs/sslcerts.html
    
  • Rails 콘솔을 사용하여 테스트하는 것도 실패하는 경우:

    uri = URI.parse("https://gitlab.domain.tld")
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.verify_mode = 1
    response = http.request(Net::HTTP::Get.new(uri.request_uri))
    ...
    Traceback (most recent call last):
          1: from (irb):5
    OpenSSL::SSL::SSLError (SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate))
    

이 문제를 해결하려면:

자체 서명된 인증서를 사용하는 원격 GitLab 인스턴스에서
저장소를 미러링하려고 할 때 또 다른 오류 메시지가 발생할 수 있습니다:

2:Fetching remote upstream failed: fatal: unable to access 'https://gitlab.domain.tld/root/test-repo/':
SSL: unable to obtain common name from peer certificate

이 경우, 문제는 인증서 자체와 관련이 있을 수 있습니다:

  1. 자체 서명된 인증서에 공통 이름이 누락되지 않았는지 확인하세요.
    누락된 경우, 유효한 인증서를 재생성하세요.

  2. 인증서를 /etc/gitlab/trusted-certs에 추가하세요.

  3. sudo gitlab-ctl reconfigure를 실행하세요.

Git 작업을 수행할 수 없는 경우(내부 또는 자체 서명된 인증서로 인한 문제)

GitLab 인스턴스가 자체 서명된 인증서를 사용하거나 인증서가 내부 인증 기관(CA)에 의해 서명된 경우, Git 작업을 수행할 때 다음과 같은 오류가 발생할 수 있습니다:

$ git clone https://gitlab.domain.tld/group/project.git
'project'로 복제 중...
fatal: 'https://gitlab.domain.tld/group/project.git/'에 접근할 수 없습니다: SSL 인증서 문제: 자체 서명된 인증서
$ git clone https://gitlab.domain.tld/group/project.git
'project'로 복제 중...
fatal: 'https://gitlab.domain.tld/group/project.git/'에 접근할 수 없습니다: 서버 인증서 확인 실패. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: 없음

이 문제를 해결하려면:

  • 가능하다면 모든 Git 작업에 SSH 원격을 사용하세요. 이는 더 안전하고 편리한 방법으로 간주됩니다.

  • HTTPS 원격을 사용해야 하는 경우, 다음을 시도해 볼 수 있습니다:

    • 자체 서명된 인증서 또는 내부 루트 CA 인증서를 로컬 디렉토리(예: ~/.ssl)에 복사하고 Git이 인증서를 신뢰하도록 설정합니다:

      git config --global http.sslCAInfo ~/.ssl/gitlab.domain.tld.crt
      
    • Git 클라이언트에서 SSL 검증을 비활성화합니다. 이는 보안 위험으로 간주될 수 있으므로 임시 조치로 권장됩니다.

      git config --global http.sslVerify false
      

SSL_connect 잘못된 버전 번호

잘못된 구성으로 인해 다음과 같은 문제가 발생할 수 있습니다:

  • gitlab-rails/exceptions_json.log 항목에 포함된 내용:

    "exception.class":"Excon::Error::Socket","exception.message":"SSL_connect returned=1 errno=0 state=error: wrong version number (OpenSSL::SSL::SSLError)",
    "exception.class":"Excon::Error::Socket","exception.message":"SSL_connect returned=1 errno=0 state=error: wrong version number (OpenSSL::SSL::SSLError)",
    
  • gitlab-workhorse/current에 포함된 내용:

    http: 서버가 HTTPS 클라이언트에 HTTP 응답을 보냈습니다.
    http: 서버가 HTTPS 클라이언트에 HTTP 응답을 보냈습니다.
    
  • gitlab-rails/sidekiq.log 또는 sidekiq/current에 포함된 내용:

    message: SSL_connect returned=1 errno=0 state=error: wrong version number (OpenSSL::SSL::SSLError)
    message: SSL_connect returned=1 errno=0 state=error: wrong version number (OpenSSL::SSL::SSLError)
    

이러한 오류 중 일부는 Excon Ruby gem에서 발생하며, GitLab이 오직 HTTP만 제공하는 원격 서버에 대한 HTTPS 세션을 시작하도록 구성된 경우에 발생할 수 있습니다.

한 가지 시나리오는 객체 저장소를 사용하고 있는데, 이는 HTTPS로 제공되지 않는 경우입니다. GitLab이 잘못 구성되어 TLS 핸드쉐이크를 시도하지만, 객체 저장소가 일반 HTTP로 응답하는 상황입니다.

schannel: SEC_E_UNTRUSTED_ROOT

Windows를 사용하는 경우 다음 오류 메시지가 표시될 수 있습니다:

Fatal: 'https://gitlab.domain.tld/group/project.git'에 접근할 수 없습니다: schannel: SEC_E_UNTRUSTED_ROOT (0x80090325) - 인증서 체인이 신뢰할 수 없는 기관에 의해 발급되었습니다."

이 경우 Git이 OpenSSL을 사용하도록 지정해야 합니다:

git config --system http.sslbackend openssl

또는 다음을 실행하여 SSL 검증을 무시할 수 있습니다:

경고: SSL 무시하기에 유의하십시오. 이는 전역 수준에서 이 옵션을 비활성화하는 것과 관련된 잠재적인 보안 문제로 인해 주의 깊게 진행해야 합니다. 문제 해결 시에만 이 옵션을 사용하고, 즉시 SSL 검증을 복구하십시오.

git config --global http.sslVerify false

OpenSSL 3으로 업그레이드

버전 17.5부터 GitLab은 OpenSSL 3을 사용합니다. 일부 이전 TLS 프로토콜 및 암호 스위트, 또는 외부 통합에 대한 약한 TLS 인증서는 OpenSSL 3 기본값과 호환되지 않을 수 있습니다.

OpenSSL 3으로 업그레이드하면서:

  • 모든 수신 및 송신 TLS 연결에는 TLS 1.2 이상이 필요합니다.

  • TLS 인증서는 최소 112비트의 보안을 가져야 합니다. 2048비트보다 짧은 RSA, DSA 및 DH 키와 224비트보다 짧은 ECC 키는 금지됩니다.

다음 중 하나의 오류 메시지를 접할 수 있습니다:

  • TLS 연결에서 TLS 1.2보다 오래된 프로토콜을 사용할 때 no protocols available.
  • TLS 인증서의 보안이 112비트보다 낮을 때 certificate key too weak.
  • 레거시 암호가 요청될 때 unsupported cipher algorithm.

OpenSSL 3 가이드를 사용하여 외부 통합의 호환성을 식별하고 평가하세요.