У меня странная проблема: 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
У нас периодически возникала эта ошибка после применения патчей для 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).
Я провел множество тестов, и нашим решением было откатить этот патч:
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 либо не поддерживает эти наборы шифров, либо не настроен для этого.
Учитывая это, у вас есть несколько вариантов:
- Использовать обходной путь - не устанавливать обновление KB 3161639.
- Переустановить обновление KB 3161639. Настройте упорядочивание шифров так, чтобы новые наборы шифров не выбирались.
Мы выбрали вариант 1, развернули его по всей нашей сети и не наблюдаем никаких негативных последствий. Надеюсь, это поможет.