Почему git перестал работать после того, как сервер отключил SSLv3?
Как и большинство других, наш сервер репозитория должен отключить SSLv3 (и v2) как можно скорее.
Однако это, похоже, нарушает работу наших git-клиентов - по крайней мере, на RHEL5 (соединения с моего рабочего стола FreeBSD работают нормально). Даже самый последний git (2.1.2) дает сбой, и обновление библиотек OpenSSL до последней версии от поставщика не помогло.
Однако! Тот же самый git-клиент прекрасно работает с github.com - и на github.com SSLv3 уже отключен. Методом проб и ошибок я установил SSL-конфигурацию нашего сервера (Apache), соответствующую конфигурации 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, но не может получить его с нашего сервера.
Когда я подключаюсь к нашему git-серверу с рабочего стола FreeBSD, git clone
команда работает. Вместо сбоя, после вывода CApath: none
, Я вижу:
CApath: none
* SSL connection using AES128-SHA
* Server certificate:
subject: C=US; postalCode= ............
и клонирование успешно. Как мне настроить наш сервер так, чтобы git работал с ним даже со старых RHEL5-систем - как это происходит с GitHub-серверами?
Обновление: пытаясь получить доступ к нашему серверу просто curl
Я получил похожую ошибку по SSL-совместимости. Тем не менее, я смог преодолеть это, вызвав curl с явным --tlsv1
вариант (также известный как -1
). Таким образом, программное обеспечение в системах RHEL5 способно поддерживать необходимые протоколы и шифры - как мне заставить их использовать их по умолчанию вместо того, чтобы пытаться использовать старые и давать сбой?
2 ответа
Хорошо, вот сделка. Отключение SSLv3 в современном Apache означает, что сервер даже не скажет клиенту, что он хочет использовать TLS. Если клиент не начинает разговор с TLS, клиент потерпит неудачу - даже если может говорить TLS. Большое спасибо пользователю Chris S., который проанализировал проблему и даже предложил патч для Apache. mod_ssl
в ответе на связанный вопрос.
Взглянув на патч Криса, разработчики 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) {
Мне нравится объяснение, которое вы предоставили для того, как внести изменения на стороне сервера, чтобы заставить работать клиентов git. Моя проблема пыталась подключиться к jazzhub, где у меня нет возможности сменить сервер. Я придумал это решение сегодня (и поздно вечером):
https://developer.ibm.com/answers/answers/164635/view.html
Если у вас есть отзывы об этом, я хотел бы услышать это.
-Майкл