15 votos

DHCP de Windows Server - recibir notificación cuando un no-AD se unió dispositivo tiene una dirección IP

ESCENARIO

Para simplificar esto a que es más fácil de ejemplo:

Tengo un Windows 2008 R2 standard DC con la función de servidor DHCP. Manos fuera IPs a través de diversos IPv4 ámbitos, no hay ningún problema.

LO QUE ME GUSTARÍA

Me gustaría una forma de crear una notificación/entrada de registro de sucesos/similar cuando un dispositivo recibe una dirección DHCP contrato de arrendamiento y que el dispositivo NO ES un dominio de equipo en Active Directory. No me importa si es costumbre de Powershell, etc.

Línea de fondo = me gustaría saber cuando no sea de dominio dispositivos en la red sin necesidad de utilizar 802.1 X en el momento. Sé que esto no cuenta para IP estática dispositivos. Tengo software de monitoreo que va a escanear la red y encontrar los dispositivos, pero no es este granular en detalle.

LA INVESTIGACIÓN REALIZADA/OPCIONES CONSIDERADAS

Yo no veo ninguna tales posibilidades con el construido en el registro.

Sí, soy consciente de 802.1 X y tiene la capacidad de implementar a largo plazo en este hotel, pero estamos lejos de un proyecto como este, y mientras que iba a resolver los problemas de autenticación de red, esto es todavía útil para mí fuera de 802.1 X objetivos.

He miró a su alrededor buscando algún script, bits, etc. que podría resultar útil, pero las cosas que me voy encontrando me llevan a creer que mi google-fu se me fallaba en el momento.

Creo que la continuación lógica de sonido (asumiendo que no existe alguna solución existente):

  1. El dispositivo recibe la dirección DHCP
  2. Entrada de registro de eventos se registra (ID de evento 10 en el DHCP del registro de auditoría debería funcionar (ya que un nuevo contrato de arrendamiento es lo que me gustaría estar más interesados en el, no renovaciones): http://technet.microsoft.com/en-us/library/dd759178.aspx)
  3. En este punto, un guión de algún tipo probablemente tendría que asumir para el resto de los "PASOS" a continuación.
  4. De alguna manera, la consulta de este registro de DHCP para estos ID de evento 10 (me encantaría empuje, pero supongo que tire es el único recurso de aquí)
  5. Analizar la consulta por el nombre del dispositivo al que se asigna el nuevo contrato de arrendamiento
  6. Consulta de ANUNCIOS para el nombre del dispositivo
  7. SI no se encuentran en el año, enviar un correo electrónico de notificación

Si alguien tiene alguna idea sobre la manera correcta de hacer esto, realmente lo apreciaría. Yo no estoy buscando un "dame el codez" pero quisiera saber si hay alternativas a la lista anterior, o si no estoy pensamiento claro y existe otro método para la recopilación de esta información. Si usted tiene fragmentos de código/comandos PS te gustaría compartir para ayudar a lograr esto, mejor que mejor.

6voto

TheCleaner Puntos 22495

Con mucho gracias a ErikE y los demás aquí, me he ido por un camino...no voy a decir que es el camino correcto, pero el script de Powershell que he dado con el truco.

El código es el siguiente por si alguien lo quiere. Sólo tiene que ejecutar manualmente señalando a cada servidor DHCP o el horario (de nuevo apuntando a cada servidor DHCP en la secuencia de comandos).

Lo que hace el script:

  1. Obtiene la información de la concesión del servidor DHCP (ipv4 arrendamientos)
  2. Las salidas de los contratos de arrendamiento a un archivo csv
  3. Lee de vuelta en el archivo CSV para realizar consultas AD
  4. Consultas AD para el equipo
  5. Si no encuentra salidas a un nuevo archivo txt
  6. Crea una lista única definitiva archivo txt a partir de la creada en el #5 arriba (ya que no puede ser incautos si el cliente se registra más de una vez o con más de un adaptador)
  7. los correos electrónicos de los contenidos del archivo de salida final a un administrador

Lo que necesitas:

La secuencia de comandos utiliza el ANUNCIO del módulo (import-module activedirectory) así que lo mejor es correr en un ANUNCIO de DC ejecución de DHCP. Si este no es el caso para usted, usted puede instalar el AD módulo de powershell: http://blogs.msdn.com/b/rkramesh/archive/2012/01/17/how-to-add-active-directory-module-in-powershell-in-windows-7.aspx

Usted también necesitará Búsqueda de ANUNCIOS de cmdlets de Powershell encontrar aquí: http://www.quest.com/powershell/activeroles-server.aspx . Instalar ESTOS ANTES de ejecutar la secuencia de comandos o se producirá un error.

El guión en sí (desinfectado, usted tendrá que configurar algunas de las variables para adaptarse a sus necesidades como el archivo de entrada de nombres de dominio para conectarse, el servidor dhcp para conectarse a, configuración de correo electrónico, cerca del final, etc.):

# 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)

Espero que ayude a alguien más!

3voto

ErikE Puntos 2371

OK, no estoy seguro de Im siguiente etiqueta aquí, pero estoy publicando una segunda respuesta en lugar de editar mi anterior, como lo hizo contener algo de información que puede ser de utilidad para alguien, incluso si se prueba que es irrelevante para este caso. Si eso me convierte en un idiota en este foro dude en informarme de mis caminos equivocados.

El problema se divide en varias partes, aquí hay algunas sugerencias para los que me parecen más interesantes. Sin ejemplos del registro de esta es la mejor que puedo hacer, así que es sólo sugerencias, no soluciones.

Para analizar el uso de registro de get-content con la -wait parámetro. Para mi caso de uso es suficiente para encontrar un error en un log de errores.

Esto es lo que funcionó para mi propia caso de uso, perdona el formato:

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: $_" `
        }

