Windows DHCPサーバー-非AD参加デバイスがIPアドレスを取得したときに通知を取得


15

シナリオ

これを最も簡単な例に単純化するには:

DHCPサーバーの役割を持つWindows 2008 R2標準DCがあります。さまざまなIPv4スコープ経由でIPを配布しますが、問題はありません。

私が好きなもの

デバイスがDHCPアドレスリースを取得し、そのデバイスがActive Directory内のドメイン参加コンピューターではない場合に、通知/イベントログエントリ/類似を作成する方法が欲しい。カスタムPowershellなどであるかどうかは関係ありません。

要点= 現時点では802.1Xを使用せずに、非ドメインデバイスがネットワーク上にあることを知りたいのですが。 これは静的IPデバイスを考慮しないことを知っています。ネットワークをスキャンしてデバイスを検出する監視ソフトウェアはありますが、これほど詳細ではありません。

研究完了/オプションを考慮

組み込みのロギングではこのような可能性は見当たりません。

はい、802.1Xを認識しており、この場所で長期的に実装することができますが、そのようなプロジェクトからしばらく離れています。それにより、ネットワーク認証の問題は解決しますが、これは外部の私にとってはまだ役に立ちます802.1Xの目標。

スクリプトビットなどを探してみましたが、役に立つかもしれませんが、私が見つけたものは、私のgoogle-fuが現時点で私を失敗させていると信じさせます。

