25

On Machine A I am running a port scanner. On Machine B I would like to open and close ports in an organized fashion. I am hoping to do all of this via powershell.

I found THIS script to run on Machine B however when scanning the same port from Machine A it still says that it is closed.

Do any of you know how I can successfully open a port on Machine B

mhopkins321
  • 2,993
  • 15
  • 56
  • 83
  • It could help if you described the relationship between `Machine A` and `Machine B` (talking about network hierarchy here). – Victor Zakharov Oct 29 '12 at 20:31
  • `Machine A` is 10.0.0.20 and `Machine B` is 10.0.0.199 they are on the same domain. Does that explain what you were getting at sorta? – mhopkins321 Oct 29 '12 at 20:36
  • It certainly makes the life more simple. The further machines are from each other, the more factors you have to take into account when troubleshooting why it does not work. Check my updated answer. – Victor Zakharov Oct 29 '12 at 20:41

2 Answers2

56

Avoid COM if possible. You can use TcpListener to open a port:

$Listener = [System.Net.Sockets.TcpListener]9999;
$Listener.Start();
#wait, try connect from another PC etc.
$Listener.Stop();

If you happen to miss a Stop command during debugging - just close and re-open the application from where you opened the socket - hanging port should be cleared. In my case it was PowerGUI script editor.

Then use TcpClient to check it.

(new-object Net.Sockets.TcpClient).Connect($host, $port)

If you cannot connect, means the firewall is blocking it.

EDIT: To print a message when connection is received, you should be able to use this code (based on this article from MSDN):

#put this code in between Start and Stop calls.
while($true) 
{
    $client = $Listener.AcceptTcpClient();
    Write-Host "Connected!";
    $client.Close();
}
Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151
  • my goal here is to not have to touch the firewall. meaning, I need software that will open and close ports on the machine, that way, if I test the port and I get a rejection, I know it was due to the firewall, and not the machine – mhopkins321 Oct 29 '12 at 20:32
  • 1
    Sweet, I've been working a bit with tcpClient. I did just find out that ALL ports within the subnet are open. So a better example is `Machine A` is 10.0.0.199 and `Machine B` is 192.168.1.10 – mhopkins321 Oct 29 '12 at 21:09
  • hmmm, when I run the above script it ends instantly, I'm sure I'm missing something incredibly obvious... – mhopkins321 Oct 29 '12 at 21:57
  • @mhopkins321: of course it does. You need to wait for connection in between `Start` and `Stop`. For example, use [AcceptTcpClient](http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.accepttcpclient.aspx), but if it never receives the connection request (i.e. due to firewall block), it will wait indefinitely. So maybe use [AcceptTcpClientAsync](http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.accepttcpclientasync.aspx), and check if it receives connection until timeout. The resulting script may get complicated to account for such sync issues. – Victor Zakharov Oct 29 '12 at 22:18
  • Is there any way to (easily) make it print something when a connection is received? – David says Reinstate Monica Oct 20 '15 at 04:20
  • 1
    @Neolisk Awesome! Thanks for updating 3 years later :) – David says Reinstate Monica Oct 20 '15 at 13:57
  • 1
    @Neolisk Genial! Gracias – walterpaoli Nov 04 '15 at 22:47
  • 3
    Works on Linux (SLES 12 SP 3) too. Thanks! – Tobias Wollgam Jan 21 '19 at 10:25
3

I needed something that would not only acknowledge that the port was open, but respond as well. So,here's my super-basic not-quite-telnet server.

Clear-Host; $VerbosePreference="Continue"; $Port=23
$EndPoint=[System.Net.IPEndPoint]::new([System.Net.IPAddress]::Parse("<ip address>"),$Port)
$Listener=[System.Net.Sockets.TcpListener]::new($EndPoint)

$KeepListening=$true
while ($KeepListening) {
  $Listener.Start()
  while (!$Listener.Pending) { Start-Sleep -Milliseconds 100 }

  $Client=$Listener.AcceptTcpClient()
  Write-Output "Incoming connection logged from $($Client.Client.RemoteEndPoint.Address):$($Client.Client.RemoteEndPoint.Port)"

  $Stream=$Client.GetStream()
  $Timer=10; $Ticks=0; $Continue=$true
  $Response=[System.Text.Encoding]::UTF8.GetBytes("I see you.  I will die in $($Timer.ToString()) seconds.`r`nHit <space> to add another 10 seconds.`r`nType q to quit now.`r`nType x to terminate listener.`r`n`r`n")
  $Stream.Write($Response,0,$Response.Length)

  $StartTimer=(Get-Date).Ticks
  while (($Timer -gt 0)  -and $Continue) {
    if ($Stream.DataAvailable) {
      $Buffer=$Stream.ReadByte()
      Write-Output "Received Data: $($Buffer.ToString())"
      if ($Buffer -eq 113) {
        $Continue=$false
        $Response=[System.Text.Encoding]::UTF8.GetBytes("`r`nI am terminating this session.  Bye!`r`n")
      }
      elseif ($Buffer -eq 32) {
        $Timer+=10
        $Response=[System.Text.Encoding]::UTF8.GetBytes("`r`nAdding another 10 seconds.`r`nI will die in $($Timer.ToString()) seconds.`r`n")
      }
      elseif ($Buffer -eq 120) {
        $Continue=$false
        $KeepListening=$false
        $Response=[System.Text.Encoding]::UTF8.GetBytes("`r`nI am terminating the listener.  :-(`r`n")
      }
      else { $Response=[System.Text.Encoding]::UTF8.GetBytes("`r`nI see you.  I will die in $($Timer.ToString()) seconds.`r`nHit <space> to add another 10 seconds.`r`nType q to quit this session.`r`nType x to terminate listener.`r`n`r`n") }

      $Stream.Write($Response,0,$Response.Length)
    }
    $EndTimer=(Get-Date).Ticks
    $Ticks=$EndTimer-$StartTimer
    if ($Ticks -gt 10000000) { $Timer--; $StartTimer=(Get-Date).Ticks }
  }

  $Client.Close()
}
$Listener.Stop()