Ssl

為什麼伺服器禁用 SSLv3 後 git 停止工作?

  • November 14, 2014

像大多數其他人一樣,我們的儲存庫伺服器需要盡快禁用 SSLv3(和 v2)。

但是,這樣做似乎會破壞我們的 git-clients —— 至少在 RHEL5 上(來自我的 FreeBSD 桌面的連接工作正常)。即使是最新的 git (2.1.2) 也失敗了,從供應商處將 OpenSSL 庫升級到最新版本也無濟於事。

然而!相同的 git-client 對 github.com 工作得很好——而且 github.com 也已經禁用了 SSLv3。通過反複試驗,我將我們伺服器的 (Apache) SSL 配置設置為與 github 的配置相匹配:

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 之間唯一可察覺的區別sslscan是能夠輸出 GitHub 證書的詳細資訊,但無法從我們的伺服器獲取這些詳細資訊。

當我從我的 FreeBSD 桌面連接到我們的 git-server 時,同樣的git clone命令可以工作。在輸出之後,我沒有失敗,而是CApath: none看到:

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

並且複製成功。如何配置我們的伺服器,以便 git 甚至可以從舊的 RHEL5 系統使用它——就像它對 GitHub 伺服器一樣?

更新:嘗試使用簡單的方式訪問我們的伺服器curl,我在 SSL 兼容性方面遇到了類似的錯誤。--tlsv1但是,我能夠通過使用顯式選項(也稱為)呼叫 curl 來克服它-1。因此,RHEL5 系統上的軟體能夠使用必要的協議和密碼——我如何讓它預設使用它們而不是嘗試舊的並失敗?

好的,這是交易。在今天的 Apache 中禁用 SSLv3 意味著伺服器甚至不會告訴客戶端它想要使用 TLS。如果客戶端不使用 TLS開始對話,客戶端將失敗——即使可以使用 TLS。非常感謝使用者Chris S.,他分析了問題,甚至在回答相關問題時為 Apache提供了更新檔mod_ssl

看過 Chris 的更新檔後,Apache 開發人員提出了一個更全面的更新檔,甚至可能成為下一個 Apache 版本的一部分。它為 Apache 的SSLProtocols指令引入了一個新選項:ANY. 當 Apache 遇到TLS 時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) {

引用自:https://serverfault.com/questions/640344