Telnet with PowerShell - powershell

I use this powershell script for getting output stream of telnet request.
Function Get-Telnet {
Param (
[Parameter(ValueFromPipeline=$true)]
[string[]]$Commands = #(),
[string]$RemoteHost = "0.0.0.0",
[string]$Port = "23",
[int]$WaitTime = 1000,
[string]$OutputPath = "C:\temp\telnet_output.log"
)
#Attach to the remote device, setup streaming requirements
$Socket = New-Object System.Net.Sockets.TcpClient($RemoteHost, $Port)
if ($Socket) {
$Stream = $Socket.GetStream()
$Writer = New-Object System.IO.StreamWriter($Stream)
$Buffer = New-Object System.Byte[] 1024
$Encoding = New-Object System.Text.AsciiEncoding
#Now start issuing the commands
foreach ($Command in $Commands) {
$Writer.WriteLine($Command)
$Writer.Flush()
Start-Sleep -Milliseconds $WaitTime
}
#All commands issued, but since the last command is usually going to be
#the longest let's wait a little longer for it to finish
Start-Sleep -Milliseconds ($WaitTime * 4)
$Result = ""
#Save all the results
while ($Stream.DataAvailable) {
$Read = $Stream.Read($Buffer, 0, 1024)
$Result += ($Encoding.GetString($Buffer, 0, $Read))
}
} else {
$Result = "Unable to connect to host: $($RemoteHost):$Port"
}
#Done, now save the results to a file
#$Result | Out-File $OutputPath
$Result
}
This works for a Cisco switch and a telnet server, but for the Alcatel OmniPCX and the HPUX the stream reading is empty.

Related

PowerShell readline from a stream

Using a PowerShell script I will have to read and write to a console. We write an input and wait for an out that will be captured by $Reader.ReadLine(). But in some cases there wont be any output to get captured for the reader in that case the reader needs to look data from the stream and if there is no data the ReadLine() gets stuck/blocked waiting for the data from the console stream, whereas we need the ReadLine() to just wait for 5 seconds. If there is no data, it needs to get timed out and move on to the next command.
Please let me know whether there is any way to timeout $Reader.ReadLine() in PowerShell?
I see that in Java/C# we can use $Reader.ReadLine(1000) to timeout after 1 second but that doesn't seem to be working on PowerShell.
$tcpConnection = New-Object System.Net.Sockets.TcpClient($Computername, $Port)
$tcpStream = $tcpConnection.GetStream()
$reader = New-Object System.IO.StreamReader($tcpStream)
$writer = New-Object System.IO.StreamWriter($tcpStream)
$writer.AutoFlush = $true
$buffer = New-Object System.Byte[] 1024
$encoding = New-Object System.Text.AsciiEncoding
while ($tcpStream.DataAvailable) {
$reader.ReadLine()
}
if ($tcpConnection.Connected) {
$writer.WriteLine($username)
$reader.ReadLine()
$writer.WriteLine($password)
$reader.ReadLine()
try {
# if there is any data it will show here if there is no data then
# it should get timed out after 5 seconds
$Reader.ReadLine()
} catch {
Write-Host "Login Failed"
}
}
I would say that you should read this post C# Stream.Read with timeout
Converting that to your code sample, should end up with something like this.
$tcpConnection = New-Object System.Net.Sockets.TcpClient($Computername, $Port)
#This is one way you could try
$tcpConnection.ReceiveTimeout = 5000;
$tcpStream = $tcpConnection.GetStream()
$reader = New-Object System.IO.StreamReader($tcpStream)
$writer = New-Object System.IO.StreamWriter($tcpStream)
$writer.AutoFlush = $true
$buffer = New-Object System.Byte[] 1024
$encoding = New-Object System.Text.AsciiEncoding
while ($tcpStream.DataAvailable) {
$reader.ReadLine()
}
if ($tcpConnection.Connected) {
$writer.WriteLine($username)
$reader.ReadLine()
$writer.WriteLine($password)
$reader.ReadLine()
try {
# if there is any data it will show here if there is no data then
# it should get timed out after 5 seconds
$Reader.ReadLine()
} catch {
Write-Host "Login Failed"
}
}
Take it for a spin and let me know if it works or not.
Updated:
Updated to reflect the code to only contain the working solution.

PowerShell and Telnet Integration Outputs Junk Chars

