故障排除

此页面包含使用极狐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。

  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)。

golang 编写的 Git-LFS 等嵌入式服务报告未知机构签名的自定义证书

gitlab-workhorse 和其他用 golang 编写的服务使用来自 golangcrypto/tls 库而不是 OpenSSL

/etc/gitlab/gitlab.rb 中添加以下条目以解决问题:

gitlab_workhorse['env'] = {
  'SSL_CERT_DIR' => '/opt/gitlab/embedded/ssl/certs/'
}
note如果您已将 GitLab 安装到除 /opt/gitlab/ 之外的路径,请在您的操作环境中使用正确的路径修改上面的条目。

证书导致重新配置失败

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. 您未看到任何跳过的或链接的自定义证书消息

您可能会遇到 Omnibus 认为已添加自定义证书的问题。

要解决,请删除受信任的证书目录哈希:

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

然后再次运行gitlab-ctl reconfigure。重新配置应现在检测并链接您的自定义证书。

Let’s Encrypt 证书由未知机构签署

Let’s Encrypt 集成的初始实现仅使用证书,而不是完整的证书链。

现在使用完整的证书链。对于已经在使用证书的安装,在续订逻辑指示证书即将到期之前不会发生切换。要尽快强制执行,请运行以下命令:

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

其中 HOSTNAME 是证书的主机名。

重新配置时 Let’s Encrypt 失败

重新配置时,Let’s Encrypt 可能会在以下常见情况下失败:

  1. 如果您的服务器无法访问 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 已打开并可访问

  2. 您的域名的证书颁发机构授权 (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
    
  3. 如果您使用的是例如 gitlab.example.com 之类的测试域名,但没有证书,您将看到上面显示的 unable to request certificate。在这种情况下,通过在 /etc/gitlab/gitlab.rb 中设置 letsencrypt['enable'] = false 来禁用 Let’s Encrypt。

您可以使用 Let’s Debug 诊断工具测试您的域名。它可以帮助您找出无法颁发 Let’s Encrypt 证书的原因。

在极狐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 实例镜像仓库时,还可能会收到另一条错误消息:

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