pping – Ein Ping auf Port-Ebene

Manchmal muss man eben selbst Hand anlegen, wenn man etwas braucht. Normalerweise suche ich mir kleine Apps und Tools im schier unerschöpflichen Fundus des Internet. Dieses Mal gab es aber nichts, was mir wirklich passte. Ich brauchte ein ping, das nicht den Rechner, sondern einen Port auf diesem auf Erreichbarkeit prüft.


Download aktuelle Version (7Zip)

Wofür?

PPing ist eigentlich schnell erklärt. Ein normales ping gibt einem Nutzer an, ob ein Netzwerkendpunkt erreichbar ist, oder eben nicht. Das ist in den meisten Fällen auch alles, was man wissen muss. Ich brauchte aber immer wieder die Information, ob ein bestimmter Port auf einer Maschine erreichbar ist und das kann ping erstmal nicht.

Sucht man in Internetforen nach einer Lösung dieses Problems, tauchen immer wieder 2 Lösungsvorschläge auf:

  1. Versuchen, eine telnet-Session auf den betreffenden Port aufzubauen.
  2. nmap benutzen

Irgendwie fand ich beides immer schon reichlich blöd bzw. überzogen. telnet muss man unter Windows z.B. erstmal freischalten bzw. installieren. Hat man das dann endlich und benutzt diesen Weg, macht man eigentlich nichts anderes, als ein Programm zu missbrauchen. telnet ist einfach nicht für diese Aufgabe gemacht und wenn ich (wie man es bei ping oft tut) einen Trace laufen lassen möchte, der mir sagt, wann ein Port einfach da ist, dann geht das auch nicht.

nmap scheint da besser geeignet, aber es ist einfach zu mächtig. nmap ist die eierlegenede Wollmilchsau unter den Netzwerktools. Ein Sniffer-Portchecker-Clone, der mir immer irgendwie zu “schwer” vorkam.

Und genau hier kommt pping ins Spiel.

Wie?

Ich habe pping als .NET-Konsolenanwendung geschrieben. Es basiert auf .NET Framework 4.5, nutzt eigentlich nur den Namespace System.Net und kommt mit vielerlei Optionen daher, die ich später noch erläutern werde.

Der Download bringt einem ein 7Zip, das aus 2 Dateien besteht. pping.exe und SabUtils.dll. Letztere ist eine Bibliothek, die ich für meine Firmen-Belange geschrieben habe bzw. immer weiter entwickle. Sie beinhaltet die eigentliche Logik für das Feststellen, ob ein Port offen ist oder nicht (auch dazu später mehr).

Die Nutzung ist nun denkbar einfach. Der Minimal-Aufruf lautet:

pping {Adresse} {Portnummer}

Das bei Nutzung von codingfreaks.de als Port und 80 als Port zu folgendem Output:

C:\Program Files (x86)\PPing>pping codingfreaks.de 80
Starting pinging host codingfreaks.de on port 80 4 times:
#   1 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   2 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   3 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   4 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
Finished pinging host codingfreaks.de (IP:-). 4 pings sent (4 OK, 0 CLOSED)

Was man da sieht ist also dem Verhalten des Windows-Ping nachempfunden. Ohne weitere Angabe von Optionen werden 4 Versuche unternommen, den Zielhost auf dem angegebenen Port zu erreichen. Die IP-Adresse wird nicht aufgelöst (Zeitgründe) und zum Schluss wird eine Zusammenfassung angezeigt.

Was geht sonst noch?

In der aktuellen Version sind weitere Optionen enthalten. Hier mal eine alphabetisch sortierte Liste.

address (a)

Die Adresse des Endpunkts, der geprüft werden soll. man könnte auch sagen, die Netzwerkadresse des Rechners, der gepingt werden soll. Die Adresse ist logischerweise ein Pflichtparameter. Man kann ihn z.B. so angeben:

pping -a=irgendwas.com

oder einfach hinter pping als erstes einfügen.

autostop (as)

Autostop ist ein Flag-Parameter. Es reicht also, ihn anzugeben, damit er wirksam wird. Ziel ist es, beim ersten OPEN-Ergebnis die Ausführung zu stoppen. Hier ein Beispiel:

