横井 羽衣子 (よこい ういこ)
SQL Developer Support Engineer
- Data Access
皆様ごきげんよう。本日は、「クラスタ化された構成の SQL Server 2008 Service Pack 1 以前のバージョンの名前付きインスタンスに Windows Vista 以降から接続できない」という現象についてお知らせいたします。
【今日のお題】
Windows Firewall ログを取ってみてみたところ、SQL Server Browser サービスの利用する UDP 1434 あてのパケットがファイアウォールまで到達している状況だった。取り急ぎ、クライアントアプリケーションで、接続先インスタンスのポート番号を指定してみたところ、接続はできるようになったが、この対処の妥当性などについても不安。 |
この現象について
以下の条件がそろった場合に、上記エラーが発生します。これらの条件は、AND 条件です。
・SQL Server のバージョンが 2000 および 2005、2008 サービス パックなしの環境
・クラスタ構成
・名前付きインスタンス
・Windows Vista 以降のバージョンから接続を実施する
クラスタ構成の場合、接続先の IP アドレスは物理 IP と仮想 IP が存在しますが、Windows Vista 以降のセキュリティ強化されたファイアウォールは、通信パケットの IP アドレスが両者の IP で合致しない(厳密なソース マッピングが出来ない)ために、応答パケットを破棄してしまいます。
これにより、上記のようなエラーが発生することになります。
クライアント OS として Windows Vista がリリースされて以降、弊社研究開発本部ではこの動作を問題として認識し、SQL Server 側で対処を実施しました。
しかしながら、SQL Server 2008 サービス パック 1 以降から対処がなされているため、SQL Server 2005 (全サービス パックのバージョン) および SQL Server 2008 RTM (サービス パック適用なし) から SQL Server 2008 サービス パック 1 より前のバージョンにおいては、例外のプログラムやリモート IP を登録いただく運用回避を取っていただく必要があります。
対処方法
ご利用の SQL Server によって、それぞれ以下のように対処いただく必要があります。
SQL Server 2000、2005 SQL Server 2008 サービス パックなし |
しかし、SQL Server 2000、2005 の場合や、SQL Server 2008 環境でも、なかなかサービス パックを適用するのが難しい場合もあると思います。そうした場合は、例外プログラムやリモート IP を登録する方法で対処します。では、方法を見てみましょう。
■クライアント アプリケーションの動作環境側で対処する
(1)特定のアプリケーションに対してのみ対処する場合
以下のいずれか接続元アプリケーションに対して実施します。
1. 接続文字列で、接続先の名前付きインスタンスの TCP ポート番号を指定する。
2. 名前付きパイプ プロトコルで接続をするようにする。
(2)クライアント マシン全体に有効な対処をする場合(複数のアプリケーションが動作している場合など)
アプリケーションが動作するマシン上の Windows Firewall で以下の対処のいずれかを実施します。
A. SQL Server に接続するアプリケーション用の送信の規則を作成する。
1. コントロール パネルの [システムとメンテナンス] をクリックし、[管理ツール] をクリックします (クラシック表示の場合は [管理ツール] をダブルクリックします)。
2. [管理ツール] の [セキュリティが強化された Windows ファイアウォール] をダブルクリックします。
3. [セキュリティが強化された Windows ファイアウォール] で [送信の規則] をクリックし、[新規の規則] をクリックします。
4. [プログラム] をクリックし、[次へ] をクリックします。
5. [このプログラムのパス] をクリックし、アプリケーションのパスを指定し、[次へ] をクリックします。
6. [接続を許可する] をクリックし、[次へ] をクリックします。
7. 新規の送信の規則ウィザードの手順を完了します。
B. リモー�� サーバーで使用可能なすべての IP アドレス、またはフェールオーバー クラスタ インスタンス用に構成されている使用可能なすべての IP アドレスからのトラフィックを許可する受信の規則を作成する。
1. コントロール パネルの [システムとメンテナンス] をクリックし、[管理ツール] をクリックします (クラシック表示の場合は [管理ツール] をダブルクリックします)。
2. [管理ツール] の [セキュリティが強化された Windows ファイアウォール] をダブルクリックします。
3. [セキュリティが強化された Windows ファイアウォール] で [受信の規則] をクリックし、[新規の規則] をクリックします。
4. [カスタム] をクリックし、[次へ] をクリックします。
5. [すべてのプログラム] をクリックし、[次へ] をクリックします。
6. [プロトコルの種類] ボックスの一覧で [任意] をクリックし、[次へ] をクリックします。
7. [この規則はどのリモート IP アドレスに一致しますか?] の [これらの IP アドレス] をクリックし、[追加] をクリックします。
8. [IP アドレス] ダイアログ ボックスの [この IP アドレスまたはサブネット] の下に、いずれかの IP アドレスを入力し、[OK] をクリックします。
9. その他の IP アドレスを追加するには、手順 7. ~ 8. を繰り返し [次へ] をクリックします。
10.[接続を許可する] をクリックし、[次へ] をクリックします。
11.新規の受信の規則ウィザードの手順を完了します。
※ netsh firewall コマンドで一括登録するという手法もあります。
Netsh を使用して Windows ファイアウォールを管理する
http://technet.microsoft.com/ja-jp/library/cc776229(v=ws.10).aspx
では、次項でなぜこんなことになるか、見ていきましょう。
SQL Server の名前付きインスタンスに接続するまでの動作の流れと問題発生のメカニズム
本事象は、今回のように SQL Server 環境がクラスタ化されている場合の他、複数の IP アドレスを持つ場合に発生することが報告されています。
名前付きインスタンスに接続する場合には、下記の流れで接続します。
1. クライアントは SQL Server の待ち受けポートを確認するために、データベース サーバーに対して UDP 要求パケットを送信します。
2. SQL Server 側で、UDP 要求パケットを受信します。
3. 要求を受けて、SQL Server 側では、SQL Server Browser サービスが、SQL Server のインスタンス名と待ち受けポートに関する情報を含む UDP 応答パケットをクライアントへ送信します。
4. クライアントは、UDP 応答パケットを受信します。
5. クライアントは、UDP 応答パケットで受け取ったポート番号を使用して SQL Server に接続を行います。
しかし、前述の条件を満たす環境において、4. の処理(サーバからの UDP 応答パケットの受信)までは完了していますが、Windows Vista 以降の OS では、ファイア ウォールにおいて、UDP 応答パケットを破棄することになります。これにより、フェーズ 5. の接続処理に至らない状況となり、問題が発生します。この動作については、弊社でも問題と捉えており、SQL Server 2008 SP1 にて動作が変更され、事象が発生しないように実装変更が行われました。
この現象については、以下をご参照ください。
Windows Vista または Windows Server 2008 を実行しているクライアント コンピュータ上で SQL Server の名前付きインスタンスに接続するとエラー メッセージ "指定された SQL Server が見つかりません" または "指定された Server/Instance の位置を特定しているときにエラーが発生しました" が表示される
http://support.microsoft.com/kb/944390
技術情報 944390について
この問題を例えていうと、「うちの娘に良くわからん素性のやつは会わせられん」とお父様が勝手に彼氏からの手紙を捨てちゃって、娘からすると彼から連絡がないのでもういいわ…あきらめましょう、となって関係が終わっちゃったという感じです。
…はい、わけわかりませんね。ちょっと整理します。
・娘さん … 接続元のクライアントのアプリケーション
・お父さん… Windows Firewall
・素性の良くわからない彼氏 … クラスタ化された SQL Server
※ 娘とお父さんはおなじおうち ( = 同じマシン) に住んでいます。
上記の一連の接続までの流れのうち、フェーズ 3.において、SQL Server 側は UDP 応答パケットに SQL Server が稼動しているマシンの "物理" IP アドレスを含めます。しかしクラスタ環境の場合、クライアントから見える IP アドレスは "仮想" IP アドレスになります。
そのため、クラスタ環境では上記 2 つの異なる IP アドレスが存在する形となります。
しかし、Windows Vista 以降 (Windows 7 も含む) の OS の Windows ファイアウォールはセキュリティが強化されているため、このような "厳密でない" ソース マッピングを許可しません。
これにより、Windows ファイア ウォールは SQL Server から送信された UDP 応答パケットを破棄することになります。
今回の場合には、ポートとしては、サーバー側で許可されているポート、クライアント側で許可されているポートのいずれも、フェーズ 1. から 5. のやり取りが可能なポートが許可されています。 しかしながら、クラスタ環境の SQL Server からのパケットはこうした理由により、クライアント側の Windows Firewall で破棄されてしまいます。それにより接続できない事象が発生します。
■ 問題発生時の動作の流れ
1. クライアントは SQL Server の待ち受けポートを確認するために、データベース サーバーに対して UDP 要求パケットを送信します。
2. SQL Server 側で、UDP 要求パケットを受信します。
図 : クライアントアプリケーションは、SQL Server へ接続要求を実施する
3. 要求を受けて、SQL Server 側では、SQL Server Browser サービスが、SQL Server のインスタンス名と待ち受けポートに関する情報を含む UDP 応答パケットをクライアントへ送信します。
4. クライアントの Windows Firewall が、SQL Server からの UDP 応答パケットを受信し、内容を確認します。
図 : Windows Firewall はアプリケーションに先んじてパケットを受け取る
4. パケットの差出人の IP アドレスは仮想 IP アドレスなのに、接続先情報は物理 IP アドレスであるという状態のパケットであるため、Windows Firewall がパケットを破棄してしまいます。
図 : Windows Firewall は厳密ではないソースマッピングのパケットを破棄してしまう
5. SQL Server に接続したいアプリケーションには、情報は届きません。しかし、アプリケションには自分の環境の Windows Firewall が SQL server からのパケットを破棄したということまではわかりません。
図 : アプリケーションは、Windows Firewall がパケットを削除したことなどわからないので、接続先がわからず接続に失敗する
6. SQL Server の情報が届かないため、クライアントのアプリケーションでは「指定された SQL Serverが見つかりません。 」エラーが発生し、SQL Server への接続が失敗します。
補足 : 接続問題の際の対処について
今回のエラーは、SQL Server のインスタンスに到達していませんので、SQL Server Profiler など SQL Server 側のデータでは確認できません。 接続については、その内容によって一連の接続処理のうち何れで問題が発生しているかについて、エラー メッセージから確認をします。 以下の記事においてそれぞれの問題発生のタイミングにあわせた情報採取方法などについてご案内しております。
Troubleshooting: Connectivity #1 - SQL Server への接続
http://blogs.msdn.com/b/jpsql/archive/2011/11/28/troubleshooting-connectivity-1-sql-server.aspx
Troubleshooting: Connectivity #2 - エラー情報からわかる失敗原因
http://blogs.msdn.com/b/jpsql/archive/2012/04/05/troubleshooting-connectivity-2.aspx
Troubleshooting Connectivity #3 - 予期しない接続切断
http://blogs.msdn.com/b/jpsql/archive/2012/07/20/troubleshooting-connectivity-3.aspx
いかがでしたでしょうか。何とも、クライアントの “マシン” にサーバーからのパケットは到達してるのに、それが Windows firewall が捨ててしまうので、その先のマシンの中の箱入り娘(接続元のプログラム)には届かないので接続できないなんてことがあるんですね。
それでは皆さんごきげんよう。