为什么服务器禁用 SSLv3 后 git 停止工作?

为什么服务器禁用 SSLv3 后 git 停止工作?

与大多数其他服务器一样,我们的存储库服务器需要尽快禁用 SSLv3(和 v2)。

但是,这样做似乎会破坏我们的 git 客户端 — — 至少在 RHEL5 上是如此(从我的 FreeBSD 桌面连接工作正常)。即使是最新的 git (2.1.2) 也会失败,将 OpenSSL 库升级到供应商提供的最新版本也无济于事。

然而!同样的 git-client 可以很好地与 github.com 配合使用 - 而且 github.com 也已禁用 SSLv3。通过反复试验,我将我们服务器 (Apache) 的 SSL 配置设置为与 github 的 SSL 配置相匹配:

SSLProtocol     ALL -SSLv2 -SSLv3
SSLHonorCipherOrder On
SSLCipherSuite  "AES128-SHA AES256-SHA RC4-SHA"

通过sslscan对我们的服务器和 github 进行运行,我得到了相同的接受和拒绝的密码列表。但 git 仍然失败:

    % git clone https://git.example.net/git/puppet-hiera
    Cloning into 'puppet-hiera'...
    * Couldn't find host git.example.net in the .netrc file, using defaults
    * About to connect() to git.example.net port 443
    *   Trying 10.89.8.27... * connected
    * Connected to git.example.net (10.89.8.27) port 443
    * successfully set certificate verify locations:
    *   CAfile: /etc/pki/tls/certs/ca-bundle.crt
      CApath: none
    * Unknown SSL protocol error in connection to git.example.net:443
    * Closing connection #0
    fatal: unable to access 'https://git.example.net/git/puppet-hiera/': Unknown SSL protocol error in connection to git.example.net:443

现在,我们服务器的 SSL 和 GitHub 的 SSL 之间唯一明显的区别是sslscan能够输出 GitHub 证书的详细信息,但无法从我们的服务器获取这些信息。

当我从 FreeBSD 桌面连接到我们的 git 服务器时,同样的git clone命令有效。输出后,我不仅没有失败,CApath: none还看到:

      CApath: none
    * SSL connection using AES128-SHA
    * Server certificate:
             subject: C=US; postalCode= ............

克隆成功。我该如何配置我们的服务器,以便 git 甚至可以在旧的 RHEL5 系统上使用它——就像它对 GitHub 服务器所做的那样?

更新:尝试使用简单的 访问我们的服务器curl,我遇到了类似的 SSL 兼容性错误。但是,我能够通过使用显式选项--tlsv1(也称为-1)调用 curl 来克服它。因此,RHEL5 系统上的软件是有能力的必要的协议和密码——我如何让它默认使用它们,而不是尝试旧的并失败?

答案1

好吧,事情是这样的。在今天的 Apache 中禁用 SSLv3 意味着,服务器甚至不会告诉客户端它想要使用 TLS。如果客户端不开始与 TLS 的对话,客户端将会失败——即使可以讨论 TLS。非常感谢用户克里斯·S。,他分析了这个问题,甚至提出了一个修补Apachemod_ssl在回答相关问题

看过 Chris 的补丁后,Apache 开发人员想出了一个更全面的补丁,甚至可能成为下一个 Apache 版本的一部分。它为 Apache 的SSLProtocols指令引入了一个新选项:ANY。当 Apache 遇到时ANY,它将建议连接的客户端(通过 SSLv2Hello)必须切换到 TLS:

SSLProtocol ANY -SSLv2 -SSLv3

对于那些等不及 Apache 2.4.11 的人,我将其粘贴在这里。

Index: modules/ssl/ssl_private.h
===================================================================
--- modules/ssl/ssl_private.h    (revision 1635012)
+++ modules/ssl/ssl_private.h    (working copy)
@@ -295,8 +295,10 @@ typedef int ssl_opt_t;
 #define SSL_PROTOCOL_TLSV1_2 (1<<4)
 #define SSL_PROTOCOL_ALL   (SSL_PROTOCOL_SSLV3|SSL_PROTOCOL_TLSV1| \
                 SSL_PROTOCOL_TLSV1_1|SSL_PROTOCOL_TLSV1_2)
+#define SSL_PROTOCOL_ANY   (1<<5)
 #else
 #define SSL_PROTOCOL_ALL   (SSL_PROTOCOL_SSLV3|SSL_PROTOCOL_TLSV1)
+#define SSL_PROTOCOL_ANY   (1<<3)
 #endif
 typedef int ssl_proto_t;

Index: modules/ssl/ssl_engine_init.c
===================================================================
--- modules/ssl/ssl_engine_init.c    (revision 1635012)
+++ modules/ssl/ssl_engine_init.c    (working copy)
@@ -490,6 +490,7 @@ static apr_status_t ssl_init_ctx_protocol(server_r
     }

     cp = apr_pstrcat(p,
+                     (protocol & SSL_PROTOCOL_ANY ? "SSLv23, " : ""),
              (protocol & SSL_PROTOCOL_SSLV3 ? "SSLv3, " : ""),
              (protocol & SSL_PROTOCOL_TLSV1 ? "TLSv1, " : ""),
 #ifdef HAVE_TLSV1_X
Index: modules/ssl/ssl_engine_config.c
===================================================================
--- modules/ssl/ssl_engine_config.c    (revision 1635012)
+++ modules/ssl/ssl_engine_config.c    (working copy)
@@ -1311,6 +1311,9 @@ static const char *ssl_cmd_protocol_parse(cmd_parm
     else if (strcEQ(w, "all")) {
         thisopt = SSL_PROTOCOL_ALL;
     }
+        else if (strcEQ(w, "any")) {
+            thisopt = SSL_PROTOCOL_ANY|SSL_PROTOCOL_ALL;
+        }
     else {
         return apr_pstrcat(parms->temp_pool,
                parms->cmd->name,
Index: modules/ssl/ssl_engine_io.c
===================================================================
--- modules/ssl/ssl_engine_io.c    (revision 1635012)
+++ modules/ssl/ssl_engine_io.c    (working copy)
@@ -1137,6 +1137,7 @@ static apr_status_t ssl_io_filter_handshake(ssl_fi
      * IPv4 and IPv6 addresses are not permitted".)
      */
     if (hostname_note &&
+            !(sc->proxy->protocol & SSL_PROTOCOL_ANY) &&
         sc->proxy->protocol != SSL_PROTOCOL_SSLV3 &&
         apr_ipsubnet_create(&ip, hostname_note, NULL,
                 c->pool) != APR_SUCCESS) {

答案2

我喜欢你提供的关于如何进行服务器端调整以使 git 客户端正常工作的解释。我的问题是尝试连接到 jazzhub,而我无法更改服务器。我今天(以及昨晚深夜)想出了这个解决方案:

https://developer.ibm.com/answers/answers/164635/view.html

如果您对此有任何反馈,我很乐意听到。

-迈克尔

相关内容