я пытаюсь использовать какой-то скрипт, который проверяет соединение NW между хостами, в основном у меня есть CSV с исходным IP-адресом и портом, который выглядит так
проблема в том, что когда я запускаю этот скрипт, он проверяет каждый IP-адрес для каждого порта, и мне нужно, чтобы он проверил порт onlu, который находится рядом с ним, то есть для 8.8.8.8 только порт 53, а для 1.1.1.1 только 443.
ниже мой код
$dest = Import-Csv "C:\temp\dest.csv"
#$dest | ft
$source = (Get-WmiObject Win32_Computersystem).name
Foreach ($d in $dest.SourceIP){
Foreach ($P in $dest.Port){
try{
$temp = new-object Net.Sockets.TcpClient
$temp.Connect("$d", $P)
if ($temp.Connected -eq $true){
Write-Host $P -ForegroundColor Green " => port is open from" $source "to" $d
}
}
catch {$theError =$_
if ($theError.Exception -like "*A connection attempt failed*"){
Write-Host $P -ForegroundColor Red "=> NO TRAFFIC between" $source "and" $d
}
elseif ($theError.Exception -like "*No connection could be made*"){
Write-Host $P -ForegroundColor Red "=> port is closed from" $source "to" $d
}
}
}
}
Я знаю, что проблема здесь в вложенном цикле, но у меня закончились идеи, как его изменить, чтобы он работал правильно.
Вы случайно используете что-то под названием «Перечисление доступа к членам» — $dest.SourceIP
извлекает массив, содержащий значения SourceIP
из всех строк, а $dest.Port
делает то же самое для свойства Port
. В результате ваши вложенные циклы foreach перебирают каждый порт для каждого SourceIP, что объясняет наблюдаемое вами поведение. См. Learn.microsoft.com/en-us/powershell/module/… для получения более подробной информации об этой функции (которую вы на самом деле не хотите здесь использовать!)
Это всего лишь идея... вы можете ускориться, группируя. Что-то вроде Group-object-property Port
Get-WmiObject
устарело. Использование Get-CimInstance
работает примерно так же.
И почему вложенный цикл на первом месте? Вы можете получить доступ к свойствам!
$source = (Get-CimInstance -ClassName Win32_Computersystem).Name
Foreach ($Address in $dest) {
$PortString = '{0,-5} => ' -f $Address.Port
try {
if ([System.Net.Sockets.TcpClient]::new($Address.SourceIP, $Address.Port).Connected) {
Write-Host -ForegroundColor Green $PortString 'port is open from' $source 'to' $Address.SourceIp
}
}
catch [System.Net.Sockets.SocketException] {
switch ($_.Exception.ErrorCode) {
10060 { Write-Host -ForegroundColor Red $PortString 'NO TRAFFIC between' $source 'and' $Address.SourceIp }
10061 { Write-Host -ForegroundColor Red $PortString 'port is closed from' $source 'to' $Address.SourceIp }
}
}
catch {
# generic error management
}
}
и если вы используете Powershell Core/7.x и вам нужно проверить много элементов, вы можете использовать Foreach-Object -Parallel
. Видеть:
$source = (Get-CimInstance -ClassName Win32_Computersystem).Name
Import-Csv -Path $CsvPath | ForEach-Object -Parallel {
# technically superfluous, but helps readibility.
$Address = $_
# necessary to access the out-of-scope $source varible.
# the local name could by anything, but I kept the same name for clarity.
$source = $using:source
$PortString = '{0,-5} => ' -f $Address.Port
try {
if ([System.Net.Sockets.TcpClient]::new($Address.SourceIP, $Address.Port).Connected) {
Write-Host -ForegroundColor Green $PortString 'port is open from' $source 'to' $Address.SourceIp
}
}
catch [System.Net.Sockets.SocketException] {
switch ($_.Exception.ErrorCode) {
10060 { Write-Host -ForegroundColor Red $PortString 'NO TRAFFIC between' $source 'and' $Address.SourceIp }
10061 { Write-Host -ForegroundColor Red $PortString 'port is closed from' $source 'to' $Address.SourceIp }
}
}
catch {
# generic error management
}
}
Очень хорошо. Возможно, вы захотите добавить отдельный блок catch [System.Net.Sockets.SocketException] {...}
и проверить значение $_.Exception.ErrorCode (чтобы избежать сравнения с локализованным сообщением об ошибке) - ошибка «не удалось установить соединение» будет иметь код 10060, «Не удалось установить соединение» 10061
@MathiasR.Jessen, кстати, спасибо за редактирование моего сообщения. И да, есть несколько способов улучшить сценарий. Я сосредоточился только на основной проблеме, которую действительно поднял ОП, - двойной петле. Я отредактировал свое решение с учетом ваших предложений и нескольких других улучшений (надеюсь)
Спасибо большое, это работает. Я использовал вложенные циклы, потому что ранее я проверял исходный IP-адрес или несколько IP-адресов, непосредственно предоставленных сценарию, и несколько портов, бот, эти порты были одинаковыми для всех IP-адресов, которые нужно было проверить. В любом случае, я заметил, что это не очень эффективный способ сделать это, поэтому я хотел изменить его на файлы csv, и даже если мне придется дублировать строки с IP, чтобы проверить еще несколько портов для того же адреса, это будет все равно лучший способ сделай это. Еще раз, спасибо
Если вы используете Powershell Core/7.x и вам нужно проверить много элементов, я добавил в свое решение вариант, использующий Foreach-Object -Parallel
, который позволит вам проверять несколько IP-адресов одновременно, что значительно ускоряет работу.
Прокрутите каждую строку таблицы has, используя: Foreach ($row in $dest){ } Проверка $row.SourceIP и $row.Port.