FreeTDS не удается подключиться к SQL Server после недавних исправлений Windows и отключения TLS1

У меня странная проблема: FreeTDS (MacOS 10.11.5) не подключается к SQL Server 2014, работающему на Windows Server 2012 r2, к которому я мог подключиться ранее (около недели или около того назад). Сервер в последнюю неделю проходил через усиление безопасности (последние исправления 2012 r2, плюс другие вещи*, которые, как я полагаю, и являются виновником, но моя локальная машина для разработки (и фактически только FreeTDS на моей машине) кажется единственной проблемой после исправлений.

Я подозреваю, что причина проблемы кроется где-то в шифрах RC4 и SSL 2.0 & TLS 1.0 отключен, но я не знаю, как это исправить.

Для ясности, в отличие от других подобных вопросов - я не могу никакими средствами подключить freetds к DB01, но я могу подключить другие драйверы к DB01 (но я разрабатываю приложение на python и мне нужен freetds в этом случае) и другие машины могут подключаться к DB01.

Основная ошибка заключается в следующем:

$ tsql -S DB01 -U db_user
Password: ****************
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
Error 20002 (severity 9):
    Adaptive Server connection failed
There was a problem connecting to the server

Не очень полезно - я выполнил обычные действия по устранению неполадок, включая попытки различных версий TDS, использование различных переключателей в командной строке и т.д.

Журнал также указывает на возможность проблемы с SSL - например, tls.c регистрирует "handshake failed", пакет, содержащий строку "SSL_Self_Signed_Fallback" (иначе пакеты не читаются):

net.c:216:Connecting to 000.000.000.000 port 1433 (TDS version 7.4)
net.c:242:tds_open_socket: connect(2) returned "Operation now in progress"
net.c:343:tds_open_socket() succeeded
packet.c:741:Sending packet
[blah blah]
login.c:1185:detected flag 0
tls.c:116:in tds_push_func_login
tls.c:86:in tds_pull_func_login
packet.c:741:Sending packet
[blah blah]
packet.c:639:Received packet
[blah blah... what?
xxx |..0.S.S. L._.S.e.|
xxx |l.f._.S. i.g.n.e.|
xxx |d._.F.a. l.l.b.a.|
xxx |c.k0...1 blahblah|
tls.c:116:in tds_push_func_login
packet.c:741:Sending packet
0000 12 01 00 0f 00 00 00 00-15 03 00 00 02 02 28    |........ ......(|
tls.c:923:handshake failed
login.c:530:login packet rejected
query.c:3796:tds_disconnect() 
util.c:165:Changed query state from IDLE to DEAD
util.c:322:tdserror(0x7fef2b403aa0, 0x7fef2b403ba0, 20002, 0)
util.c:352:tdserror: client library returned TDS_INT_CANCEL(2)
util.c:375:tdserror: returning TDS_INT_CANCEL(2)
mem.c:644:tds_free_all_results()

Когда я подключаюсь к другим серверам и смотрю на freetds.log, я могу прочитать пакеты (вроде как), например:

xxx |.C.h.a.n .g.e.d. |
xxx |.d.a.t.a .b.a.s.e|
xxx |. .c.o.n .t.e.x.t|
xxx |. .t.o.  .'.m.a.s|
xxx |.t.e.r.' 

в отличие от DB01, где пакеты представляют собой строки и строки }.???G??? .??T???٠.

А вот и freetds Compile-time settings -- нужен ли мне GnuTLS = да?

$ tsql -C
Compile-time settings (established with the "configure" script)
                            Version: freetds v1.00.9
             freetds.conf directory: /usr/local/Cellar/freetds/1.00.9/etc
     MS db-lib source compatibility: no
        Sybase binary compatibility: no
                      Thread safety: yes
                      iconv library: yes
                        TDS version: 7.3
                              iODBC: no
                           unixodbc: yes
              SSPI "trusted" logins: no
                           Kerberos: no
                            OpenSSL: yes
                             GnuTLS: no
                               MARS: no

вот мой файл freetds.conf:

[global]
    # TDS protocol version
    tds version = auto
    dump file = /tmp/freetds.log
    debug flags = 4FFF
    text size = 64512
[DB01]
    host = db01.mydomain.tld
    port = 1433
    tds version = 7.4
    database = DB_NAME
    # I added this in case it was a cert issue, see below
    check certificate hostname = no

Некоторые другие быстрые данные по устранению неполадок:

  • Используя TCPVew на сервере, я вижу, что мои соединения принимаются (но журнал также подтверждает это).

  • У нас есть сервер windows, который обслуживает PHP страницы (подключение к DB01 через ODBC), и у нас не было проблем с подключением этого сервера к DB01. с подключением этого сервера к DB01

  • Я могу использовать jTDS (через IntelliJ и Pycharm) для подключения к db01 прекрасно, это был бы конец расследования, если бы я мог подключить jTDS в приложении django.

  • Microsoft's JDBC Driver не подключается к db01 (это также новый), этот драйвер выдает такую ошибку:

     [08S01] Драйвер не смог установить безопасное соединение с SQL Server

    используя шифрование Secure Sockets Layer (SSL). Ошибка: "Сервер выбрал SSLv3, но эта версия протокола не включена или не поддерживается клиентом." ... java.lang.RuntimeException: javax.net.ssl.SSLHandshakeException: Сервер выбрал SSLv3, но эта версия протокола не включена или не поддерживается клиентом.

Кто-нибудь еще сталкивался с этим? Есть ли способ указать TLS 1.2 и т.д. при подключении с помощью freetds? (Я не смог найти документацию по этому вопросу).

UPDATE:

Я решил посмотреть в средстве просмотра событий Windows на наличие ошибок, и вот что там есть:

    DB01    17836   Error   MSSQLSERVER Application 7/20/2016 2:52:18 PM
    The login packet used to open the connection is structurally invalid;
 the connection has been closed. Please contact the vendor of the client
 library. [CLIENT: [my ip address]]

    [and also]

    Length specified in network packet payload did not match number of 
bytes read; the connection has been closed. Please contact the vendor 
of the client library. [CLIENT: [my ip address]]
Решение

TLDR; Мне нужно было переустановить freetds с поддержкой gnutls вместо openssl..

После множества (нет, действительно множества) проб и ошибок я, наконец, нашел решение проблемы с тем, что freetds на mac не подключается.

Мне все еще нужно подключить все остальное, чтобы работал pyodbc и т.д., но вот основное решение:

brew edit freetds.

Замените формулу freetds на следующую https://gist.github.com/hanleybrand/dfb7b9004aae250fabd01cd2466251c4

Вкратце, это добавляет опцию --with-gnutls в установку brew и убеждается, что если она существует, то появляется перед --with-openssl. Я не изучал этот вопрос подробно, но подозреваю, что openssl/gnutls - это или/или, а не или/или.

brew rm freetds && brew install freetds --with-gnutls --with-unixodbc.

После этого tsql заработал нормально - как я уже говорил, мне еще предстоит настроить все остальное (unixodbc, pyodbc), но я уверен, что если tsql работает, то и остальное тоже, хотя я не могу быть полностью уверен.

Это может быть связано с наборами шифров в двух пакетах (openssl и gnutls), как указывает @FlipperPA

Комментарии (2)

У нас периодически возникала эта ошибка после применения патчей для Linux и MS. Мы по-прежнему могли подключаться из Linux к серверу MSSQL, но случайным образом наше соединение завершалось с ошибкой EOF... даже в середине запроса. Я включил журнал freetds и увидел ошибку квитирования шифрования, подобную этой:

    net.c:1366:handshake failed: A TLS packet with unexpected length was received.          
    login.c:466:login packet rejected
    util.c:331:tdserror(0x1e752b0, 0x2c27f40, 20002, 0)

После долгих поисков мы откатили KB3172605 на сервер MS Windows Server 2008 R2, на котором работает наша СУБД MS SQL Server... это решило проблему. (KB 3172605 заменяет KB 3161639).

Комментарии (3)

Я провел множество тестов, и нашим решением было откатить этот патч:

https://support.microsoft.com/en-us/kb/3161639

Судя по всему, набор шифров затрагивает не только Edge и IE. :) Я открыл дело в Microsoft, и они знают о проблемах, которые это вызвало. Из уст лошади:

Поскольку проблема больше не возникает после удаления этого KB. обновление решило проблему, я провел быстрый поиск по этому обновлению KB для предыдущие случаи. На данный момент было зарегистрировано 21 дело о проблемах с этим обновлением с прошлого месяца. Если вы не знаете, и на основании моего исследования, KB 3161639 добавляет дополнительные ключи шифрования, использующие протокол TLS 1.2, который был представлен в обновлении KB 3161608. Следующие шифры, скорее всего, являются причиной проблемы:

TLS_DHE_RSA_WITH_AES_128_CBC_SHA

TLS_DHE_RSA_WITH_AES_256_CBC_SHA

Я подозреваю, что либо ваш Unix/Linux сервер и/или FreeTDS ODBC либо не поддерживает эти наборы шифров, либо не настроен для этого.
Учитывая это, у вас есть несколько вариантов:

  1. Использовать обходной путь - не устанавливать обновление KB 3161639.
  2. Переустановить обновление KB 3161639. Настройте упорядочивание шифров так, чтобы новые наборы шифров не выбирались.

Мы выбрали вариант 1, развернули его по всей нашей сети и не наблюдаем никаких негативных последствий. Надеюсь, это поможет.

Комментарии (0)