понедельник, 12 октября 2015 г.

Скрипт Powershell для сканирование сети

  Задача: скрипт на Powershell должен пройтись по всем IP адресам подсети. И собрать в текстовый файл для каждого хоста  - IP, аппаратный адрес, NetBIOS-имя и группу, DNS-имя. Когда-то я уже создал Linux-скрипт для сбора статистики сети. И теперь надо его переделать его под Windows.
  Все функции этого скрипта я уже подробно описал в статьях как получить аппаратный адрес компьютера в сети, как найти NetBIOS имя и группу удаленного компьютера и как получить DNS-имя хоста.
  Если вы будете адаптировать этот скрипт к своей подсети, то в основном теле скрипт проходится по диапазону IP адресов 192.168.0.1 - 192.168.0.254


#Файл scannet.ps1 
#http://www.nastroj-comp.ru
#Сценарий последовательно сканирует IP подсеть и выдает таблицу:
#MAC-адрес сетевой карты, IP-адрес компа,
#NETBIOS-имя компа, NETBIOS-группа компа,
#DNS-адрес связанный с этим именем
#Результат выводится на экран

Function Get-MAC ($IP) {
  $This_IP=((Get-NetIPConfiguration).IPv4Address).IPv4Address
  if ($IP -eq $This_IP) {
    $InterfaceAlias=(Get-NetIPConfiguration).InterfaceAlias
    $This_HWAddr=(Get-NetAdapter | Where-Object{$_.ifAlias -eq $InterfaceAlias}).MACAddress
    #$This_HWAddr=(Get-NetAdapter).MACAddress | Select-Object -First 1
    $HW_Addr=$This_HWAddr
  } else {
    ping -4 -n 1 -w 2000 $IP > $Null
    $Cmd_Arp_Out=arp -a | Where-Object {$_.Contains("$IP ")}
    if ($Cmd_Arp_Out -ne $NULL) {
      $HW_Addr=$Cmd_Arp_Out.Substring(24,17)
    }
  }
  $HW_Addr
}#Get-MAC

Function Get-DNSName ($IP) {
  (Resolve-DnsName -Name $IP -ErrorAction SilentlyContinue).NameHost
}

Function Get-NBTNames ($IP) {
  $NETBIOS_Name=""
  $NETBIOS_Group=""
  $Cmd_Nbtstat_Out=nbtstat -A $IP
  if ( ($Cmd_Nbtstat_Out | Select-String(" <00> ")).Count -gt 0) {
    $NETBIOS_Name=$Cmd_Nbtstat_Out  | Where-Object {$_.Contains("<00>  Уникальный")} | Select-Object -First 1
    if($NETBIOS_Name -ne $NULL) {
      $NETBIOS_Name=$NETBIOS_Name.Substring(4,15)
      $NETBIOS_Group=($Cmd_Nbtstat_Out | Where-Object {$_.Contains("<00>  Группа")} | Select-Object -First 1)
      if($NETBIOS_Group -ne $NULL) {
        $NETBIOS_Group=$NETBIOS_Group.Substring(4,15)
      } else {
        $NETBIOS_Group="---------------"
      }
    } else {
      $NETBIOS_Name="---------------"
    }
  } else {
    $NETBIOS_Name="---------------"
    $NETBIOS_Group="---------------" 
  }
  $NETBIOS_Name
  $NETBIOS_Group
}

Function ScanHost ($IP,$LogFullPath=$Null) {
  $MAC_Address=Get-MAC($IP)
  if ($MAC_Address -ne $Null) {
    $NETBIOS_Names=Get-NBTNames($IP)
    $DNS_Name=Get-DNSName($IP)
    "$MAC_Address $IP $NETBIOS_Names $DNS_Name"
  }
}

"HW_Address        IP        NETBIOS_Names NETBIOS_Group   DNS_Name"
 

#Эта часть скрипта проходит по диапазону IP 192.168.0.1 - 192.168.0.254

$i1=192
$i2=168
$i3=0
For ($i4=1; $i4 -le 254; $i4++) {
  ScanHost "$i1.$i2.$i3.$i4"
}


#----- Конец скрипта scannet.ps1 -----

  Чтобы автоматизировать процесс сканирования сети я создал скрипт scannet_cron.ps1 для запуска из планировщика. Как настроить планировщик заданий Windows для запуска Powershell-скрипта я уже писал.
  Этот скрипт в качестве параметра получает папку куда надо записать файл результата, дает этому файлу имя с текущей датой и временем до миллисекунды.

#Файл scannet_cron.ps1
#http://www.nastroj-comp.ru
#Скрипт запускается из планировщика
#В параметре получает папку куда записывает файл результата
#Файл результата имеет имя дата_время_милисекунды.log

Param ($LogPath)

$LogFile=Get-Date -Format yyyy_MM_dd_hh_mm_ss_FFFFFFF

if ($LogPath -ne $Null) {
  $LogFullPath=$LogPath + "\" + $LogFile + ".log"
} else {
  $LogFullPath=".\" + $LogFile + ".log"
}
C:\scannet.ps1 > $LogFullPath 


#----- Конец скрипта scannet_cron.ps1 -----

3 комментария:

  1. Спасибо за скрипт, прекрасно работает в сети. Показывает все устройства, которые включены в текущее время. Вопрос как реализовать, чтобы он выводил только не все устройства, а только включённые компьютеры. TTL компьютеров равен 125. Сможете посмочь? в Powershell не силён, в батнике понятно как, а powershell не знаю

    ОтветитьУдалить
    Ответы
    1. В фенкции Get-Mac код между " } else {"
      и "}#Get-MAC" должен выглядеть так:
      } else {
      $ExpectedTTL = 125 #Нам нужен только этот ТТЛ
      $TTL = (Test-Connection -Count 1 $IP).ResponseTimeToLive
      if($TTL -eq $ExpectedTTL){
      $Cmd_Arp_Out=arp -a | Where-Object {$_.Contains("$IP ")}
      if ($Cmd_Arp_Out -ne $NULL) {
      $HW_Addr=$Cmd_Arp_Out.Substring(24,17)
      }
      }
      $HW_Addr
      }#Get-MAC

      Два момента:
      1. У меня сегодня нет возможности проверить этот код.
      2. Если в брандмауэре на компе отключет ответ на ping, то такой комп скрипт не заметит

      Удалить
    2. После $HW_Addr забыл поставить }
      Код должен выглядеть так:
      } else {
      $ExpectedTTL = 125 #Нам нужен только этот ТТЛ
      $TTL = (Test-Connection -Count 1 $IP).ResponseTimeToLive
      if($TTL -eq $ExpectedTTL){
      $Cmd_Arp_Out=arp -a | Where-Object {$_.Contains("$IP ")}
      if ($Cmd_Arp_Out -ne $NULL) {
      $HW_Addr=$Cmd_Arp_Out.Substring(24,17)
      }
      }
      $HW_Addr
      }
      }#Get-MAC

      Удалить