私は以下のロジックが健全であると信じています(既存のソリューションが存在しないと仮定して):

  1. デバイスはDHCPアドレスを受け取ります
  2. イベントログエントリが記録されます(DHCP監査ログのイベントID 10は機能するはずです(更新ではなく、新しいリースが最も興味があるため):http : //technet.microsoft.com/en-us/library /dd759178.aspx
  3. この時点で、おそらく残りの「STEPS」については、ある種のスクリプトが引き継ぐ必要があるでしょう。
  4. どういうわけか、これらのイベントID 10についてこのDHCPログを照会します(プッシュが大好きですが、ここではプルが唯一の手段であると推測しています)
  5. 新しいリースを割り当てられているデバイスの名前のクエリを解析します
  6. ADにデバイス名を問い合わせる
  7. IF ない ADで見つかった、通知メールを送信

誰かがこれを適切に行う方法についてアイデアを持っているなら、私は本当に感謝しています。「gimme the codez」を探しているわけではありませんが、上記のリストに代わるものがあるかどうか、またはこの情報を収集するための明確な考えがなく、別の方法が存在するかどうかを知りたいです。これを達成するために共有したいコードスニペット/ PSコマンドがある場合は、さらに良い方法です。


あなたはそれらをブロックしたいですか、それとも彼らがIPを取得した場合に通知を受けるだけですか?
HostBits

@Cheekaleak-通知を受け取るだけです。
-TheCleaner

DHCPを使用するネットワークプリンターはどうですか?
jftuga

@jftuga-ネットワークプリンターに静的IPを使用します。
-TheCleaner

回答:


6

ErikEとここにいる他の人たちに感謝します。私は道を歩みました...それが正しい道だとは言いませんが、私が思いついたPowershellスクリプトはトリックをします。

誰かが望めば、コードは以下にあります。各DHCPサーバーをポイントして手動で実行するか、スケジュールを設定します(スクリプト内の各DHCPサーバーを再度ポイントします)。

スクリプトの機能:

  1. DHCPサーバーからリース情報を取得します(ipv4リース)
  2. リースをcsvファイルに出力します
  3. ADを照会するためにそのCSVファイルを読み取ります
  4. コンピューターのADを照会します
  5. 見つからない場合は、新しいtxtファイルへの出力
  6. 上記の#5で作成されたものから一意のリスト最終txtファイルを作成します(クライアントが複数回、または複数のアダプターで登録すると重複する可能性があるため)
  7. 最終出力ファイルの内容を管理者にメールで送信します

必要なもの:

スクリプトはADモジュール(import-module activedirectory)を使用するため、DHCPを実行するAD DCで実行するのが最適です。これが当てはまらない場合は、AD powershellモジュールをインストールできます:http ://blogs.msdn.com/b/rkramesh/archive/2012/01/17/how-to-add-active-directory- module-in-powershell-in-windows-7.aspx

また、http://www.quest.com/powershell/activeroles-server.aspxにあるQuestのAD Powershellコマンドレットも必要 です。 スクリプトを実行する前にこれらインストールしないと、失敗します。

スクリプト自体(サニタイズされ、入力ファイル名、接続するドメイン、接続するdhcpサーバー、電子メールの設定など、ニーズに合わせていくつかの変数を設定する必要があります):

# Get-nonADclientsOnDHCP.ps1

# Author : TheCleaner http://serverfault.com/users/7861/thecleaner with a big thanks for a lot of the lease grab code to Assaf Miron on code.google.com

# Description : This Script grabs the current leases on a Windows DHCP server, outputs it to a csv
# then takes that csv file as input and determines if the lease is from a non-AD joined computer.  It then emails
# an administrator notification.  Set it up on a schedule of your choosing in Task Scheduler.
# This helps non-802.1X shops keep track of rogue DHCP clients that aren't part of the domain.

#

# Input : leaselog.csv

# Output: Lease log = leaselog.csv
# Output: Rogue Clients with dupes = RogueClients.txt
# Output: Rogue Clients - unique = RogueClientsFinal.txt

$DHCP_SERVER = "PUT YOUR SERVER NAME OR IP HERE" # The DHCP Server Name

$LOG_FOLDER = "C:\DHCP" # A Folder to save all the Logs

# Create Log File Paths

$LeaseLog = $LOG_FOLDER+"\LeaseLog.csv"

#region Create Scope Object

# Create a New Object

$Scope = New-Object psobject

# Add new members to the Object

$Scope | Add-Member noteproperty "Address" ""

$Scope | Add-Member noteproperty "Mask" ""

$Scope | Add-Member noteproperty "State" ""

$Scope | Add-Member noteproperty "Name" ""

$Scope | Add-Member noteproperty "LeaseDuration" ""

# Create Each Member in the Object as an Array

$Scope.Address = @()

$Scope.Mask = @()

$Scope.State = @()

$Scope.Name = @()

$Scope.LeaseDuration = @()

#endregion


#region Create Lease Object

# Create a New Object

$LeaseClients = New-Object psObject

# Add new members to the Object

$LeaseClients | Add-Member noteproperty "IP" ""

$LeaseClients | Add-Member noteproperty "Name" ""

$LeaseClients | Add-Member noteproperty "Mask" ""

$LeaseClients | Add-Member noteproperty "MAC" ""

$LeaseClients | Add-Member noteproperty "Expires" ""

$LeaseClients | Add-Member noteproperty "Type" ""

# Create Each Member in the Object as an Array

$LeaseClients.IP = @()

$LeaseClients.Name = @()

$LeaseClients.MAC = @()

$LeaseClients.Mask = @()

$LeaseClients.Expires = @()

$LeaseClients.Type = @()

#endregion


#region Create Reserved Object

# Create a New Object

$LeaseReserved = New-Object psObject

# Add new members to the Object

$LeaseReserved | Add-Member noteproperty "IP" ""

$LeaseReserved | Add-Member noteproperty "MAC" ""

# Create Each Member in the Object as an Array

$LeaseReserved.IP = @()

$LeaseReserved.MAC = @()

#endregion


#region Define Commands

#Commad to Connect to DHCP Server

$NetCommand = "netsh dhcp server \\$DHCP_SERVER"

#Command to get all Scope details on the Server

$ShowScopes = "$NetCommand show scope"

#endregion


function Get-LeaseType( $LeaseType )

{

# Input : The Lease type in one Char

# Output : The Lease type description

# Description : This function translates a Lease type Char to it's relevant Description


Switch($LeaseType){

"N" { return "None" }

"D" { return "DHCP" }

"B" { return "BOOTP" }

"U" { return "UNSPECIFIED" }

"R" { return "RESERVATION IP" }

}

}


function Check-Empty( $Object ){

# Input : An Object with values.

# Output : A Trimmed String of the Object or '-' if it's Null.

# Description : Check the object if its null or not and return it's value.

If($Object -eq $null)

{

return "-"

}

else

{

return $Object.ToString().Trim()

}

}


function out-CSV ( $LogFile, $Append = $false) {

# Input : An Object with values, Boolean value if to append the file or not, a File path to a Log File

# Output : Export of the object values to a CSV File

# Description : This Function Exports all the Values and Headers of an object to a CSV File.

#  The Object is recieved with the Input Const (Used with Pipelineing) or the $inputObject

Foreach ($item in $input){

# Get all the Object Properties

$Properties = $item.PsObject.get_properties()

# Create Empty Strings - Start Fresh

$Headers = ""

$Values = ""

# Go over each Property and get it's Name and value

$Properties | %{ 

$Headers += $_.Name + ","

$Values += $_.Value

}

# Output the Object Values and Headers to the Log file

If($Append -and (Test-Path $LogFile)) {

$Values | Out-File -Append -FilePath $LogFile -Encoding Unicode

}

else {

# Used to mark it as an Powershell Custum object - you can Import it later and use it

# "#TYPE System.Management.Automation.PSCustomObject" | Out-File -FilePath $LogFile

$Headers | Out-File -FilePath $LogFile -Encoding Unicode

$Values | Out-File -Append -FilePath $LogFile -Encoding Unicode

}

}

}


#region Get all Scopes in the Server 

# Run the Command in the Show Scopes var

$AllScopes = Invoke-Expression $ShowScopes

# Go over all the Results, start from index 5 and finish in last index -3

for($i=5;$i -lt $AllScopes.Length-3;$i++)

{

# Split the line and get the strings

$line = $AllScopes[$i].Split("-")

$Scope.Address += Check-Empty $line[0]

$Scope.Mask += Check-Empty $line[1]

$Scope.State += Check-Empty $line[2]

# Line 3 and 4 represent the Name and Comment of the Scope

# If the name is empty, try taking the comment

If (Check-Empty $line[3] -eq "-") {

$Scope.Name += Check-Empty $line[4]

}

else { $Scope.Name += Check-Empty $line[3] }

}

# Get all the Active Scopes IP Address

$ScopesIP = $Scope | Where { $_.State -eq "Active" } | Select Address

# Go over all the Adresses to collect Scope Client Lease Details

Foreach($ScopeAddress in $ScopesIP.Address){

# Define some Commands to run later - these commands need to be here because we use the ScopeAddress var that changes every loop

#Command to get all Lease Details from a specific Scope - when 1 is amitted the output includes the computer name

$ShowLeases = "$NetCommand scope "+$ScopeAddress+" show clients 1"

#Command to get all Reserved IP Details from a specific Scope

$ShowReserved = "$NetCommand scope "+$ScopeAddress+" show reservedip"

#Command to get all the Scopes Options (Including the Scope Lease Duration)

$ShowScopeDuration = "$NetCommand scope "+$ScopeAddress+" show option"

# Run the Commands and save the output in the accourding var

$AllLeases = Invoke-Expression $ShowLeases 

$AllReserved = Invoke-Expression $ShowReserved 

$AllOptions = Invoke-Expression $ShowScopeDuration

# Get the Lease Duration from Each Scope

for($i=0; $i -lt $AllOptions.count;$i++) 

{ 

# Find a Scope Option ID number 51 - this Option ID Represents  the Scope Lease Duration

if($AllOptions[$i] -match "OptionId : 51")

{ 

# Get the Lease Duration from the Specified line

$tmpLease = $AllOptions[$i+4].Split("=")[1].Trim()

# The Lease Duration is recieved in Ticks / 10000000

$tmpLease = [int]$tmpLease * 10000000; # Need to Convert to Int and Multiply by 10000000 to get Ticks

# Create a TimeSpan Object

$TimeSpan = New-Object -TypeName TimeSpan -ArgumentList $tmpLease

# Calculate the $tmpLease Ticks to Days and put it in the Scope Lease Duration

$Scope.LeaseDuration += $TimeSpan.TotalDays

# After you found one Exit the For

break;

} 

}

# Get all Client Leases from Each Scope

for($i=8;$i -lt $AllLeases.Length-4;$i++)

{

# Split the line and get the strings

$line = [regex]::split($AllLeases[$i],"\s{2,}")

# Check if you recieve all the lines that you need

$LeaseClients.IP += Check-Empty $line[0]

$LeaseClients.Mask += Check-Empty $line[1].ToString().replace("-","").Trim()

$LeaseClients.MAC += $line[2].ToString().substring($line[2].ToString().indexOf("-")+1,$line[2].toString().Length-1).Trim()

$LeaseClients.Expires += $(Check-Empty $line[3]).replace("-","").Trim()

$LeaseClients.Type += Get-LeaseType $(Check-Empty $line[4]).replace("-","").Trim()

$LeaseClients.Name += Check-Empty $line[5]

}

# Get all Client Lease Reservations from Each Scope

for($i=7;$i -lt $AllReserved.Length-5;$i++)

{

# Split the line and get the strings

$line = [regex]::split($AllReserved[$i],"\s{2,}")

$LeaseReserved.IP += Check-Empty $line[0]

$LeaseReserved.MAC += Check-Empty $line[2]

}

}

#endregion 


#region Create a Temp Scope Object

# Create a New Object

$tmpScope = New-Object psobject

# Add new members to the Object

$tmpScope | Add-Member noteproperty "Address" ""

$tmpScope | Add-Member noteproperty "Mask" ""

$tmpScope | Add-Member noteproperty "State" ""

$tmpScope | Add-Member noteproperty "Name" ""

$tmpScope | Add-Member noteproperty "LeaseDuration" ""

#endregion

#region Create a Temp Lease Object

# Create a New Object

$tmpLeaseClients = New-Object psObject

# Add new members to the Object

$tmpLeaseClients | Add-Member noteproperty "IP" ""

$tmpLeaseClients | Add-Member noteproperty "Name" ""

$tmpLeaseClients | Add-Member noteproperty "Mask" ""

$tmpLeaseClients | Add-Member noteproperty "MAC" ""

$tmpLeaseClients | Add-Member noteproperty "Expires" ""

$tmpLeaseClients | Add-Member noteproperty "Type" ""

#endregion

#region Create a Temp Reserved Object

# Create a New Object

$tmpLeaseReserved = New-Object psObject

# Add new members to the Object

$tmpLeaseReserved | Add-Member noteproperty "IP" ""

$tmpLeaseReserved | Add-Member noteproperty "MAC" ""

#endregion

# Go over all the Client Lease addresses and export each detail to a temporary var and out to the log file

For($l=0; $l -lt $LeaseClients.IP.Length;$l++)

{

# Get all Scope details to a temp var

$tmpLeaseClients.IP = $LeaseClients.IP[$l] + ","

$tmpLeaseClients.Name = $LeaseClients.Name[$l] + ","

$tmpLeaseClients.Mask =  $LeaseClients.Mask[$l] + ","

$tmpLeaseClients.MAC = $LeaseClients.MAC[$l] + ","

$tmpLeaseClients.Expires = $LeaseClients.Expires[$l] + ","

$tmpLeaseClients.Type = $LeaseClients.Type[$l]

# Export with the Out-CSV Function to the Log File

$tmpLeaseClients | out-csv $LeaseLog -append $true

}



#Continue on figuring out if the DHCP lease clients are in AD or not

#Import the Active Directory module
import-module activedirectory

#import Quest AD module
Add-PSSnapin Quest.ActiveRoles.ADManagement

#connect to AD
Connect-QADService PUTTHEFQDNOFYOURDOMAINHERE_LIKE_DOMAIN.LOCAL | Out-Null

# get input CSV
$leaselogpath = "c:\DHCP\LeaseLog.csv"
Import-csv -path $leaselogpath | 
#query AD for computer name based on csv log
foreach-object `
{ 
   $NameResult = Get-QADComputer -DnsName $_.Name
   If ($NameResult -eq $null) {$RogueSystem = $_.Name}
   $RogueSystem | Out-File C:\DHCP\RogueClients.txt -Append
   $RogueSystem = $null

}
Get-Content C:\DHCP\RogueClients.txt | Select-Object -Unique | Out-File C:\DHCP\RogueClientsFinal.txt
Remove-Item C:\DHCP\RogueClients.txt

#send email to netadmin
$smtpserver = "SMTP SERVER IP"
$from="DHCPSERVER@domain.com"
$to="TheCleaner@domain.com"
$subject="Non-AD joined DHCP clients"
$body= (Get-Content C:\DHCP\RogueClientsFinal.txt) -join '<BR>&nbsp;<BR>'
$mailer = new-object Net.Mail.SMTPclient($smtpserver)
$msg = new-object Net.Mail.MailMessage($from,$to,$subject,$body)
$msg.IsBodyHTML = $true
$mailer.send($msg)

それが他の誰かを助けることを願っています!


3

OK、ここでエチケットをフォローしているのかどうかはわかりませんが、以前の質問を編集する代わりに2番目の回答を投稿しています。もしそれがこのフォーラムで私をバカにしてくれたら、私の間違った方法を気軽に知らせてください。

この問題はいくつかの部分に分かれています。ここで、私が最も興味深いと思うものに対する提案を示します。ログからの例がなければ、これは私ができる最善のことなので、解決策ではなく単なる提案です。

ログを解析するにget-contentは、-waitパラメーターとともに使用します。私のユースケースでは、エラーログでエラーを見つけるだけで十分です。

これは私自身のユースケースでうまくいったものですが、フォーマットを許してください:

get-content E:\temp13\log.txt -tail(1) -wait | where {$_ -match "ERROR"} |
    foreach {
        send-mailmessage `
        -port 25 `
        -smtpserver my.mail.server `
        -from logmon@a.b `
        -to erike@a.b `
        -subject "test logmonitor" `
        -body "ERROR found: $_" `
        }