En lugar de la $_ -match "ERROR" usted necesita para separar el registro de IDENTIFICACIÓN de campo y el nombre de equipo de alguna manera. No estoy seguro de cómo ir sobre esto de la mejor manera, pero desde where-object -match da soporte regex supongo que podría ser una opción. Usted también podría comenzar a almacenar la variable $_ en otra nueva variable, para ser capaz de recogerlo en su comodidad, más tarde en la tubería, anidada dentro de bucles foreach etc.

Suponiendo que usted puede conseguir en el ordenador, supongo que el get-adcomputer cmdlet sería la forma más sencilla de consultar su ANUNCIO (import-module activedirectory), y supongo que en el error de enviar el correo?

El uso de la import-csv sería, por supuesto, mucho más elegante en su caso, pero no soy consciente de ninguna manera de seguir a la cola (si alguien pasa a leer esto y sabe un truco que callejón, a continuación, por favor, por favor compartir).

1voto

ErikE Puntos 2371

Bajo el supuesto de que usted está seguro de que el IDENTIFICADOR de Evento, y que ningún otro registro de eventos para este ID en el registro de DHCP, pero los que usted está interesado en, el empuje es de hecho una opción.

1) Abra el Administrador del Servidor, vaya al registro de DHCP en el Visor de Sucesos.

2) Encontrar un representante de la entrada que desea adjuntar a su acción. Selecciónelo y haga clic derecho.

3) Seleccione La Opción "Adjuntar Tarea Para Este Evento".

4) La Creación de la Tarea, se abre el Asistente, llevarlo lejos de allí...

En realidad, hay una explícita opción de correo electrónico, pero si usted necesita más lógica que la que por supuesto son libres de utilizar el inicio de un programa de opción de que el fuego de powershell.exe y adjuntar una secuencia de comandos. Hay un montón de excelentes googleable tutoriales sobre cómo permitir que el Administrador de Tareas de ejecutar scripts de powershell si usted necesita orientación.

La recta de distancia alternativa que yo veo es el uso de la extracción de analizar el Registro de Sucesos del uso de powershell en intervalos programados. "Microsoft Scripting", alias Ed Wilson ha escrito algunas impresionante entradas de blog sobre cómo analizar el Registro de Sucesos de usar los cmdlets disponibles en las diferentes versiones de powershell, de modo de tomar su blog como un punto de partida sería mi sugerencia.

Como para el real cmdlets no tengo el tiempo ahora para sacar mi escondite de la mano de fragmentos, pero será en otra vez en un día o dos y puede contribuir si nadie ha puesto en con algunos bien elegidos, o te has solucionado lo de todo por ti mismo :-)

1voto

fukawi2 Puntos 3522

Mientras esto no abordar su solución deseada, una opción que puede lograr su objetivo es utilizar arpwatch(enlace) para que le notifique cuando un nuevo (nunca antes visto) host es visto en la red.

Windows alternativa a arpwatch parece ser decaffeinatid pero nunca la he utilizado, así que no puede hablar por que es bueno o malo.

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: