【问题标题】:How to check Network port access and display useful message?如何检查网络端口访问并显示有用的消息?
【发布时间】:2012-03-05 11:44:16
【问题描述】:

我正在尝试使用 powershell 来检查端口是否打开,如下所示。

(new-object Net.Sockets.TcpClient).Connect("10.45.23.109", 443)

此方法有效,但输出对用户不友好。这意味着如果没有错误,则它可以访问。有什么方法可以检查是否成功并显示诸如“端口 443 正在运行”之类的消息?

【问题讨论】:

标签: powershell port powershell-2.0 port-scanning


【解决方案1】:

如果您运行的是 Windows 8/Windows Server 2012 或更高版本,则可以在 PowerShell 中使用 Test-NetConnection 命令。

例如:

Test-NetConnection -Port 53 -ComputerName LON-DC1

【讨论】:

  • Test-NetConnection 仅适用于 Windows 8.x 和 Server 2012R2 及更高版本。
  • Test-NetConnection 在 PS 5 之前无法投反对票。
  • @Brettski 您的评论完全错误。刚刚在装有 PS4 的 Windows Server 2012 机器上进行了测试。但是,它是 NetTCPIP module 的一部分,在 Windows 7 和 Windows Server 2008 R2 及更低版本上不可用。
  • @jpmc26 啊,你是对的,它是一个 PowerShell 4 cmdlet。错误发生。已删除反对票。
【解决方案2】:

我从几个方面改进了 Salselvaprabu 的答案:

  1. 它现在是一个功能 - 您可以放入您的 powershell 配置文件并在需要时随时使用
  2. 它可以接受主机作为主机名或 IP 地址
  3. 如果主机或端口不可用,则不再有例外 - 只是文本

这样称呼它:

Test-Port example.com 999
Test-Port 192.168.0.1 80

function Test-Port($hostname, $port)
{
    # This works no matter in which form we get $host - hostname or ip address
    try {
        $ip = [System.Net.Dns]::GetHostAddresses($hostname) | 
            select-object IPAddressToString -expandproperty  IPAddressToString
        if($ip.GetType().Name -eq "Object[]")
        {
            #If we have several ip's for that address, let's take first one
            $ip = $ip[0]
        }
    } catch {
        Write-Host "Possibly $hostname is wrong hostname or IP"
        return
    }
    $t = New-Object Net.Sockets.TcpClient
    # We use Try\Catch to remove exception info from console if we can't connect
    try
    {
        $t.Connect($ip,$port)
    } catch {}

    if($t.Connected)
    {
        $t.Close()
        $msg = "Port $port is operational"
    }
    else
    {
        $msg = "Port $port on $ip is closed, "
        $msg += "You may need to contact your IT team to open it. "                                 
    }
    Write-Host $msg
}

