Tech

RDP接続をクライアントPC名から判別して切断する方法

AD環境にあるサーバに接続してるRDPクライアントを、

  • 規定の時間以上Idle状態のユーザを
  • PC名で判定して

Disconnectしたいということ、ありますよね?

概要

はい、そういうシチュエーションありますよね。

例えば、ユーザごとの制限はしたくないけど、特定のPCからの接続に対してのみアイドル時間が一定以上を超えたセッションを切断する。

今回はそのシチュエーションに対してバッチファイルを作った話です。

0. 前提条件

特に書くことを思いつかなかった。

1. 何が問題だったか

Group Policyで探すと
[アクティブでアイドル状態になっているリモートデスクトップサービスセッションの制限時間を設定する]
(英語名:Set time limit for active but idle Remote Desktop Services sessions)

というものが見つかります。これはそのホストに接続しているRDPセッションが一定以上のIdle時間を超えたらセッションを切るという挙動になります。

しかしながらこれはホスト側の設定なので
「そのホストに接続しているセッション全てに対して」適用されてしまいます。

まぁその運用ができるならいいんですが、ちょっと待てよオフィスから接続しているユーザにそんな短い時間で切断したくないよというような要望があると思います。
例えば共用で使われてるPCからのRDP接続に対してのみセッションを切りたい(セッションの切り忘れに対処したい)という状況があるかと思います。

2. バッチファイルで解決した

いい方法が思いつかなかったのでバッチファイルを作りました。Administrator権限で実行するバッチです。

大枠の流れはこうです。

  1. レジストリHKEY_USERS\S-1-5-21-* から順番にセッションIDを取得
  2. レジストリ\Volatile Environment\"session_id"以下のCLIENTNAMEキーからPC名を取得
  3. Query user "session_id"を実行してIdle timeを取得
  4. PC名から、対象のクライアントPCかどうかを判別
  5. Idle timeが1時間を超えていたらtsdisconでセッションをDisconnect

3. バッチファイル中身

@echo off
setlocal enableextensions enabledelayedexpansion || exit /b 1
chcp 437 > nul

rem Make sure to put targets.txt file in the same folder.
set target=%~dp0targets.txt
set BAT_LOG=%~dp0disconnectrdp.log

rem This bat file is excuted every 30 mins on a Task Scheduler. Disconnect the session idling over 1 hr judging from a PC name on a target.txt file.
rem If you want to add a target PC, you should add a PC name in the bottom line in the target.txt file.

rem Lookup HKU S-1-5-21- registories.
for /f "usebackq" %%i in (`reg query HKU ^| findstr "S-1-5-21-" ^| findstr /V _Classes`) do (

  rem Initialize valuables.
  set session_id=
  set client_name=
  set user_name=
  set active=
  set idle_time=
  set apply=
  set reg_dir=%%i

  rem Get sessionID from "Volatile Environment" sub key.
  for /f "usebackq delims=\ tokens=4" %%j in (`reg query "!reg_dir!\Volatile Environment" ^| findstr "Volatile Environment"`) do (
    set session_id=%%j

    if not ""!session_id!""=="""" (

      rem Get a client_name from the CLIENTNAME key.
      for /f "usebackq tokens=3" %%k in (`reg query "!reg_dir!\Volatile Environment\!session_id!" /v "CLIENTNAME"`) do set client_name=%%k

      rem Check if user_name corresponds target.
      for /f %%o in (%target%) do (
        set tar=%%o
        if ""!client_name!""==""!tar!"" (
          set apply=true
        )
      )

      if ""!apply!""==""true"" (

        rem Execute QUERY command using session_id.
        for /f "skip=1 tokens=1,4,5" %%l in ('query user !session_id!') do (
          set user_name=%%l
          set active=%%m
          set idle_time=%%n

          rem Check if the session is active.
          if ""!active!""==""Active"" (

            rem Reformat idle_time value.
            set len=0
            call :GETLEN !idle_time!
            if !len! leq 2 if not "!idle_time!" equ "." (
              set idle_time=0!idle_time!
              set idle_time=0:!idle_time:~-2,2!
            )

            rem If the idle_time is over 1h, disconnect the session.
            if "!idle_time!" gtr "1:00" (
              echo %date% %time% Disconnected the session id:!session_id! user:!user_name! PC:!client_name! idle time:!idle_time!. >> %BAT_LOG% 2>&1
              tsdiscon !session_id!
            )
          )
        )
      )
    )
  )
)
exit

rem Check length of a string
:GETLEN
set str=%1
:LOOP
if not "%str%"=="" (
    set str=%str:~1%
    set /a len=%len%+1
    goto :LOOP
)
exit /b

4. 使い方

  1. cmdファイルと同フォルダにtarget.txtを作成(1行ずつ対象PC名を記載)
  2. タスクスケジューラにタスク設定(Administrator権限で)

5. おわりに

グループポリシーでできると思ってたけど、微妙に痒いところに手が届かなかったのでバッチで対処することになりました。他に方法はあるかもしれませんが今の所うまくいってます。

誰かの役に立てばいいなと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

x  Powerful Protection for WordPress, from Shield Security
このサイトは
Shield Security によって保護されています →