Wednesday, February 6, 2013

Simple Powershell TCP client for reading telnet banner

For many IT pro's you will find yourself in situations where you get an alert that a system you manage is down.  This can be from a variety of issues, but typically you will ping to see if its really down, and sometimes just based on the ICMP reply types for the ping, you can roughly tell where the problem lies.

Some of these results can roughly be translated as follows

     TTL expired in transit = Routing loop.  Can be due to default routes in use and a link being down
     Destination host not reachable OR Request time out = the subnet is accessible or directly connected, but no arp reply for ethernet to work, or firewall filtering is occuring
     Destination network not reachable = a router doesn't know how to get to that subnet
     Request timed out = router may be trying to forward a packet (but the network is not available), system is on the same subnet and down.

You can follow that your ping with a trace-route to see if the link going to the location that the system is in, is up.  Often, you won't get much information from the trace-route as most hop's won't have reverse dns records.  So, if you have an environment with routers that can be accessed by telnet, and the banner information provides some details on where it is, you can telnet to the last responding hop in your trace to see where the network connection drops.  Since telnet.exe is frequently not available on windows machines these days, yet powershell is, you can leverage the .NET framework to do the work for you (and you won't have to lose output prior to the telnet command and wait for the connection to auto disconnect you).

#requires -version 2.0
    [parameter(mandatory=$true,position=0,helpmessage="Hostname or IP")]

if (test-connection $hostname) {
    $conn = new-object$hostname,23)
    $str = $conn.getstream()
    $buff = new-object system.byte[] 1024
    $enc = new-object System.Text.ASCIIEncoding
    start-sleep -m 200
    $output = ""
    while ($str.DataAvailable -and $output -notmatch "username") {
        $read = $$buff,0,1024)
        $output += $enc.getstring($buff, 0, $read)
        start-sleep -m 300
} else {
    Write-Error "Unable to ping or resolve host"
    exit 1