最近のWindowsパッチとTLS1無効化の後、FreeTDSがSQL Serverに接続できない。
以前(1週間ほど前)は接続できていたWindows Server 2012 r2上で動作するSQL Server 2014にFreeTDS(MacOS 10.11.5)が接続できない、という奇妙な問題があります。先週、サーバーはセキュリティハードニング(最新の2012 r2パッチ、およびその他のもの※)を受けており、これが原因だと思いますが、私のローカル開発マシン(実際には私のマシン上のFreeTDSのみ)はパッチの後に問題が発生しているようです。
RC4暗号とSSL 2.0 & TLS 1.0が無効になっていることが問題の原因だと思われますが、それを改善する方法がわかりません。
はっきり言って、他の同様の質問とは異なり、私はいかなる手段でもDB01にfreetdsを接続することはできませんが、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のバージョンを変えてみたり、コマンドラインで別のスイッチを使ったりと、通常のトラブルシューティングは行っています。
例えば 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とは異なり、パケットは`}の行と行で構成されています。
以下、freetds コンパイル時の設定 -- GnuTLSは必要か = yes?
$ 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を使用すると、接続が受け入れられていることが確認できます(ログでも確認できます)。
-
私たちは、PHPページを提供するWindowsサーバーを持っています。 PHPページ(ODBC経由でDB01に接続)を提供するWindowsサーバがあり、そのサーバがDB01に接続することに問題はありませんでした。 そのサーバーからDB01への接続は問題ありません。
-
jTDSを使用して(IntelliJとPycharm経由で)DB01に接続することは可能です。 jTDSをDB01に接続することができれば、この調査は終了です。 jTDSをdjangoアプリで配線することができれば、これで調査は終了です。
-
Microsoft's JDBC Driver will not to db01 (this is also new), that driver gives this error. 新しい)、そのドライバは、このエラーを与える。
[08S01] ドライバがSQL Serverへの安全な接続を確立できませんでした。
Secure Sockets Layer (SSL)暗号化を使用した安全な接続を確立できませんでした。 エラー: "サーバーはSSLv3を選択しましたが、そのプロトコル・バージョンはクライアントで有効になっていないか、サポートされていません。 ... java.lang.RuntimeException: javax.net.ssl.SSLHandshakeException: サーバーはSSLv3を選択しましたが、そのプロトコルのバージョンは有効になっていないか、クライアントがサポートしていません。 またはクライアントがサポートしていない。
他にこれを見た人はいますか? freetdsで接続する際にTLS1.2などを指定する方法はないのでしょうか?(これに関するドキュメントを見つけることができませんでした。)
更新:
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; I needed to re-install freetds with support for gnutls instead of openssl.を再インストールする必要がありました。
試行錯誤の末、ようやくmacのfreetdsが接続できない解決策を見つけました。
まだ、pyodbcが動作するように残りの部分を配線する必要がありますが、これが基本的な修正方法です。
ブリューで freetds を編集する`。
freetdsの数式を次のように置き換えます。 https://gist.github.com/hanleybrand/dfb7b9004aae250fabd01cd2466251c4
要するに、これは brew install に
--with-gnutls
というオプションを追加し、もしそれが存在するなら--with-openssl
の前に発生するようにします。 まだよく調べていませんが、openssl/gnutlsはどちらか一方であって、どちらか一方ではないのではないかと思います。brew rm freetds && brew install freetds --with-gnutls --with-unixodbc` です。
その後、tsqlはうまくいきました。上で述べたように、残りの部分(unixodbc, pyodbc)をまだセットアップしなければなりませんが、私はtsqlがうまくいけば、残りの部分もうまくいくとかなり確信しています(完全に確信できるわけではありませんが)。
これは @FlipperPA が指摘するように、2つのパッケージの暗号セット(openssl と gnutls)に関連しているのかもしれません。
LinuxとMSのパッチを適用した後、断続的にこのエラーが発生しました。 LinuxからMSSQLサーバーへの接続は可能でしたが、クエリの途中でもランダムにEOFエラーで接続が終了していました。 freetdsログをオンにすると、このような暗号化ハンドシェイクの失敗が見られました。
トラブルシューティングの後、MS SQL Server DBを実行しているMS Windows Server 2008 R2サーバーでKB3172605**をロールバックしました...これで問題は解決しました。 (KB3172605はKB3161639より優先されます。)
私はこの件で何度もテストを行い、私たちの解決策はこのパッチをロールバックすることでした。
https://support.microsoft.com/en-us/kb/3161639
どうやら、この暗号スイートはEdgeとIE以外にも影響を及ぼしているようです :)Microsoftに問い合わせたところ、この問題が発生したことを認識しているとのことです。From the horse's mouth:
そのKBをアンインストールしたところ、問題が発生しなくなりましたので そのKBのアップデートをアンインストールしたら問題が発生しなくなったので、そのKBのアップデートについて検索してみたところ 先行事例を検索してみました。 現時点では、21件の不具合事例があります。 そのKBアップデートは、先月以降、21件の事例があります。 もし、あなたが知らないのであれば、そして、私の調査に基づくと KB 3161639は、TLSを利用した暗号鍵の追加です。 1.2プロトコルが追加されました。 以下の暗号が、この問題を引き起こしている可能性が高いです。 TLS_DH1
私たちは、オプション1を選択し、ネットワーク全体に展開しましたが、悪影響は見られません。これがお役に立てれば幸いです。