5

SQL Server で、データベースへのすべての (成功した) ログイン/接続を記録するログ ファイルを作成します。ログには、最小限以下が含まれている必要があります。

  • 接続しているクライアントの IP アドレスとポート
  • クライアントのアプリケーション名
  • ユーザー名
  • データベース名
  • 接続時または該当する取引

サーバー トレースはこのすべての情報をキャプチャできる可能性が高いように見えますが、Microsoft は、サーバー トレースは拡張イベントを支持して非推奨であると述べています。

そのため、拡張イベントを使用してこの情報を収集しようとしています。私のテストでは、SQL Server 2017 Developer Edition (Windows 10 の Docker コンテナーで実行) と SSMS v17.7 を使用しています。拡張イベントを作成または表示するときに「sa」としてログインしています。

これまでのところ、拡張イベントを使用してこの情報のほとんどを収集できました。問題は、クライアントの IP とポートを収集することです。どちらかを単独で取得することはできますが、両方を同時に取得することはできません。私が使用している XEvent を以下に示します。2 度記載されていることconnection_acceptは間違いではありません。SQL Server には、実際にはまったく同じ名前の 2 つの異なるイベントがあります (!!!)。

  • Login: クライアント IP またはポートを収集するためのオプション (フィールドまたはアクション) はありません。少なくともそれは提供しますclient_hostname!
  • Logout: クライアント IP またはポートを収集するためのオプション (フィールドまたはアクション) はありません。これもキャプチャしclient_hostnameます。
  • connection_accept:
    • クライアント IP を収集しますが、最下位のオクテット (192.168.1.XX など) をマスクします!!!
    • クライアントポートを収集!良い!
    • Loginsession_id を収集しないため、またはLogoutイベントと関連付けることができません。
    • Myは、およびEVENT SESSIONのコレクションを指定しますが、これらのフィールド/アクションは収集されたデータに存在しません。:(usernameclient_app_nameclient_hostname
  • connection_accept:
    • クライアント ポートを収集しますが、クライアント IP は収集しません!!!
    • session_id があるため、少なくとも関連付けることができLoginLogout
    • 注:私はまだこの特定のイベントを実際に捕まえていないので、これ以上のコメントはありません。

これらのイベントはいずれもクライアントの IP アドレスを提供しませんが、クライアントのホスト名を妥当な代替物として受け入れます。ただし、ポート番号を取得することは実際の問題です。ポート番号はイベントでのみ検出され、それをホスト名を持つイベントconnection_acceptに関連付ける明らかな方法はありません。loginつまり、拡張イベントは、この基本的なクライアント IP とポートのペアリングを提供できないようです。それはとても基本的なデータなので、私は間違っていると信じたいです。私が見落としていることについての助けや提案は大歓迎です。

拡張イベント DDL

EVENT SESSION私がテストしてきたのDDLは次のとおりです。

CREATE EVENT SESSION [Connections] ON SERVER 
ADD EVENT SQLSatellite.connection_accept(
    ACTION(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.context_info,sqlserver.database_name,sqlserver.nt_username,sqlserver.request_id,sqlserver.server_instance_name,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.transaction_id,sqlserver.username)
    WHERE ([sqlserver].[not_equal_i_sql_unicode_string]([sqlserver].[client_app_name],N'SQLServerCEIP'))),
ADD EVENT sqlserver.connection_accept(
    ACTION(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.context_info,sqlserver.database_name,sqlserver.nt_username,sqlserver.request_id,sqlserver.server_instance_name,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.transaction_id,sqlserver.username)
    WHERE ([sqlserver].[not_equal_i_sql_unicode_string]([sqlserver].[client_app_name],N'SQLServerCEIP'))),
ADD EVENT sqlserver.connectivity_ring_buffer_recorded(
    ACTION(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.server_instance_name,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_nt_username,sqlserver.transaction_id,sqlserver.username)
    WHERE ([sqlserver].[client_app_name]<>N'SQLServerCEIP')),
ADD EVENT sqlserver.login(SET collect_options_text=(1)
    ACTION(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.server_instance_name,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_nt_username,sqlserver.transaction_id,sqlserver.username)
    WHERE ([sqlserver].[client_app_name]<>N'SQLServerCEIP')),
ADD EVENT sqlserver.logout(
    ACTION(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.server_instance_name,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_nt_username,sqlserver.transaction_id,sqlserver.username)
    WHERE ([sqlserver].[client_app_name]<>N'SQLServerCEIP'))
ADD TARGET package0.event_file(SET filename=N'c:\xevents\connections')
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)
GO

代替案

拡張イベントとは別に、 "セキュリティ監査" は非推奨ではないもう 1 つのメカニズムです。だから私もこれを試してみようと思った:

USE [master]
GO

CREATE SERVER AUDIT [AuditTest]
TO FILE 
(   FILEPATH = N'C:\xevents\'
    ,MAXSIZE = 2 MB
    ,MAX_FILES = 5
    ,RESERVE_DISK_SPACE = OFF
)
WITH
(   QUEUE_DELAY = 1000
    ,ON_FAILURE = CONTINUE
)

CREATE SERVER AUDIT SPECIFICATION [Connections]
FOR SERVER AUDIT [AuditTest]
ADD (SUCCESSFUL_LOGIN_GROUP),
ADD (LOGOUT_GROUP)

GO

これが提供するフィールドには、「クライアント アプリ」、「クライアント IP」、「セッション ID」、およびユーザー名 (つまり、「サーバー プリンシパル名」) がありました。connection_acceptただし、これをXEventに関連付ける方法はありません。そのため、必要な 2 つの情報 (クライアント IP とポート番号) を抽出する方法はありません。:(

ボーナス

クライアントの IP とポートを収集する以外に、SQL Server のネットワーク トラフィック量の収集にも関心があります。ただし、それを行う方法もまだ見ていません。ヒントをいただければ幸いです。あいまいに関連する投稿しか表示されません。

アップデート

とイベントtask_addressを関連付けるように見えるloginグローバルアクション (フィールド) が呼び出されていることに気付きました。したがって、とを組み合わせることで、IP とポートを見つけることができるようになりました。私の唯一の懸念は、私の観察を検証するためのドキュメントが見つからないことです。logoutconnection_acceptlogin:client_hostnameconnection_accept:porttask_address

4

1 に答える 1