代わりに、$_ -match "ERROR"ログIDフィールドとコンピューター名を何らかの方法で分離する必要があります。私は今それを最善の方法でどのように実行するのかわかりませんが、where-object -match正規表現のサポートを提供するので、それはオプションかもしれないと思います。また、$ _変数を別の新しい変数に格納することから始めて、後でパイプラインで、ネストされたforeachループ内などで都合のよいときにそれを取得できるようにすることもできます。

コンピューター名を取得できると仮定すると、get-adcomputerコマンドレットはAD(import-module activedirectory)を照会する最も簡単な方法であり、エラーが発生するとメールを送信すると思いますか?

使用import-csvの当然はるかにエレガントなあなたのケースではだろうが、私は(誰もがこれを読んで、たまたま、その路地続いて下さい、お願いシェアアップのトリックを知っていれば)、それを尾行のいずれかの方法を認識していませんよ。


ErikEに感謝します、私はこれで走り、知らせます。情報を取得し、ADを照会し、「アラート」がその同じ入力行の今後のチェックを無視した後、情報を取得する方法を見つける必要があります。たとえば、5分ごとにファイルを照会する場合、同じ情報を再解析して5分ごとにデュープアラートを送信しないようにします。
-TheCleaner

ちょっとしたすてきなことが2つあります。スクリプトを実行させるだけの場合、waitパラメーターは、新しい行が表示されるのを常に待機させます。スクリプトを再実行する必要はありません。彼は引っ張るのではなく、プッシュ効果を与えます。また、tail(1)は、開始時に最後の1行を解析するだけです。したがって、タスクマネージャーがスクリプトを再起動する必要があると判断し、最後の行を置き換えてプレースホルダー行を挿入してアラートをトリガーする方法を見つけた場合、realertの煩わしさを解消できます。
エリック

