כלי מותאם PowerShell Test-Port: מדריך

בואו נתעמ淓票融弓? 艇 לבנות כלי בדיקת יציבת פתח PowerShell שמאפשר לך לבדוק פתחים פתוחים לפי מספר פתח ותווית.

כדי לבנות סקריפט יציב שלא יתקע וימות חצי דרך בשרתים שלך, חשוב לוודא תחילה שהדרישות המקדימות הקיימות לך לקבלת התוצאה הסופית נעמדות.

מהם אלו הדרישות המקדימות? הדרישות המקדימות הן שירותים כמו FTP, HTTP, DCOM, WMI, WSMAN וכו '. החיבור שאתה מנסה ליצור לשרת תלוי נפרדות בשירותים כאלה.

יש היררכיה של מספר שכבות של בדיקות שאתה יכול לבצע על השרתים שלך לפני שאתה מנסה ליצור חיבור בהתאם לכמה אתה רוצה להיות מפרט.

למתחילים, יש לך את כל מחסנית ה-OSI לעבור מצד הרשת. זה לא כולל שירותים במערכת המארח שאתה מפעיל את התסריט ממנה והכל יתרה מהמערכת המארחת המרוחקת.

אחת מהבדיקות הראשוניות שעליך לבצע כשאתה שואל שרת מרוחק היא לוודא שהפתחים הרשתיים המתאימים פתוחים וזמינים. תלוי בשירותים שרצים על השרת המרוחק, תלוי בפתחים שעליך לשאול.

I always used to either not even attempting to test port connections or fumbling around with finding that latest Test-Port script I had scavenged somewhere. Once I found it to figure out what ports I actually needed to a test ahead of time. Today was the final straw.

I needed to query a set of domain controllers before running some CIM queries against them. I went about my normal fumbling around and decided enough was enough and sat down and built my own, fully featured port testing script.

עם עזרה מתסריט של Technet, הצלחתי ליצור זוג פונקציות PowerShell נחמדות שלא רק יאפשרו לך לבדוק פתחים TCP ו-UDP פתוחים אלא גם לבדוק קבוצות פתחים לפי תפקיד השרת. סיום לחיפוש בכל פעם לאילו פתחים שירות משתמש!

ניתן, במיוחד עבור Active Directory, הימנעות מפתחי יציאה יכולה להשתנות לפי מערכת ההפעלה של השרת, שירותים שונים בשרת בדומיין וכו'. ניתן לשנות אותם ככל הצורך למצב הסביבתי שלך.

כאן מסך של דוגמה לשימוש:

Testing ports with PowerShell

כפי שתוכל לראות, ניתן לציין כמה שרתים שתרצה והוא יפיק רשימה נעימה של אובייקטים המחולקים לפי קבוצת פורט שירות ולכל מחשב פורט. עד כה היה מאוד שימושי! מקווה שתיהנה ממנו כמו שעשיתי!