I have tried to get PowerShell automation for Telnet connecting to Windows Server 2012 R2, Ubuntu 16.04 and Windows XP SP3 and all servers are throwing junk characters as output.
I was going through rfc854 but I could not get this done.
Could you please help me on how to resolve this issue.
Below code would try to connect Telnet server with credentials and output dir list.
Code
param (
[string] $terminalServer = "192.168.19.131",
[int] $port = 23,
[string] $username = "username",
[string] $password = "password",
[int] $commandDelay = 1000,
[string] $output = ""
)
function GetOutput {
## Create a buffer to receive the response
$buffer = new-object System.Byte[] 1024
$encoding = new-object System.Text.AsciiEncoding
$outputBuffer = ""
$foundMore = $false
## Read all the data available from the stream, writing it to the
## output buffer when done.
do {
## Allow data to buffer for a bit
start-sleep -m 1000
## Read what data is available
$foundmore = $false
$stream.ReadTimeout = 2000
do {
try {
$read = $stream.Read($buffer, 0, 1024)
if($read -gt 0) {
$foundmore = $true
$outputBuffer += ($encoding.GetString($buffer, 0, $read))
}
} catch { $foundMore = $false; $read = 0 }
} while($read -gt 0)
} while($foundmore)
$outputBuffer
}
$output = ""
write-host "Connecting to $terminalServer on port $port..."
trap { Write-Error "Could not connect to the server: $_"; exit }
$socket = new-object System.Net.Sockets.TcpClient($terminalServer, $port)
write-host "Connected. `n"
$stream = $socket.GetStream()
$writer = new-object System.IO.StreamWriter $stream
## Receive the output that has buffered so far
$SCRIPT:output += GetOutput
$writer.WriteLine($username)
$writer.Flush()
Start-Sleep -m $commandDelay
$SCRIPT:output += GetOutput
$writer.WriteLine($password)
$writer.Flush()
Start-Sleep -m $commandDelay
$SCRIPT:output += GetOutput
$writer.WriteLine("dir")
$writer.Flush()
Start-Sleep -m $commandDelay
$SCRIPT:output += GetOutput
$writer.WriteLine("exit")
$writer.Flush()
Start-Sleep -m $commandDelay
## Close the streams
$writer.Close()
$stream.Close()
write-host "All streams are closed. The final output is"
$output
Output
D:\Tools\T24\PowerShell>powershell .\telnet_test.ps1
Connecting to 192.168.19.131 on port 23...
Connected.
All streams are closed. The final output is
??%??????'???? ??
I have tried with jBASE Telnetd Server Version 4.1.1 on Windows Server 2012 R2 and perfectly listing directory.
So, with Windows version of Telnet requires some more manipulation as per rfc854 implementation.

PowerShell TCP Server

