PowerShell Test-Port: 사용자 지정Shell 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 스크립트의 도움을 받아서 TCP 및 UDP 포트를 테스트할 뿐만 아니라 서버 역할별로 포트 그룹을 테스트할 수 있는 좋은 PowerShell 함수 쌍을 만들었습니다. 이제 무슨 서비스가 어떤 포트를 사용하는지 매번 구글링할 필요가 없습니다!

부여됨, 특히 Active Directory의 경우, 포트는 서버 OS, 도메인 컨트롤러의 다양한 서비스 등에 따라 다를 수 있습니다. 환경에 맞게 필요에 따라 조정해 주세요.

여기에 사용 예제의 화면 캡처가 있습니다:

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
		
		이 예제는 LABDC 및 LABDC2 서버에서 NetBIOS, WinRm 및 Dns가 작동하는 데 필요한 네트워크 포트를 테스트합니다.
	#>
	
	[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 포트 확인은 $true일 때 $false를 출력합니다. 이것이 왜 그런지는 알 수 없습니다.
	.PARAMETER Computername
		하나 이상의 원격 쉼표로 구분된 컴퓨터 이름
	.PARAMETER Port
		테스트하려는 하나 이상의 쉼표로 구분된 포트 번호
	.PARAMETER Protocol
		테스트할 프로토콜 (UDP 또는 TCP)
	.PARAMETER TcpTimeout
		함수가 TCP 포트를 닫힌 것으로 선언하기까지 대기하는 시간(밀리초)
	.PARAMETER UdpTimeout
		함수가 UDP 포트를 닫힌 것으로 선언하기까지 대기하는 시간(밀리초)
	.EXAMPLE
		PS> Test-Port -Computername 'LABDC','LABDC2' -Protocol TCP 80,443
		
		이 예제는 LABDC 및 LABDC2 서버의 TCP 네트워크 포트 80과 443을 테스트합니다.
	#>
	[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/