C:\Program Files (x86)\PPing>pping codingfreaks.de 80 -as
Starting pinging host codingfreaks.de on port 80 4 times:
#   1 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
Finished pinging host codingfreaks.de (IP:-). 4 pings sent (1 OK, 0 CLOSED)

Da bereits die erste Anfrage “OPEN” lieferte, wird das Programm sofort verlassen. Man kann das z.B. in Verbindung mit endless nutzen, um solange Anfragen an den Port zu senden, bis er endlich da ist. Ich nutze dies gelegentlich, um auf Port 3389 eines Systems zu lauschen, dass ich gerade remote neu gestartet habe. Dann brauche ich nicht dümmlich immer wieder zu versuchen, eine RDP-Verbindung aufzubauen, obwohl der Dienst noch gar nicht online ist.

endless (t)

Endless sorgt dafür, dass pping nicht auffhört, Anfragen zu senden. “Nicht aufhört” ist dabei natürlich relativ. Das Maximum an Anfragen beträgt in .NET gesprochen int.MaxValue. Der Parameter wurde von mir mit “t” abgekürzt, weil das bei ping genauso gemacht wurde.

Auch endless ist ein Flag-Parameter, es reicht also, ihn anzugeben:

Starting pinging host codingfreaks.de on port 80 infinite times:
#   1 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   2 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   3 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   4 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   5 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   6 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   7 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   8 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   9 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#  10 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#  11 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#  12 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#  13 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN

logo (l)

Ein Flag, das dafür sorgt, dass ein App-Header erscheint, wenn es gesetzt wurde. Beispiel:

C:\Program Files (x86)\PPing>pping codingfreaks.de 80 -logo
*******************************************************************************
* PPing                                                                       *
* --------------------------------------------------------------------------- *
* codingfreaks ping with port-check                                           *
* --------------------------------------------------------------------------- *
* codingfreaks                                                                *
* Copyright © codingfreaks 2012                                               *
*******************************************************************************

Starting pinging host codingfreaks.de on port 80 4 times:
#   1 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   2 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   3 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   4 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
Finished pinging host codingfreaks.de (IP:-). 4 pings sent (4 OK, 0 CLOSED)

port (p)

Die Nummer des Ports, der geprüft werden soll. Der Wert muss größer als 0 sein und darf int.MaxValue nicht überschreiten:

C:\Program Files (x86)\PPing>pping codingfreaks.de -p=3389
Starting pinging host codingfreaks.de on port 3389 4 times:
#   1 -> Pinging host codingfreaks.de (IP:-) on port 3389 with timeout 1: CLOSED
#   2 -> Pinging host codingfreaks.de (IP:-) on port 3389 with timeout 1: CLOSED
#   3 -> Pinging host codingfreaks.de (IP:-) on port 3389 with timeout 1: CLOSED
#   4 -> Pinging host codingfreaks.de (IP:-) on port 3389 with timeout 1: CLOSED
Finished pinging host codingfreaks.de (IP:-). 4 pings sent (0 OK, 4 CLOSED)

repeats (r)

Kann genutzt werden, um anzugeben, wie viele Anfrage-Pakete das Tool senden soll. Der Standardwert ist 4.

C:\Program Files (x86)\PPing>pping codingfreaks.de 80 -r=10
Starting pinging host codingfreaks.de on port 80 10 times:
#   1 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   2 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   3 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   4 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   5 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   6 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   7 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   8 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#   9 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
#  10 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 1: OPEN
Finished pinging host codingfreaks.de (IP:-). 10 pings sent (10 OK, 0 CLOSED)

resolve (res)

Sorgt dafür, dass das Tool versucht, die IP-Adresse aus dem angegebenen Endpunkt zu ermitteln. Resolve ist ein Flag-Parameter und braucht keinen Wert.

C:\Program Files (x86)\PPing>pping codingfreaks.de 80 -res
Starting pinging host codingfreaks.de on port 80 4 times:
#   1 -> Pinging host codingfreaks.de (IP:85.13.141.89) on port 80 with timeout 1: OPEN
#   2 -> Pinging host codingfreaks.de (IP:85.13.141.89) on port 80 with timeout 1: OPEN
#   3 -> Pinging host codingfreaks.de (IP:85.13.141.89) on port 80 with timeout 1: OPEN
#   4 -> Pinging host codingfreaks.de (IP:85.13.141.89) on port 80 with timeout 1: OPEN
Finished pinging host codingfreaks.de (IP:85.13.141.89). 4 pings sent (4 OK, 0 CLOSED)