1
エリック、DHCP(2012年にはPSコマンドレットがありますが、2008年にはありません)からリースをcsvファイルにエクスポートする方法を見つけました。このようにして、実際の監査ログを台無しにしたり、入力で何かを壊すことを心配したりする必要はありません。残りのコードを完成させ、すぐに更新することをいじり始めます。
-TheCleaner

1

イベントIDは確実であり、DHCPログでこのIDにログを記録するイベントは他にないが、関心のあるイベントはログに記録するという仮定の下では、プッシュは確かにオプションです。

1)サーバーマネージャーを開き、イベントビューアーでDHCPログに移動します。

2)アクションを添付する代表的なエントリを見つけます。それを選択して右クリックします。

3)[このイベントにタスクを添付]を選択します。

4)タスク作成ウィザードが開き、そこから削除します...

実際には明示的な電子メールオプションがありますが、それ以上のロジックが必要な場合は、もちろんプログラム起動オプションを使用してpowershell.exeを起動し、それにスクリプトを添付してください。ガイダンスが必要な場合に、タスクマネージャーにPowerShellスクリプトを実行させる方法については、グーグルで検索できる優れた方法がたくさんあります。

私が見る直接的な代替案は、スケジュールされた間隔でpowershellを使用してイベントログを解析することでプルを使用することです。エドウィルソンとして知られる「Microsoft Scripting Guy」は、さまざまなバージョンのPowerShellで使用可能なコマンドレットを使用してイベントログを解析する方法に関する素晴らしいブログ記事をいくつか書いています。