【讨论】:

    【解决方案3】:

    实际上,Shay levy 的回答几乎是正确的,但正如我在他的评论栏中提到的那样,我遇到了一个奇怪的问题。所以我把命令分成两行,它工作正常。

    $Ipaddress= Read-Host "Enter the IP address:"
    $Port= Read-host "Enter the port number to access:"
    
    $t = New-Object Net.Sockets.TcpClient
    $t.Connect($Ipaddress,$Port)
        if($t.Connected)
        {
            "Port $Port is operational"
        }
        else
        {
            "Port $Port is closed, You may need to contact your IT team to open it. "
        }
    

    【讨论】:

      【解决方案4】:

      您可以检查 Connected 属性是否设置为 $true 并显示友好消息:

          $t = New-Object Net.Sockets.TcpClient "10.45.23.109", 443 
      
          if($t.Connected)
          {
              "Port 443 is operational"
          }
          else
          {
              "..."
          }
      

      【讨论】:

      • 伙计,我遇到了上述解决方案的奇怪问题。例如。我第一次使用端口 443 ,它失败并显示 else 部分字符串。然后我给出了可以访问的端口号( 80 )。如果部分字符串显示。我再次将端口号更改为 443 并显示如果部分字符串。 (它应该显示其他字符串)
      • 这足以得到真/假响应(New-Object Net.Sockets.TcpClient "10.45.23.109", 443).Connected
      【解决方案5】:

      在最新版本的 PowerShell 中,有一个新的 cmdlet,Test-NetConnection。

      这个 cmdlet 实际上让您可以 ping 一个端口,如下所示:

      Test-NetConnection -ComputerName <remote server> -Port nnnn
      

      我知道这是一个老问题,但如果您(像我一样)点击此页面查找此信息,此添加可能会有所帮助!

      【讨论】:

        【解决方案6】:

        我试图改进 mshutov 的建议。 我添加了将输出用作对象的选项。

         function Test-Port($hostname, $port)
            {
            # This works no matter in which form we get $host - hostname or ip address
            try {
                $ip = [System.Net.Dns]::GetHostAddresses($hostname) | 
                    select-object IPAddressToString -expandproperty  IPAddressToString
                if($ip.GetType().Name -eq "Object[]")
                {
                    #If we have several ip's for that address, let's take first one
                    $ip = $ip[0]
                }
            } catch {
                Write-Host "Possibly $hostname is wrong hostname or IP"
                return
            }
            $t = New-Object Net.Sockets.TcpClient
            # We use Try\Catch to remove exception info from console if we can't connect
            try
            {
                $t.Connect($ip,$port)
            } catch {}
        
            if($t.Connected)
            {
                $t.Close()
                $object = [pscustomobject] @{
                                Hostname = $hostname
                                IP = $IP
                                TCPPort = $port
                                GetResponse = $True }
                Write-Output $object
            }
            else
            {
                $object = [pscustomobject] @{
                                Computername = $IP
                                TCPPort = $port
                                GetResponse = $False }
                Write-Output $object
        
            }
            Write-Host $msg
        }
        

        【讨论】:

          【解决方案7】:

          如果您使用的是旧版本的 Powershell,其中 Test-NetConnection 不可用,这里是主机名“my.hostname”和端口“123”的单行:

          $t = New-Object System.Net.Sockets.TcpClient 'my.hostname', 123; if($t.Connected) {"OK"}
          

          返回 OK 或错误消息。

          【讨论】:

            【解决方案8】:

            mshutov 和 Salselvaprabu 的出色回答。我需要一些更健壮的东西,它会检查所有提供的 IPAddress,而不是只检查第一个。

            我还想复制一些参数名称和功能,而不是 Test-Connection 函数。

            这个新功能允许您设置重试次数的计数,以及每次尝试之间的延迟。尽情享受吧!

            function Test-Port {
            
                [CmdletBinding()]
                Param (
                    [string] $ComputerName,
                    [int] $Port,
                    [int] $Delay = 1,
                    [int] $Count = 3
                )
            
                function Test-TcpClient ($IPAddress, $Port) {
            
                    $TcpClient = New-Object Net.Sockets.TcpClient
                    Try { $TcpClient.Connect($IPAddress, $Port) } Catch {}
            
                    If ($TcpClient.Connected) { $TcpClient.Close(); Return $True }
                    Return $False
            
                }
            
                function Invoke-Test ($ComputerName, $Port) {
            
                    Try   { [array]$IPAddress = [System.Net.Dns]::GetHostAddresses($ComputerName) | Select-Object -Expand IPAddressToString } 
                    Catch { Return $False }
            
                    [array]$Results = $IPAddress | % { Test-TcpClient -IPAddress $_ -Port $Port }
                    If ($Results -contains $True) { Return $True } Else { Return $False }
            
                }
            
                for ($i = 1; ((Invoke-Test -ComputerName $ComputerName -Port $Port) -ne $True); $i++)
                {
                    if ($i -ge $Count) {
                        Write-Warning "Timed out while waiting for port $Port to be open on $ComputerName!"
                        Return $false
                    }
            
                    Write-Warning "Port $Port not open, retrying..."
                    Sleep $Delay
                }
            
                Return $true
            
            }
            

            【讨论】:

              【解决方案9】:

              将其归结为一个行将变量“$port389Open”设置为 True 或 false - 它可以快速且轻松地复制到端口列表

              try{$socket = New-Object Net.Sockets.TcpClient($ipAddress,389);if($socket -eq $null){$Port389Open = $false}else{Port389Open = $true;$socket.close()}}catch{Port389Open = $false}
              

              如果你不想真正发疯,你可以返回整个数组-

              Function StdPorts($ip){
                  $rst = "" |  select IP,Port547Open,Port135Open,Port3389Open,Port389Open,Port53Open
                  $rst.IP = $Ip
                  try{$socket = New-Object Net.Sockets.TcpClient($ip,389);if($socket -eq $null){$rst.Port389Open = $false}else{$rst.Port389Open = $true;$socket.close();$ipscore++}}catch{$rst.Port389Open = $false}
                  try{$socket = New-Object Net.Sockets.TcpClient($ip,53);if($socket -eq $null){$rst.Port53Open = $false}else{$rst.Port53Open = $true;$socket.close();$ipscore++}}catch{$rst.Port53Open = $false}
                  try{$socket = New-Object Net.Sockets.TcpClient($ip,3389);if($socket -eq $null){$rst.Port3389Open = $false}else{$rst.Port3389Open = $true;$socket.close();$ipscore++}}catch{$rst.Port3389Open = $false}
                  try{$socket = New-Object Net.Sockets.TcpClient($ip,547);if($socket -eq $null){$rst.Port547Open = $false}else{$rst.Port547Open = $true;$socket.close();$ipscore++}}catch{$rst.Port547Open = $false}
                  try{$socket = New-Object Net.Sockets.TcpClient($ip,135);if($socket -eq $null){$rst.Port135Open = $false}else{$rst.Port135Open = $true;$socket.close();$SkipWMI = $False;$ipscore++}}catch{$rst.Port135Open = $false}
                  Return $rst
              }
              

              【讨论】:

                【解决方案10】:

                扫描关闭的端口时,它会长时间无响应。将 fqdn 解析为 ip 时似乎更快:

                [System.Net.Dns]::GetHostAddresses("www.msn.com").IPAddressToString
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2016-05-17
                  • 2013-10-12
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-07-03
                  • 1970-01-01
                  • 2016-07-09
                  相关资源
                  最近更新 更多