ほとんどの人は SQL Server のホスト名を完全なアドレスと見なし、VPN を許可か不許可かのどちらかと考える。実際には名前付きインスタンスは、クライアントに DNS の後に二回目の検索をさせるが、トンネルが最も頻繁に壊すのはまさにその検索である。明示的なエンドポイントはそれを回避するので、tcp:host,port が機能する一方で host\INSTANCE がタイムアウトすることがある。違いは、サービスを見つけることと、それを使う許可を得ることの間にある。

神話:一つのホスト名は一つのポートを意味する

ホスト名はアドレスに解決され、そこで役割は終わる。名前付きインスタンスは、サーバーが TCP ポートに変換しなければならないインスタンス名を追加し、クライアントはそれを推測できない。ポート 1433 は既定のインスタンスの既定値であり、マシン上のすべてのインスタンスの性質ではない。両者を同じものとして扱うと、ping は通り、DNS も通り、1433 のスキャンは何も示さず、結論はネットワークが SQL をブロックしているという典型的な症状が生じる。

二つ目の前提、すなわち TCP 1433 を開ければ十分だという前提も同じように破綻する。インスタンスが別の場所で待ち受けているなら、開いている 1433 は何か別のものがあることしか証明しない。ポートはリスナーと一致しなければならず、リスナーはサーバー側の設定の詳細であること これは推測するのではなく尋ねるべきものだ。

クライアントは名前付きインスタンスで実際に何をするのか

ホストを解決した後、クライアントは UDP 1434 で SQL Server Browser に検出要求を送り、名前付きインスタンスが使うポートを尋ねる。ブラウザーサービスはサーバー自身のレジストリから応答し、その後クライアントはそのポートへ TCP 接続を開く。ログインを試みる前に、二つのプロトコルと二つのポートが関与する。

nslookup sqlhost.corp.example
nc -vzu sqlhost.corp.example 1434
Get-Service -Name SQLBrowser

そのため UDP だけを遮断すると、死んだホストのように見えるタイムアウトになる。ブラウザーサービスが停止または無効になっていると、データベースエンジンが動作し TCP ポートが開いていても、検出要求は答えのないままになる。インスタンスが固定ポートで構成されている場合、エンドポイントを直接与えられていない限り、クライアントはそれでも問い合わせる。これらの失敗はどれもアプリケーションのエラーメッセージでは同じに見え、必要な修正は異なる。

ブラウザーサービスは検出のための便宜であり、データベースではない。停止してもエンジンは止まらず、開始してもインスタンスの TCP ポートは開かない。

名前が機能しないときに明示的なエンドポイントが機能する理由

明示的なエンドポイントは検索を手順から外し、クライアントは指定したアドレスとポートに直接接続する。後でインスタンスが動的ポートに再構成されればポートが変わりうるため、これは自動的な恒久的修正ではなく、まず診断である。結論を出す前に、同じクライアントと同じアカウントで両方の形式を比較してほしい。

sqlcmd -S "tcp:sqlhost.corp.example,51433" -U app_login -Q "SELECT @@SERVERNAME"
Test-NetConnection sqlhost.corp.example -Port 51433

明示的な形式が成功し、名前付きの形式が失敗するなら、検出が欠けている部分であり、トンネルで UDP 1434 を許可するか、管理者に固定ポートを設定させエンドポイントを文書化してもらうかで塞ぎ方を選べる。どちらも保守コストの異なる意図的な判断だ。範囲内のすべてのポートを開けるのはどちらでもなく、長い一日の終わりに提案されがちな選択肢である。選択は接続文字列が置かれている場所に記録してほしい。

どちらの形式も機能しないなら、問題は検出より上流にある。ブラウザーサービスを責める前に、リスナー、ルート、そしてインスタンスが実際に使うポートのアクセス規則を確認してほしい。

検出の後:認証と ID は別物

ログインの失敗はタイムアウトとは別の出来事であり、トンネルがあるからといって VPN の ID が SQL ログインになるわけではない。クライアントが正しいポートに到達すると、データベースエンジンは独自の認証と権限を適用する。二つの段階を一つのチケットに混ぜると、検出の問題が間違ったチームに割り当てられる。何かを変える前にエラー番号を読んでほしい。

ドライバーがサーバー証明書を検証するなら、数値アドレスでの接続が元の問題を解決するのではなく検証自体を変えてしまいかねないため、文書化されたホスト名を維持してほしい。最近の Microsoft ドライバーは既定で暗号化するため、名前の不一致は TCP 接続の成功後に証明書エラーとして現れる。それは新しい失敗ではなく前進だ。

捨てるべき神話は、SQL Server のホスト名が完全なアドレスだというものだ。それはホストであり、名前付きインスタンスではトンネルが運ばないかもしれない検索が加わる。ポートを示し、検出路を示せば、次の失敗がどの層を直すべきか教えてくれる。

関連記事