I would like to ask you, how it is possible to handle multiple connection threads.
I have implemented TCP server in the following way:
$endpoint = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Any, 8989)
$listener = New-Object System.Net.Sockets.TcpListener $endpoint
$listener.Start()
do {
$client = $listener.AcceptTcpClient() # will block here until connection
$stream = $client.GetStream();
$reader = New-Object System.IO.StreamReader $stream
do {
$line = $reader.ReadLine()
Write-Host $line -fore cyan
} while ($line -and $line -ne ([char]4))
$reader.Dispose()
$stream.Dispose()
$client.Dispose()
} while ($line -ne ([char]4))
$listener.Stop()
This code can handle just one thread in time.
Can you give me an advice on how to create a TCP server in PowerShell that can handle multiple clients?
For handling multiple clients you need multiple threads and for that you need to use runspaces. Below is the working code which accepts multiple clients and do the processing of each client in separate thread (runspace)
$Global:Listener = [HashTable]::Synchronized(#{})
$Global:CnQueue = [System.Collections.Queue]::Synchronized((New-Object System.collections.queue))
$Global:space = [RunSpaceFactory]::CreateRunspace()
$space.Open()
$space.SessionStateProxy.setVariable("CnQueue", $CnQueue)
$space.SessionStateProxy.setVariable("Listener", $Listener)
$Global:newPowerShell = [PowerShell]::Create()
$newPowerShell.Runspace = $space
$Timer = New-Object Timers.Timer
$Timer.Enabled = $true
$Timer.Interval = 1000
Register-ObjectEvent -SourceIdentifier MonitorClientConnection -InputObject $Timer -EventName Elapsed -Action {
While($CnQueue.count -ne 0) {
$client = $CnQueue.Dequeue()
$newRunspace = [RunSpaceFactory]::CreateRunspace()
$newRunspace.Open()
$newRunspace.SessionStateProxy.setVariable("client", $client)
$newPowerShell = [PowerShell]::Create()
$newPowerShell.Runspace = $newRunspace
$process = {
$stream = $client.GetStream();
$reader = New-Object System.IO.StreamReader $stream
[console]::WriteLine("Inside Processing")
# You have client here so do whatever you want to do here.
# This is a separate thread so if you write blocking code here, it will not impact any other part of the program
}
$jobHandle = $newPowerShell.AddScript($process).BeginInvoke()
#jobHandle you need to save for future to cleanup
}
}
$listener = {
$Listener['listener'] = New-Object System.Net.Sockets.TcpListener("127.0.0.1", "1234")
$Listener['listener'].Start()
[console]::WriteLine("Listening on :1234")
while ($true) {
$c = $Listener['listener'].AcceptTcpClient()
If($c -ne $Null) {
[console]::WriteLine("{0} >> Accepted Client " -f (Get - Date).ToString())
$CnQueue.Enqueue($c)
}
Else {
[console]::WriteLine("Shutting down")
Break
}
}
}
$Timer.Start()
$Global:handle = $newPowerShell.AddScript($listener).BeginInvoke()
For more detailed example please go here

How to Configure cisco router using POWERSHELL SSH.net?

Good, this is the code I'm using:
function escribe_log($dispositivo, $log, $comando){
$Fichero_Log = "C:\Modificacion_routers.log"
$texto = $dispositivo
$texto >> $Fichero_Log
$texto = $log
$texto >> $Fichero_Log
$texto = $comando
$texto >> $Fichero_Log
}
##PROGRAMA PRINCIPAL##
Import-Module SSH-Sessions
$ficheroIPS = "C:\ipsdispositivos.txt"
$ficheroComandos = "c:\comandos.txt"
$dispositivos = Get-Content $ficheroIPS
$comandos = Get-Content $ficheroComandos
foreach ($dispositivo in $dispositivos) {
New-SshSession -ComputerName $dispositivo -Username USUARIO -password PASSWORD
foreach ($comando in $comandos) {
$SshResults = Invoke-SshCommand -ComputerName $dispositivo -Command $comando
escribe_log $dispositivo $SshResults $comando
Start-Sleep -s 1
}
$comandos = Get-Content $ficheroComandos
}
Remove-sshSession -RemoveAll
Works perfectly to launch "sh" show commands, my problem is that when I launch a command automatically disconnects the session, then command is not possible to launch a "conf t" to enter configuration mode and then launch configuration commands.
Do you know if this library is possible to configure a router?
if that is not possible,
would they know me any alternative to configure the router using script?
SOLVED:
FUNCTION FOR CHANGES TO SSH ROUTER/SWITCH WITH POWERSHELL
Function set-SSH($devices, $ssh){
function ReadStream($reader)
{
$line = $reader.ReadLine();
while ($line -ne $null)
{
$line
$line = $reader.ReadLine()
}
}
function WriteStream($cmd, $writer, $stream)
{
$writer.WriteLine($cmd)
while ($stream.Length -eq 0)
{
start-sleep -milliseconds 1000
}
}
$stream = $ssh.CreateShellStream("dumb", 80, 24, 800, 600, 1024)
$reader = new-object System.IO.StreamReader($stream)
$writer = new-object System.IO.StreamWriter($stream)
$writer.AutoFlush = $true
while ($stream.Length -eq 0)
{
start-sleep -milliseconds 500
}
ReadStream $reader
foreach ($command in $commands) {
WriteStream $command $writer $stream
ReadStream $reader
Write-Host $reader
start-sleep -milliseconds 500
}
$stream.Dispose()
$ssh.Disconnect()
$ssh.Dispose()
}
There are three variables to initialize $commands, $ssh, $devices
#Example of file commands.txt...
#sh conf
#conf t
#int f0/1
#description Modify via powershell
#exit
#exit
#wr
#...
$fileCommands= ".\commands.txt"
$commands= Get-Content $fileCommands
#Example of file devices.csv...
#10.10.10.10;SWITCH01
#10.10.10.11;SWITCH02
#10.10.10.12;SWITCH03
#...
$devices = Import-Csv -path ".\devices.csv" -header 'ip','hostname' -delimiter ';'
$port = 22
$ssh = new-object Renci.SshNet.SshClient($devices[0].ip, $port, $user, $password)
Try{
$ssh.Connect()
Start-Sleep -s 1
set-SSH $commands $ssh
}catch{
}

Powershell v2.0 , unable to read the correct data from a tcpclient

I am very new to powershell programming,I have the following script, which reads from a socket stream as long as data is available, and then sends a "q" to exit the connection.
I am running this on win 2003 server std,Power shell V2.0.
When I execute the pgm, the output is the text from the pgm, which is reading and buffering.It almost looks like The following is the output:
Connecting to aardwolf.org on port 23
while($stream.DataAvailable)
{
$read = $stream.Read($buffer, 0, 1024)
write-Host $read
if($read -gt 0)
{
$outputBuffer += ($encoding.GetString($buffer, 0, $read))
}
}## Read the user's command, quitting if they hit
Following is the code:
# Interact with a service on a remote TCP port
param( [string] $remoteHost = "aardwolf.org",
[int] $port = 23 )
## Open the socket, and connect to the computer on the specified port
write-host "Connecting to $remoteHost on port $port"
$socket = new-object System.Net.Sockets.TcpClient($remoteHost, $port)
if($socket -eq $null) { return; }
$stream = $socket.GetStream()
$writer = new-object System.IO.StreamWriter($stream)
$buffer = new-object System.Byte[] 1024
$encoding = new-object System.Text.AsciiEncoding
while($true)
{
## Allow data to buffer for a bit
start-sleep -m 500
$outputBuffer = ""
## Read all the data available from the stream, writing it to the ## screen when done.
if($stream.CanRead)
{
while($stream.DataAvailable)
{
$read = $stream.Read($buffer, 0, 1024)
write-Host $read
if($read -gt 0)
{
$outputBuffer += ($encoding.GetString($buffer, 0, $read))
}
}## Read the user's command, quitting if they hit
}
write-Host $outputBUffer
$command = "q"
$writer.WriteLine($command)
$writer.Flush()
break
}
## Close the streams
if($writer -ne $null)
{
$writer.Close()
$stream.Close()
}
Need some help resolving the issue.