SSL 문제 해결

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

이 페이지에는 GitLab 작업 중에 마주칠 수 있는 일반 SSL 관련 오류 및 시나리오 목록이 포함되어 있습니다. 이는 주요 SSL 문서에 추가로 제공될 것입니다:

유용한 OpenSSL 디버깅 명령어

SSL 인증서 체인을 직접 확인하여 더 나은 그림을 얻는 것이 도움이 되는 경우가 있습니다. 이러한 명령어는 진단 및 디버깅을 위한 표준 OpenSSL 라이브러리의 일부입니다.

참고: GitLab은 사용자 지정 컴파일된 OpenSSL 버전을 포함하고 있으며, 모든 GitLab 라이브러리가 이에 연결됩니다. 이 OpenSSL 버전을 사용하여 다음 명령을 실행하는 것이 중요합니다.

  • HTTPS를 통해 호스트로의 테스트 연결 수행. HOSTNAME을 GitLab URL로, 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를 신뢰하거나, 연결하려는 서버에 등록된 전체 체인 인증서를 제시하도록 인증서를 수정해야 합니다.

    참고: 클라이언트가 연결할 때 SSL 오류를 방지하기 위해 전체 인증서 체인을 사용하는 것이 좋습니다. 전체 인증서 체인 순서는 먼저 서버 인증서, 그 다음 중간 인증서 모두, 마지막으로 루트 CA로 이루어져야 합니다.

  2. unable to verify the first certificate

    이 오류는 서버가 불완전한 인증서 체인을 제시하는 것을 나타냅니다. 이 오류를 해결하려면, 서버의 인증서를 전체 체인으로 대체해야 합니다. 전체 인증서 체인 순서는 먼저 서버 인증서, 그 다음 중간 인증서 모두, 마지막으로 루트 CA로 이루어져야 합니다.

    참고: 시스템 OpenSSL 유틸리티가 아닌 /opt/gitlab/embedded/bin/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)이 인증서에 구성되어 있어야 함을 나타냅니다. 자세한 정보는 이 이슈를 참조하세요.

인증서로 인한 Reconfigure 실패

ERROR: Not a certificate: /opt/gitlab/embedded/ssl/certs/FILE. Move it from /opt/gitlab/embedded/ssl/certs to a different location and reconfigure again.

/opt/gitlab/embedded/ssl/certs를 확인하고 README.md가 아닌 유효한 X.509 인증서가 아닌 파일을 제거하세요.

참고: 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이 OS에 설치되어 있지 않음
  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-----

만약 위 예제와 같이 해당 문자열이 포함된다면 해당 문자열을 제거하고 다시 gitlab-ctl reconfigure를 실행해보세요.

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

gitlab-ctl reconfigure를 실행한 후:

  1. /opt/gitlab/embedded/ssl/certs/에 심볼릭 링크가 생성되지 않은 경우
  2. 사용자 정의 인증서를 /etc/gitlab/trusted-certs/에 배치한 경우 및
  3. 건너뛰거나 심볼릭 링크로 연결된 사용자 정의 인증서 메시지를 볼 수 없는 경우

사용자 정의 인증서가 이미 추가되었다고 생각하는 Linux 패키지 설치 문제가 발생한 것일 수 있습니다.

해결하려면, 신뢰할 수 있는 인증서 디렉토리 해시를 삭제하세요:

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

그런 다음 다시 gitlab-ctl reconfigure를 실행하세요. 이제 다시 구성하면 사용자 정의 인증서가 감지되고 심볼릭 링크가 만들어집니다.

알 수 없는 기관이 서명한 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
    

    GitLab 구성 중에 Let’s Encrypt으로 인한 문제가 발생하면 포트 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과 같은 테스트 도메인을 사용하고 인증서가 없는 경우, 위에 표시된 인증서를 요청할 수 없음 오류가 표시됩니다. 그 경우 /etc/gitlab/gitlab.rb에서 letsencrypt['enable'] = false로 설정하여 Let’s Encrypt를 비활성화하세요.

  • Let’s Encrypt은 요율 제한을 시행하며 최상위 도메인에서 이루어집니다. 예를 들어 *.cloudapp.azure.com과 같은 클라우드 제공업체 호스트명을 external_url로 사용하는 경우, 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 인스턴스의 mirror를 설정하는 동안 인증서 문제: 로컬 발급자 인증서를 가져올 수 없음 오류가 표시됩니다.
  • 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 해시 예시는 다음과 같습니다:

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

다음은 불일치하는 키와 인증서 간의 md5 해시 예시로, 서로 다른 md5 해시가 표시됩니다:

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

이전 예시와 같이 두 출력이 다른 경우 인증서와 키가 일치하지 않습니다. SSL 인증서 제공업체에 문의하여 추가 지원을 받으세요.

내부 CA 인증서 또는 자체 서명된 인증서가 구성된 GitLab 인스턴스에서 GitLab Runner 사용

GitLab에서 내부 CA 인증서 사용하기에 언급된 오류 외에도 CI 파이프라인이 대기 중 상태에서 멈출 수 있습니다. Runner 로그에서 다음과 같은 오류 메시지를 볼 수 있습니다.

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 인증서 문제: 자체 서명된 인증서 오류 메시지가 표시될 수 있습니다.

이 문제의 원인은 다음을 확인하여 확인할 수 있습니다:

  • curl이 실패하는지 확인:

    $ curl "https://gitlab.domain.tld"
    curl: (60) SSL certificate problem: self signed certificate
    More details here: https://curl.haxx.se/docs/sslcerts.html
    
  • 레일즈 콘솔을 사용한 테스트도 실패하는지 확인:

    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
Cloning into 'project'...
fatal: unable to access 'https://gitlab.domain.tld/group/project.git/': SSL certificate problem: self signed certificate
$ git clone https://gitlab.domain.tld/group/project.git
Cloning into 'project'...
fatal: unable to access 'https://gitlab.domain.tld/group/project.git/': server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none

이 문제를 해결하려면:

  • 가능하다면 모든 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: server gave HTTP response to HTTPS client
    http: server gave HTTP response to HTTPS client
    
  • 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이 HTTPS 세션을 시작하도록 구성되어 있는 상황에서, HTTP만 제공하는 원격 서버로 HTTPS 세션을 시도할 때 발생할 수 있습니다.

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

schannel: SEC_E_UNTRUSTED_ROOT

Windows를 사용 중이고 다음 오류 메시지를 받은 경우:

Fatal: unable to access 'https://gitlab.domain.tld/group/project.git': schannel: SEC_E_UNTRUSTED_ROOT (0x80090325) - The certificate chain was issued by an authority that is not trusted."

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비트의 보안이 있어야 합니다. RSA, DSA 및 DH 키는 2048비트보다 짧거나, ECC 키는 224비트보다 짧은 경우 허용되지 않습니다.

다음과 같은 오류 메시지를 만날 수 있습니다:

  • TLS 연결에서 TLS 1.2 이전의 프로토콜을 사용하는 경우 사용 가능한 프로토콜 없음.
  • TLS 인증서의 보안이 112비트 미만인 경우 인증서 키가 너무 약함.
  • 레거시 암호가 요청된 경우 지원되지 않는 암호 알고리즘.

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