Skip to content

Instantly share code, notes, and snippets.

@johndonnelly
Forked from PrateekKumarSingh/PSTelnetV2.ps1
Created May 6, 2019 20:12
Show Gist options
  • Save johndonnelly/4adfa082e621e5c07078dd02a0f3e9c5 to your computer and use it in GitHub Desktop.
Save johndonnelly/4adfa082e621e5c07078dd02a0f3e9c5 to your computer and use it in GitHub Desktop.
# Function to enable telnet-ing from [Local/Remote] Source location, which requires credentials for remote source machine
# This Function is a wrapper around Function PSTelnet to add remote source telnet-ing feature
Function Test-Port
{
[cmdletbinding()]
Param
(
[Parameter(Position=0)] $Source = $(Hostname),
[Parameter(Mandatory=$true,Position=1)] $Destination,
[Parameter(Mandatory=$true,Position=2)]
[ValidateScript({
If($_ -match "^[0-9]+$"){$True}
else{Throw "A port should be a numeric value, and $_ is not a valid number"}
})] $Port,
[Parameter(Position=3)][ValidateSet('TCP','UDP')] $Protocol = 'TCP',
[Int] $TCPTimeOut=1000,
[Int] $UDPTimeOut=5000,
[Int] $PingTimeOut=80,
[Switch] $Iterate
)
Begin{}
Process
{
# If $source is a localhost, invoke command is not required and we can test port, withhout credentials
If($Source -like "127.*" -or $source -like "*$(hostname)*" -or $Source -like 'localhost')
{
Do
{
PSTelnet $Destination $Port $Protocol $TCPTimeOut $UDPTimeOut $PingTimeOut
Start-Sleep -Seconds 1 #Initiate sleep to slow down Continous telnet
}While($Iterate)
}
Else #Prompt for credentials when Source is not the local machine.
{
Get-Credential -Message "Provide Admin credentials to Telnet from [Remote source] to [Remote destination] machine(s)" -OutVariable Credentials
If($Credentials)
{
Do
{
Foreach($Item in $Source)
{
Invoke-command -ComputerName $Item `
-Credential $Credentials `
-ScriptBlock ${Function:PSTelnet} `
-ArgumentList $Destination,$Port,$Protocol,$TCPTimeOut,$UDPTimeOut,$PingTimeOut
}
# Sleep to slow down Continous telnet
Start-Sleep -Seconds 1
}While($Iterate)
}
}
}
end{}
}
# Function to telnet a port from a Source to a Destination
# Using the .Net class System.Net.Sockets.TCP/UDPClient
Function PSTelnet
{
[Alias("Tn")]
[Cmdletbinding()]
Param(
[String[]] $Destination,
[Int[]] $port,
[string[]] $Protocol,
[Int] $TCPTimeOut=1000, # 1000 ms default TCP TimeOut
[Int] $UDPTimeOut=5000, # 5000 ms default UDP TimeOut
[Int] $PingTimeout=80
)
Begin
{
$Source = (hostname).toupper()
}
Process
{
Foreach($Target in $Destination)
{
Foreach($CurrentPort in $Port)
{
Write-Verbose "Testing $Protocol port $CurrentPort from $Source to $Target"
$HostStatus = (QuickPing $Target $PingTimeOut).status
If($Protocol -eq 'TCP')
{
Try
{
# Instantiate TCPClient Socket
$TCPClient = new-Object system.Net.Sockets.TcpClient
# Establish connection to the Port
$Connection = $TCPClient.BeginConnect($Target,$CurrentPort,$null,$null)
# Wait for connection to Timeout
If ($Connection.AsyncWaitHandle.WaitOne($TCPTimeOut,$false))
{
$TCPClient.EndConnect($Connection) | out-Null
#Write-host "$((hostname).toupper()) connected to $($Target.toupper()) on $Protocol port : $currentPort " -back green -ForegroundColor White
''|select @{n='Source';e={$Source}},`
@{n='Destination';e={$Target.toupper()}},`
@{n='Protocol';e={$Protocol}},`
@{n='Port';e={$CurrentPort}},`
@{n='Open';e={$true}}, `
@{n='HostUp?';e={If($HostStatus -eq 'success'){$True}else{$false}}}
}
}
Catch
{
#Write-host "$((hostname).toupper()) Not connected to $($Target.toupper()) on $Protocol port : $currentPort" -back red -ForegroundColor white
''|select @{n='Source';e={$Source}},`
@{n='Destination';e={$Target.toupper()}},`
@{n='Protocol';e={$Protocol}},`
@{n='Port';e={$CurrentPort}},`
@{n='Open';e={$false}}, `
@{n='HostUp?';e={If($HostStatus -eq 'success'){$True}else{$false}}}
}
Finally
{
$TCPClient.Close()
}
}
Else
{
# Create object for connecting to port on computer
$UDPClient = new-Object system.Net.Sockets.Udpclient
# Set a timeout on receiving message, to avoid source machine to Listen forever.
$UDPClient.client.ReceiveTimeout = $UDPTimeOut
# Datagrams must be sent with Bytes, hence the text is converted into Bytes
$ASCII = new-object system.text.asciiencoding
$Bytes = $ASCII.GetBytes("Hi")
# UDP datagram is send
[void]$UDPClient.Send($Bytes,$Bytes.length,$Target,$CurrentPort)
$RemoteEndpoint = New-Object system.net.ipendpoint([system.net.ipaddress]::Any,0)
Try
{
# Waits for a UDP response until timeout defined above
$RCV_Bytes = $UDPClient.Receive([ref]$RemoteEndpoint)
$RCV_Data = $ASCII.GetString($RCV_Bytes)
If($RCV_Data)
{
#Write-host "$((hostname).toupper()) connected to $($Target.toupper()) on $Protocol port : $currentPort " -back green -ForegroundColor White
''|select @{n='Source';e={$Source}},`
@{n='Destination';e={$Target.toupper()}},`
@{n='Protocol';e={$Protocol}},`
@{n='Port';e={$CurrentPort}},`
@{n='Open';e={$true}}, `
@{n='HostUp?';e={If($HostStatus -eq 'success'){$True}else{$false}}}
}
}
catch
{
# If the UDP recieve is timed out it's inferred that no response was received.
# Write-host "$((hostname).toupper()) Not connected to $($Target.toupper()) on $Protocol port : $currentPort " -back red -ForegroundColor White
''|select @{n='Source';e={$Source}},`
@{n='Destination';e={$Target.toupper()}},`
@{n='Protocol';e={$Protocol}},`
@{n='Port';e={$CurrentPort}},`
@{n='Open';e={$false}}, `
@{n='HostUp?';e={If($HostStatus -eq 'success'){$True}else{$false}}}
}
Finally
{
# Disposing Variables
$UDPClient.Close()
$RCV_Data=$RCV_Bytes=$null
}
}
}
}
}
end{}
}
# Though we have Test-Connection cmdlet, but that doesn't have a Timeout option in it.
# Which makes running the script for multiple machines somewhat slower, as it waits for default timeout
# As a workaround, instantiating System.Net class give us an option to specify the TimeOut for ICMP requests, hence this function
Function QuickPing
{
Param(
[String] $Computername,
[int] $PingTimeOut = 80
)
[switch]$resolve = $true
[int]$TTL = 128
[switch]$DontFragment = $false
[int]$buffersize = 32
$options = new-object system.net.networkinformation.pingoptions
$options.TTL = $TTL
$options.DontFragment = $DontFragment
$buffer=([system.text.encoding]::ASCII).getbytes("hi"*$buffersize)
$Ping = New-Object system.net.networkinformation.ping
#$Ping.se
$Ping.Send($Computername,$PingTimeOut,$buffer,$options)
$Ping.Dispose()
}
Test-Port -Source (Get-Content .\SourceMachines.txt) `
-Destination (Get-Content .\DestinationMachines.txt) `
-Port 3389,20,21,53,25,443,135,139 `
-Protocol TCP |sort open| ft -AutoSize # | Export-Csv portstatus.csv -NoTypeInformation
#Test-Port '127.0.0.1' 'dc1' 57766 -Protocol UDP -Iterate
#Test-Port 'localhost' 'dc2' 51753 -Protocol UDP
#Test-Port -Source $EUCAS -Destination $EUMBX -Port 135 -Iterate
#Test-Port -Source 'localhost' -Destination '127.0.0.1' -Port 135 -Iterate -protocol TCP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment