Credits to the Ugly Gizmo blog, this script would not be without Grant's work.
<# .SYNOPSIS A modified graceful telnet scripting client using PowerShell and the .NET Framework. .DESCRIPTION This script was originally made with a view of using it to have full control over the text stream for automating Cisco router and switch configurations. Modifications have been added for scripting automation and logic .PARAMETER TelnetHost The address of the server or router hosting the telnet service. .PARAMETER Port The TCP port number of the Telnet service running on the Telnet host. .NOTES Modified: http://garcol.blogspot.com/2014/07/powershell-scripting-telnet.html Original: http://uglygizmo.blogspot.com/2013/10/a-telnet-client-written-in-powershell.html #> param ( [parameter(Mandatory)] [String] $TelnetHost, [Int] $TelnetPort = 23 ) # Initialize variables [System.Text.ASCIIEncoding]$ASCIIEncoding = [System.Text.Encoding]::ASCII [System.Net.Sockets.Socket]$Socket = $null # Checking host address and port. if ($TelnetHost -match ":") { $hostBytes = $TelnetHost.Split(':') $TelnetHost = $hostBytes[0] $TelnetPort = $hostBytes[1] } if ([String]::IsNullOrEmpty($TelnetHost)) { Write-Host -Object "Error: Invalid host address (null or empty)." -ForegroundColor Red return } # Setup and connect the TCP Socket. $Socket = New-Object -TypeName System.Net.Sockets.Socket( [System.Net.Sockets.AddressFamily]::InterNetwork, [System.Net.Sockets.SocketType]::Stream, [System.Net.Sockets.ProtocolType]::Tcp) $Socket.NoDelay = $true try { $Socket.Connect($TelnetHost, $TelnetPort) } catch { "Unable to connect to host {0}:{1}" -f $TelnetHost,$TelnetPort return } # This state object is used to pass the connected Socket and the # PowerShell parent Host reference to the child PowerShell object. $State = [PSCustomObject]@{"Socket"=$Socket;"Host"=$Host;"Exception"=$null;"Response"=$null} # This script block is used as the receive code for the Socket # from within the child PowerShell object. $Script = { param($state) [string[]]$returnLog = "Started" # This encoding object is used to decode the return string. [System.Text.ASCIIEncoding]$ASCIIEncoding = [System.Text.Encoding]::ASCII # TELNET commands [Byte]$GA = 249 # Go Ahead [Byte]$WILL = 251 # Desire to begin [Byte]$WONT = 252 # Refusal to perform [Byte]$DO = 253 # Request that the other party perform [Byte]$DONT = 254 # Demand that the other party stop performing [Byte]$IAC = 255 # Interpret as Command # TELNET options [Byte]$ECHO = 1 # Used to check the echo mode [Byte]$SUPP = 3 # Suppress go ahead # Used to hold the number of bytes returned from the network stream. [Int]$bytes = 0 # Buffer to hold the returned Bytes. [Byte[]]$buffer = New-Object -TypeName Byte[]($state.Socket.ReceiveBufferSize) # This is the main receive loop. while ($state.Socket.Connected) { try { # The following statement will block the thread until data is received. $bytes = $state.Socket.Receive($buffer) } catch { # This exception reference is used to pass the error back to the # parent PowerShell process. $state.Exception = $Error[0] break } if ($bytes -gt 0) { $index = 0 $responseLen = 0 # The index is used to move through the buffer to analyze the received data # looking for Telnet commands and options. while ($index -lt $bytes) { if ($buffer[$index] -eq $IAC) { try { switch ($buffer[$index + 1]) { # If two IACs are together they represent one data byte 255 $IAC { $buffer[$responseLen++] = $buffer[$index] $index += 2 break } # Ignore the Go-Ahead command $GA { $index += 2 break } # Respond WONT to all DOs and DONTs {($_ -eq $DO) -or ($_ -eq $DONT)} { $buffer[$index + 1] = $WONT $state.Socket.Send($buffer, $index, 3, [System.Net.Sockets.SocketFlags]::None) | Out-Null $index += 3 break } # Respond DONT to all WONTs $WONT { $buffer[$index + 1] = $DONT $state.Socket.Send($buffer, $index, 3, [System.Net.Sockets.SocketFlags]::None) | Out-Null $index += 3 break } # Respond DO to WILL ECHO and WILL SUPPRESS GO-AHEAD # Respond DONT to all other WILLs $WILL { [Byte]$action = $DONT if ($buffer[$index + 2] -eq $ECHO) { $action = $DO } elseif ($buffer[$index + 2] -eq $SUPP) { $action = $DO } $buffer[$index + 1] = $action $state.Socket.Send($buffer, $index, 3, [System.Net.Sockets.SocketFlags]::None) | Out-Null $index += 3; break; } } } catch { # If there aren't enough bytes to form a command, terminate the loop. $index = $bytes } } else { if ($buffer[$index] -ne 0) { $buffer[$responseLen++] = $buffer[$index] } $index++ } } # Displays the response with no command codes on the parent PowerShell object. $returnString = $ASCIIEncoding.GetString($buffer, 0, $responseLen) $returnLog += $returnString #$state.Host.UI.Write($returnString) $state.response += $returnString } } } # End of the child PowerShell script definition. # Create a child PowerShell object to run the background Socket receive method. $PS = [PowerShell]::Create() $PS.AddScript($Script).AddArgument($State) | Out-Null [System.IAsyncResult]$AsyncJobResult = $null try { # The receive job is started asynchronously. $AsyncJobResult = $PS.BeginInvoke() #YOUR TELNET COMMANDS IN HERE # Sends Commands function sendCmd($command) { # Wait, then send data. start-sleep -m 500 $Data = $ASCIIEncoding.GetBytes($command) $Socket.Send($Data) | Out-Null $Socket.Send(13) | Out-Null #sends the return keystroke after each cmd start-sleep -m 500 } ###################################################################################### #TELNET COMMANDS IN HERE # Use sendCmd("") to send text commands, use $Socket.Send() to send ascii encoded keystrokes # # List of Commands to be Sent [string[]]$cmdList = "username" $cmdlist += "password" # Login foreach ($cmd in $cmdlist){ sendCmd($cmd) | out-null} sendCmd("show something") | out-null $thisData = $state.response #Can perform logic on the response here $state.response = $null # Issue the Exit command, closing the session gracefully sendCmd("exit") | out-null # #TELNET COMMANDS IN HERE ###################################################################################### } finally { # Cleanup the socket and child PowerShell process. if ($Socket -ne $null) { $Socket.Close() $Socket.Dispose() $Socket = $null } if ($PS -ne $null -and $AsyncJobResult -ne $null) { $PS.EndInvoke($AsyncJobResult) $PS.Dispose() } }
No comments:
Post a Comment