場景:我進入了一個公司網路,需要自動執行一些網路檢查。其中之一是驗證特定埠是否沒有被防火墻阻止,但通常沒有服務偵聽遠程機器上的這些埠,并且根據我的理解,Test-NetConnection 和 portqry,如果沒有回應,則回傳 false/filtered另一邊,但實際上并不意味著防火墻阻止了埠,對嗎?
思路:我先用Test-NetConnection看看有沒有回復,這樣測驗就ok了。如果遠程端沒有在埠上回應:
- 我創建了一個 TCPClient 物件
- 向遠程計算機呼叫 ScriptBlock 以在特定埠上創建偵聽器
- 嘗試從源計算機連接到目標,這樣我就可以確定埠是打開的
到目前為止,這是我想出的:
function Test-Port([string] $server, [int] $port) {
$out = $false;
if(Test-NetConnection -ComputerName $server -Port $port | Select-Object -ExpandProperty TcpTestSucceeded) {
$out = $true;
} else {
$TcpClient = New-Object System.Net.Sockets.TcpClient;
try {
$Session = New-PSSession -ComputerName $server -ErrorAction Stop;
if($null -ne $Session) {
$RemoteLastExitCode = Invoke-Command -Session $Session -ScriptBlock {
param($p)
try {
$Listener = [System.Net.Sockets.TcpListener]$p;
$Listener.Start();
while($true) {
$client = $Listener.AcceptTcpClient();
$client.Close();
Exit $p;
}
} catch [System.Net.Sockets.SocketException] {
Write-Host "Socket Error: $($_)";
} finally {
$Listener.Stop();
}
$LASTEXITCODE;
} -ArgumentList $port
try {
$TcpClient.Connect($server, $port);
} catch [System.Net.Sockets.SocketException] {
Write-Host "TCP Client Error: $($_)";
} finally {
if($RemoteLastExitCode -eq $port) { $out = $true; }
$TcpClient.Close();
}
}
} catch [System.Management.Automation.Remoting.PSRemotingTransportException] {
Write-Host "Error: Unable to open remote session to $($server). Skipping." -ForegroundColor Red;
} finally {
Remove-PSSession -Session $Session -ErrorAction SilentlyContinue;
}
}
return $out;
}
但是,它似乎不起作用。此外,當第一次之后再次運行時,我收到錯誤“通常只允許每個套接字地址(協議/網路地址/埠)的一次使用”。我想 Socket 偵聽器或 TCPClient 沒有正確關閉/停止。
我也不確定 Invoke-Command 是否阻止執行。我也嘗試使用 -AsJob 引數運行它,但埠測驗失敗。只是說,我做了一個手動測驗(登錄到目標計算機,創建一個監聽器并從源連接)以確保埠是打開的,以證明這個測驗應該回傳 True。
提前致謝。
uj5u.com熱心網友回復:
我有相同的東西,但對于 azure 作業簿,它可以幫助你 - 它會從你的訂閱中獲取所有公共 IP,并將 telnet 到 3389 和 1433 埠,如果打開 - 發送電子郵件。
workflow PortChecker
{
#RunAs account name
$connectionName = "AzureRunAsConnection"
#connect to azure subscription
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
$connectionResult = Connect-AzAccount -Tenant $servicePrincipalConnection.TenantID -ApplicationId $servicePrincipalConnection.ApplicationID -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint -ServicePrincipal
$exclude = "Not Assigned"
$publicIps = Get-AzPublicIpAddress | where -Property IpAddress -CNotMatch $exclude | Select -ExpandProperty IpAddress
function Test-Port
{
param
(
[Parameter(Position=0, Mandatory = $True, HelpMessage="Provide destination source", ValueFromPipeline = $true)]
$Address,
[Parameter(Position=1, Mandatory = $False, HelpMessage="Provide port numbers", ValueFromPipeline = $true)]
$Port
)
$ErrorActionPreference = "SilentlyContinue"
$Results = @()
ForEach ($A in $Address) {
$Object = New-Object PSCustomObject
$Object | Add-Member -MemberType NoteProperty -Name "Destination" -Value $A
ForEach ($P in $Port) {
try
{
$tcpClient = new-object Net.Sockets.TcpClient
$tcpClient.Connect("$A", $P)
$Object = "For IP: $Address Port $P is open"
}
catch
{
$Object = "For IP: $Address Port $P is closed"
}
finally
{
$tcpClient.Dispose()
}
$Results = $Object
}
If($Results){
$Results
}}}
$allinfo = foreach -parallel ($publicIps in $publicIps) {Test-Port $publicIps -Port 1433, 3389}
$username = "---"
$password = '---' | ConvertTo-SecureString -asPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($username,$password)
#write-output $allinfo
$alertIP = $allinfo | where-object {$_ -like '*open*'}
#write-output $alertIP
if ($allinfo -like '*open*') { Send-MailMessage -SmtpServer %email-server% -useSsl -Port 587 -Credential $cred -From %From% -To %to% -Subject "New open port detected" -Body "New open port detected $alertIP, please check the Azure Portal" }
else {}
}
uj5u.com熱心網友回復:
我終于得到了解決方案。我的問題是:
- 呼叫命令,即使是遠程的,也是執行阻塞的
- 如果無法建立連接,則 TCPListener 未關閉
- 我沒有正確回傳遠程呼叫命令執行的結果
這是一個作業版本,它執行以下操作:
- 使用 Test-NetConnection 檢查 $server 和 LISTENING 上的 $port 是否打開;
- 如果沒有,創建 TCPClient TCPListener
- 在啟動 TCPlistener 的遠程 $server 上啟動 Invoke-Command 作業,這樣我們就有了一個端點來測驗防火墻是否阻止了 $port;
- 嘗試將 TCPClient 連接到 $server 上的指定 $port
- 如果成功,則呼叫命令作業回傳埠號,否則為空;
- 如果沒有連接,TCPListener 將在 10 秒后關閉;
PS:在我的示例中,我查找已經存在的特定會話名稱,您可以更改該部分。
function Test-Port([string] $server, [int] $port) {
$out = $false;
if(Test-NetConnection -ComputerName $server -Port $port | Select-Object -ExpandProperty TcpTestSucceeded) {
$out = $true;
} else {
$removeSession = $false;
$TcpClient = New-Object System.Net.Sockets.TcpClient;
try {
$Session = Get-PSSession | Where-Object -FilterScript { $_.State -eq "Opened" -and ($_.Name -eq "$($env:COMPUTERNAME)$($server)" -or $_.Name -eq "$($server)$($env:COMPUTERNAME)") };
if($null -eq $Session) {
$Session = New-PSSession -ComputerName $server -ErrorAction Stop;
$removeSession = $true;
}
Invoke-Command -Session $Session -AsJob -JobName PortTest -ScriptBlock {
param($p)
$Script:return = $null;
try {
$IPAddress = Get-NetIPConfiguration | Where-Object -FilterScript { $null -ne $_.IPv4DefaultGateway } |
Select-Object -ExpandProperty IPv4Address | Select-Object -ExpandProperty IPAddress;
$Listener = [System.Net.Sockets.TcpListener]::new($IPAddress, $p);
$Listener.Start();
$counter = 0;
while($true) {
if(!$Listener.Pending()) {
if($counter -eq 20) {
$Listener.Stop();
break;
}
$counter ;
Start-Sleep -Milliseconds 500;
continue;
}
$client = $Listener.AcceptTcpClient();
$Script:return = $p;
$client.Close();
break;
}
} catch [System.Net.Sockets.SocketException] {
Write-Host "Socket Error: $($_)";
} finally {
$Listener.Stop();
}
return $Script:return;
} -ArgumentList $port
$TcpClient.ReceiveTimeout = 10000;
$TcpClient.SendTimeout = 10000;
$TcpClient.Connect($server, $port);
$RemoteReturn = Wait-Job -Name PortTest | Receive-Job;
} catch [System.Management.Automation.Remoting.PSRemotingTransportException] {
Write-Host "Error: Unable to open remote session to $($server). Skipping." -ForegroundColor Red;
} catch [System.Net.Sockets.SocketException] {
Write-Host "TCP Client Error: $($_)";
} finally {
if($RemoteReturn -eq $port) { $out = $true; }
$TcpClient.Close();
if($removeSession) { Remove-PSSession -Session $Session -ErrorAction SilentlyContinue; }
}
}
return $out;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/399978.html