function Test-ServerRolePortGroup {
	<#
    .SYNOPSIS
        פונקציה זו בודקת פתחי TCP/UDP פתוחים לפי תפקיד השרת.
    .DESCRIPTION
        פונקציה זו בודקת את כל פתחי הTCP/UDP המתאימים לפי תפקיד השרת כך שאין צורך
        לשמור או לחפש את כל פתחי הפתוחים בכל פעם
        שברצונך לאמת תקינות מחברות מרחוק בתפקיד שרת מסוים.
    .NOTES
        קישורים לפתחי פורט:
        http://technet.microsoft.com/en-us/library/dd772723(v=ws.10).aspx
        http://en.wikipedia.org/wiki/Server_Message_Block
        http://technet.microsoft.com/en-us/library/cc940063.aspx
    .PARAMETER Computername
        שם המחשב או מספר מחשבים מרוחקים, מופרדים בפסיקים
    .PARAMETER ServerRole
        השירותים במחשב שברצונך למצוא פתחי פתוחים עבורם. זה יכול להיות
        שירותים נפוצים כמו WinRm, Smb, Dns, Active Directory ו-NetBIOS
    .EXAMPLE
        PS> Test-ServerRolePortGroup -Computername 'LABDC','LABDC2' -ServerRole NetBIOS,WinRm,Dns
        
        בדיקת פורטים הרשת הדרושים עבור NetBIOS, WinRm ו-Dns
        לפעולה בשרתים LABDC ו-LABDC2.
#>
	
	[CmdletBinding()]
	[OutputType([System.Management.Automation.PSCustomObject])]
	param (
		[Parameter(Mandatory)]
		[ValidateScript({ Test-Connection -ComputerName $_ -Count 1 -Quiet})]
		[string[]]$Computername,
		[Parameter(Mandatory)]
		[ValidateSet('WinRm','Smb','Dns','ActiveDirectoryGeneral','ActiveDirectoryGlobalCatalog','NetBios')]
		[string[]]$ServerRole
	)
	begin {
		$PortGroups = @{
			'WinRm' = @{ 'TCP' = 5985}
			'Smb' = @{ 'TCP' = 445; 'UDP' = 445 }
			'Dns' = @{ 'TCP' = 53; 'UDP' = 53 }
			'ActiveDirectoryGeneral' = @{ 'TCP' = 25, 88, 389, 464, 636, 5722, 9389; 'UDP' = 88,123,389,464 }
			'ActiveDirectoryGlobalCatalog' = @{ 'TCP' = 3268, 3269 }
			'NetBios' = @{ 'TCP' = 135, 137, 138, 139; 'UDP' = 137,138,139 }
		}
	}
	process {
		foreach ($Computer in $Computername) {
			Write-Verbose "Beginning port tests on computer '$Computer'"
			try {
				$TestPortGroups = $PortGroups.GetEnumerator() | where { $ServerRole -contains $_.Key }
				Write-Verbose "Found '$($TestPortGroups.Count)' port group(s) to test"
				foreach ($PortGroup in $TestPortGroups) {
					$PortGroupName = $PortGroup.Key
					$PortGroupValues = $PortGroup.Value
					foreach ($Value in $PortGroupValues.GetEnumerator()) {
						$Protocol = $Value.Key
						$Ports = $Value.Value
						$TestResult = Test-Port -ComputerName $Computer -Protocol $Protocol -Port $Ports
						$TestResult | Add-Member -MemberType 'NoteProperty' -Name 'PortSet' -Value $PortGroupName
						$TestResult
					}
				}
			} catch {
				Write-Verbose "$($MyInvocation.MyCommand.Name) - Computer: $Computer - Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)"
				$false
			}
		}
	}
}

