故障排除

此页面包含使用极狐GitLab 时可能遇到的常见 SSL 相关错误和场景列表,作为 SSL 文档的主要补充:

有用的 OpenSSL 调试命令

有时,通过直接在源中查看 SSL 证书链,可以更好地了解它是有帮助的。这些命令是用于诊断和调试的标准 OpenSSL 工具库的一部分。

note 极狐GitLab 包含自己的 OpenSSL 的自定义编译版本,所有极狐GitLab 库都关联到该版本。使用此 OpenSSL 版本运行以下命令很重要。
  • 通过 HTTPS 执行与主机的测试连接。将 HOSTNAME 替换为您的极狐GitLab URL(不包括 HTTPS),并将 port 替换为提供 HTTPS 连接的端口(通常为 443):

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

    echo 命令向服务器发送一个空请求,导致它关闭连接而不是等待额外的输入。您可以使用相同的命令来测试远程主机(例如,托管外部仓库的服务器),方法是将 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 如果您是在使用系统 OpenSSL 应用而不是 /opt/gitlab/embedded/bin/openssl 应用时遇到了此错误,请确保您在操作系统级别更新了 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. Move it from /opt/gitlab/embedded/ssl/certs to a different location and reconfigure again.

检查 /opt/gitlab/embedded/ssl/certs 并删除除 README.md 之外的任何不是有效 X.509 证书的文件。

note 运行 gitlab-ctl reconfigure 构造从自定义公共证书的 subject 哈希命名的链接,并将它们放在 /opt/gitlab/embedded/ssl/certs/ 中。/opt/gitlab/embedded/ssl/certs/ 中损坏的链接将被自动删除。存储在 /opt/gitlab/embedded/ssl/certs/ 中的 cacert.pemREADME.md 以外的文件将被移动到 /etc/gitlab/trusted-certs/ 中。

丢失或跳过自定义证书

GitLab versions 8.9.0, 8.9.1, and 8.9.2 all mistakenly used the /etc/gitlab/ssl/trusted-certs/ directory. This directory is safe to remove if it is empty. If it still contains custom certificates then move them to /etc/gitlab/trusted-certs/ and run gitlab-ctl reconfigure.

如果没有在 /opt/gitlab/embedded/ssl/certs/ 中创建链接,你会看到运行gitlab-ctl reconfigure后出现 “Skipping cert.pem” 消息,这意味着可能存在以下四个问题之一:

  1. /etc/gitlab/trusted-certs/ 中的文件是链接
  2. 该文件不是有效的 PEM 或 DER 编码的证书
  3. Perl 未安装在 c_rehash 正确链接证书所需的操作系统上
  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

测试 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/ 中没有创建链接;
  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 失败

note 您可以使用 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 控制台进行的测试也失败:

    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/retrustedcerts,然后运行 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 Runner 与配置有内部 CA 证书或自签名证书的极狐GitLab 实例一起使用

除了在极狐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
    More details here: 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 实例的自签名证书添加到本地实例上的 /etc/GitLab/trusted certs 目录中,然后按照安装自定义公共证书的说明,运行 sudo GitLab ctl reconfigure
  • 如果您使用 Helm Charts 安装本地极狐GitLab 实例,您可以向您的极狐GitLab 实例添加自签署证书。

当尝试从使用自签名证书的远端极狐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. 验证您的自签名证书是否缺少通用名称(common name)。如果是,请重新生成有效证书。
  2. 将证书添加到 /etc/gitlab/trusted certs
  3. 运行 sudo gitlab ctl reconfig

由于内部证书或自签名证书的原因,无法执行 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 remote。这被认为更安全,使用更方便。
  • 如果必须使用 HTTPS remote,可以尝试以下操作:
    • 将自签名证书或内部根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.logsidekiq/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: 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 验证:

caution 由于与在全局级别禁用此选项相关的潜在安全问题,忽略 SSL 时请谨慎操作。仅在故障排除时使用此选项,然后立即恢复 SSL 验证。
git config --global http.sslVerify false

升级到 OpenSSL 3

从 17.7 开始,极狐GitLab 将使用 OpenSSL 3。一些老旧的 TLS 协议和密码套件,抑或针对外部集成的较弱 TLS 证书可能会和 OpenSSL 不兼容。

随着升级到 OpenSSL 3:

  • 对于所有进入或者出去的 TLS 链接都需要 TLS 1.2 或者更高版本。
  • TLS 证书必须最少要有 112 位的安全码。短于 2048 位的 RSA、DSA 和 DH key 以及短于 224 位的 ECC key 都将被禁止。

您可能会遇到以下错误信息:

  • 当 TLS 链接使用比 TLS 1.2 低的版本时会遇到 no protocols available
  • 当 TLS 证书的安全码少于 112 位时会遇到 certificate key too weak
  • 当请求一个旧版本密码套件时会遇到 unsupported cipher algorithm

使用 OpenSSL 3 指南来识别和获取您的外部集成兼容信息。