最近の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)に関連しているのかもしれません。

解説 (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)

トラブルシューティングの後、MS SQL Server DBを実行しているMS Windows Server 2008 R2サーバーでKB3172605**をロールバックしました...これで問題は解決しました。 (KB3172605はKB3161639より優先されます。)

解説 (3)

私はこの件で何度もテストを行い、私たちの解決策はこのパッチをロールバックすることでした。

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

TLS_DHE_RSA_WITH_AES_128_CBC_SHA

TLS_DHE_RSA_WITH_AES_256_CBC_SHA

あなたのUnix/LinuxサーバとFreeTDS ODBCのどちらか、またはその両方が、これらに対応していないのではないでしょうか。 は、これらの暗号スイートに対応していないか、そのための設定がされていません。
このような場合、いくつかの選択肢があります。 1; 1.KB3161639のアップデートをインストールしない回避策をとる。 2.KB3161639のアップデートを再インストールする。 新しい暗号スイートが選択されないように、暗号の順序を設定する。

私たちは、オプション1を選択し、ネットワーク全体に展開しましたが、悪影響は見られません。これがお役に立てれば幸いです。

解説 (0)