function Test-Port {
	<#
    .SYNOPSIS
        פונקציה זו בודקת פתחי TCP/UDP פתוחים.
    .DESCRIPTION
        פונקציה זו בודקת כל פתח TCP/UDP כדי לראות האם הוא פתוח או סגור.
    .NOTES
        בעיה ידועה: אם פונקציה זו נקראת בתוך 10-20 קריאות רצופות לאותו פורט
            ומחשב, בדיקת ה-UDP תחזיר $false כאשר היא יכולה
            להיות $true. עדיין לא הצלחתי להבין למה זה קורה.
    .PARAMETER Computername
        שם המחשב או מספר מחשבים מרוחקים, מופרדים בפסיקים
    .PARAMETER Port
        מספרי פורט אחד או יותר, מופרדים בפסיקים, שברצונך לבדוק.
    .PARAMETER Protocol
        הפרוטוקול (UDP או TCP) שבו תבצע בדיקה
    .PARAMETER TcpTimeout
        מספר המילי-שניות שהפונקציה תמתין עד להכרזה
        שהפורט TCP סגור.
    .PARAMETER
        מספר המילי-שניות שהפונקציה תמתין עד להכרזה
        שהפורט UDP סגור.
    .EXAMPLE
        PS> Test-Port -Computername 'LABDC','LABDC2' -Protocol TCP 80,443
        
        בדיקת פורטי הרשת TCP 80 ו-443 על שרתי LABDC
        ו-LABDC2.
#>
	[CmdletBinding(DefaultParameterSetName='TCP')]
	[OutputType([System.Management.Automation.PSCustomObject])]
	param (
		[Parameter(Mandatory)]
		[string[]]$ComputerName,
		[Parameter(Mandatory)]
		[int[]]$Port,
		[Parameter(Mandatory)]
		[ValidateSet('TCP', 'UDP')]
		[string]$Protocol,
		[Parameter(ParameterSetName='TCP')]
		[int]$TcpTimeout = 1000,
		[Parameter(ParameterSetName = 'UDP')]
		[int]$UdpTimeout = 1000
	)
	process {
		foreach ($Computer in $ComputerName) {
			foreach ($Portx in $Port) {
				$Output = @{ 'Computername' = $Computer; 'Port' = $Portx; 'Protocol' = $Protocol; 'Result' = '' }
				Write-Verbose "$($MyInvocation.MyCommand.Name) - Beginning port test on '$Computer' on port '$Protocol<code>:$Portx'"
				if ($Protocol -eq 'TCP') {
					$TcpClient = New-Object System.Net.Sockets.TcpClient
					$Connect = $TcpClient.BeginConnect($Computer, $Portx, $null, $null)
					$Wait = $Connect.AsyncWaitHandle.WaitOne($TcpTimeout, $false)
					if (!$Wait) {
						$TcpClient.Close()
						Write-Verbose "$($MyInvocation.MyCommand.Name) - '$Computer' failed port test on port '$Protocol</code>:$Portx'"
						$Output.Result = $false
					} else {
						$TcpClient.EndConnect($Connect)
						$TcpClient.Close()
						Write-Verbose "$($MyInvocation.MyCommand.Name) - '$Computer' passed port test on port '$Protocol<code>:$Portx'"
						$Output.Result = $true
					}
					$TcpClient.Close()
					$TcpClient.Dispose()
				} elseif ($Protocol -eq 'UDP') {
					$UdpClient = New-Object System.Net.Sockets.UdpClient
					$UdpClient.Client.ReceiveTimeout = $UdpTimeout
					$UdpClient.Connect($Computer, $Portx)
					Write-Verbose "$($MyInvocation.MyCommand.Name) - Sending UDP message to computer '$Computer' on port '$Portx'"
					$a = new-object system.text.asciiencoding
					$byte = $a.GetBytes("$(Get-Date)")
					[void]$UdpClient.Send($byte, $byte.length)
					#פריט IPEndPoint יאפשר לנו לקרוא דטגרמות שנשלחו מכל מקור.
					Write-Verbose "$($MyInvocation.MyCommand.Name) - Creating remote endpoint"
					$remoteendpoint = New-Object system.net.ipendpoint([system.net.ipaddress]::Any, 0)
					try {
						#מוחסן עד שהודעה תחזור על ידי התחברות מרחוק ממארח רחוק.
						Write-Verbose "$($MyInvocation.MyCommand.Name) - Waiting for message return"
						$receivebytes = $UdpClient.Receive([ref]$remoteendpoint)
						[string]$returndata = $a.GetString($receivebytes)
						If ($returndata) {
							Write-Verbose "$($MyInvocation.MyCommand.Name) - '$Computer' passed port test on port '$Protocol</code>:$Portx'"
							$Output.Result = $true
						}
					} catch {
						Write-Verbose "$($MyInvocation.MyCommand.Name) - '$Computer' failed port test on port '$Protocol`:$Portx' with error '$($_.Exception.Message)'"
						$Output.Result = $false
					}
					$UdpClient.Close()
					$UdpClient.Dispose()
				}
				[pscustomobject]$Output
			}
		}
	}
}

Source:
https://adamtheautomator.com/powershell-test-port/