timeout (tim)

Ein Wert in Sekunden, der angibt, wie lange eine einzelne Anfrage wartet, bis sie als unbeantwortet gilt:

C:\Program Files (x86)\PPing>pping codingfreaks.de 80 -tim=10
Starting pinging host codingfreaks.de on port 80 4 times:
#   1 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 10: OPEN
#   2 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 10: OPEN
#   3 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 10: OPEN
#   4 -> Pinging host codingfreaks.de (IP:-) on port 80 with timeout 10: OPEN
Finished pinging host codingfreaks.de (IP:-). 4 pings sent (4 OK, 0 CLOSED)

waittime (w)

Zeitspanne in Millisekunden, die zwischen den einzelnen Anfragen gewartet werden soll. Der Sinn ist einfach, nicht zuviel Traffic zu erzeugen bzw. das Zielsystem nicht zu flooden. Standardmäßig steht dieser Wert auf 500. Hier ein Sample, dass 1,5 Sekunden zwischen 2 Aufrufen wartet:

C:\Program Files (x86)\PPing>pping codingfreaks.de 80 -w=1500

Technische Details

Das hier wäre nicht codingfreaks, wenn ich den Kern der Sache nicht enthüllen würde. Wie weiter oben bereits angemerkt, ist die Logik zum Ermitteln, ob ein Port geöffnet ist. Ich habe das wie folgt gelöst:

var result = false;
using (var client = new TcpClient())
{
    try
    {
        client.ReceiveTimeout = timeout * 1000;
        client.SendTimeout = timeout * 1000;
        var asyncResult = client.BeginConnect(host, port, null, null);
        var waitHandle = asyncResult.AsyncWaitHandle;
        try
        {
            if (!asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(timeout), false))
            {
                // wait handle didn't came back in time
                client.Close();
            }
            else
            {
                // The result was positiv
                result = client.Connected;
            }
            // ensure the ending-call
            client.EndConnect(asyncResult);
        }
        finally
        {
            // Ensure to close the wait handle.
            waitHandle.Close();
        }
    }
    catch
    {
    }
}
return result;

Ich habe vorher ein wenig mit allen möglichen einfacheren und komplizierteren Möglichkeiten rumgespielt. Die Variante oben erschien mir einfach ein guter Kompromiss aus Aufwand und Performance und arbeitet außerdem asynchron, was mir wichtig war. Wer weiß denn schon, wie lange es nur bei Konsolenanwendung bleibt?

Ach ja: Bevor mich Enthusiasten wegen des leeren catch geißeln: Weiter unten habe ich angekündigt, dass Logging kommt später noch und erst dann macht das an der Stelle auch Sinn.

Was kommt noch?

Ich habe wohl noch ein wenig zu tun. Mir sind ein paar Fehlerchen bekannt, wenn man einfach nur pping schreibt. Dann gibt das Tool eine Liste mit den Optionen aus, und die ist noch ein wenig “überarbeitungswürdig”.
Folgende Erweiterungen habe ich geplant:

  • Portranges
  • Logging
  • Implementierung in PowerShell-Commandlet

Mal schauen, wann ich dazu komme. Feedback ist immer gern gesehen. Ansonsten wünsche ich viel Spaß und hoffentlich nutzbringenden Einsatz.

Blogverzeichnis - Blog Verzeichnis bloggerei.de

2 Responses to “pping – Ein Ping auf Port-Ebene”

  1. » Blog Archive » FirewallLogReader Says:

    [...] sich mit Ports, Routen, Weiterleitungen und Logs beschäftigen muss. Das führte bei mir bereits zu PPing. Nun kommt ein weiterer Vertreter aus der Rige der Netzwerktools – [...]

  2. » Blog Archive » FirewallLogReader Says:

    [...] sich mit Ports, Routen, Weiterleitungen und Logs beschäftigen muss. Das führte bei mir bereits zu PPing. Nun kommt ein weiterer Vertreter aus der Rige der Netzwerktools – [...]

Leave a Reply