実際のコマンドレットに関しては、現時点で便利なスニペットを取り出す時間はありませんが、1〜2日後にもう一度調べて、他の誰かが適切に選択したものや、すべて自分で解決したわけではありません:-)


2
エリック、ありがとう。ここでの問題は、C:\ windows \ system32 \ DHCPのDHCPsrvlog- "day"(DHCPサーバーGUIでDHCP監査が有効になっている)が、DHCPサーバーイベントビューアーログを含むイベントビューアーログに書き込まないことです。Applications and Services Logs(これまでのところ私の研究/テストに基づいて)
TheCleaner

それらのログを忘れていました。しかし、これは可能性のある場所だと思います:get-contentと-waitおよび-tailディレクティブを使用してテキストログを解析します。これは* nixのtailに似ています。インスタンスが常にログを解析していることを確認するために、タスクマネージャーは、システムの起動時にスクリプトをスケジュールし、すべて(可能な限り最短の間隔)を開始できますが、実行中のインスタンスは1つのみ許可します。イベントが表示されたら、ロジックを起動します。
エリック

私はWindowsで解決する同様のログ解析問題を抱えていることが判明しました。それがうまくいくと確信したときにその特定の部分に私の調査結果を投稿します。dhcpログから、代表的だが難読化された行をいくつか貼り付けていただけますか?特にデバイス名の形式に興味があります。
エリック

1

これは望ましい解決策にはなりませんが、目標を達成する可能性のあるオプションは、ネットワーク上に新しい(以前は見えなかった)ホストが見つかったときに通知するarpwatchリンク)ことです。

Windowsの代替品はカフェイン抜きであるようにarpwatch見えますが、私はそれを使用したことがないため、良いか悪いかを話すことができません。


ありがとう。そこにあるアイデアは音です。必要に応じて、その道を行くことがあります。
-TheCleaner

追加の利点は、静的IPを使用する新しいマシンをキャッチすることです。これは、指定された範囲内ではありませんでしたが、おそらくそうであるはずです。
mfinni
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.