pping – Ein Ping auf Port-Ebene

pping, Download bei heise

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.

udp (u)

Wenn dieses Flag mit angegeben wird, wird anstelle einer TCP-Verbindung eine UDP-Verbindung genutzt.

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)

ports (p)

Die Nummer des Ports, der geprüft werden soll. Wenn mehrere Ports geprüft werden sollen, müssen die Werte durch Komma voneinander getrennt werden. Der Wert pro Port 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.

37 Gedanken zu „pping – Ein Ping auf Port-Ebene“

  1. Hallo,
    genau so ein tool benötige ich.
    Ich habe Net Framework 4.51 installiert und versuche nun die anwendung unter Windows 7 zu starten.
    Dann wird kurz eine Konsole geöffnet, aber sofort wieder geschlossen.
    Was mache ich falsch?

    1. Hallo Rainer,

      geh‘ folgendermaßen vor. Wenn Du die Dateien z.B. in C:\Program Files\pping entpackt hättest, dann öffne eine Konsole und gehe in ihr in diesen Ordner. Dann kannst Du pping eingeben und los gehts. Alternativ kannst Du den Pfad auch Deiner Umgebungsvariablen hinzufügen. Dann reicht es, einfach nur eine Konsole aufzumachen. Wenn Du Hilfe brauchst, schreib noch mal.

      sprinter

  2. Hallo,
    durch Zufall auf pping gestoßen, echt super.
    Eine Frage habe ich dennoch, gehen auch IPv6, ich bekomme es nicht hin.

    Grüße Tom

  3. super tool, genau das was ich gesucht hatte, aber leider bekomme ich wenn CLOSED kommen sollte dies hier:
    c:\temp\pping>pping.exe -address=10.238.232.172 -ports=1352 -timeout=1 -repeats=
    1
    Starting pinging host 10.238.232.172 on TCP port(s) 1352 1 times:

    Unhandled Exception: System.Net.Sockets.SocketException: Es konnte keine Verbind
    ung hergestellt werden, da der Zielcomputer die Verbindung verweigerte 10.238.23
    2.172:1352
    at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)
    at System.Net.Sockets.TcpClient.EndConnect(IAsyncResult asyncResult)
    at s2.s2Utils.Logic.Base.Utilities.NetworkUtil.IsPortOpened(String host, Int3
    2 port, Int32 timeout, Boolean useUdp)
    at codingfreaks.pping.Ui.ConsoleApp.Program.c__DisplayClass27.b__18(I
    nt32 port)
    at System.Collections.Generic.List`1.ForEach(Action`1 action)
    at codingfreaks.pping.Ui.ConsoleApp.Program.Main(String[] args)

    haben Win7 in Virtual Desktop Umgebung im Einsatz. Ich hoffen es kann mir geholfen werden. Danke im Voraus.

    Gruß Lutz

  4. Hallo zusammen,
    ich bin auf einen Bug gestoßen und wollte fragen ob das richtig ist oder ob es ein update geben wird:

    mache ich eine tcp pping auf zdf.de auf port 80 ist alles ok
    pping.exe -a=zdf.de -p=80 -t -res -r=2 -w=1500 -tim=1

    ==> Port ist offen
    mache ich hingegen einen Ping auf port 81 welches zu ist:
    pping.exe -a=zdf.de -p=81 -t -res -r=2 -w=1500 -tim=1

    sollte doch geschlossen zurück kommen

    dies macht pping aber nicht, es kommt eine art Fehlermeldung mit der ich nichts anfangen kann.
    ausser das die gegenstelle nach angemessener zeit nicht antwortet. Die nachfolgenden Einträge sagen mir nichts.

    Könntet ihr bitte mal über dieses Ergebniss schauen und mir ein kurze Rückmeldung geben. DANKE

    leachim

    1. Hallo leachim,

      danke für Dein Feedback. Die neue Version 1.2.12 ist unter http://www.codingfreaks.de/files/pping_1_2_12.7z fertig. Sie behebt das Problem, dass durch Fehler bei Einsatz von „-res“ auftauchten. Bitte beachte, dass Du aktuell mit „-r=2“ sagst, dass 2 Requests geschickt werden sollen und mit „-t“, dass Du endlos Requests schicken möchtest. Die beiden Einstellungen widersprechen sich. „-res“ macht übrigens keinen richtigen Sinn, wenn Du den DNS-Namen schon weist. Macht es dann nur langsamer.

      Ich nutze immer gern die Kurzschreibweise „pping zdf.de 80 -t -as“. Das „-t“ macht zwar endlos, das „-as“ stoppt aber beim ersten erfolgreichen Connect.

      Gruß, sprinter

  5. Per Zufall auf diesen nützlichen Helfer gestossen :)
    die Ports können ja mit Komma getrennt aneinender gereiht werden.
    nun folgende Frage:
    geht auch Port Range? also 80-88
    geht auch eine Kombination? also 80,88,8000-8080

  6. Super tool, vielen Dank dafür! Praktisch auch für Spezialdienste die auf ICMP-Pings nicht antworten.

    Jedoch habe ich ein seltsames Verhalten festgestellt, ich weiß nicht ob es ein Bug ist oder ob irgendwelche Caches im Spiel sind. Pinge ich eine Adresse erfolgreich an und ziehe anschließend das Netzwerkkabel wird mit beim nächsten mal immer noch eine erfolgreiche Verbindung angezeigt. Der Rechner ist definitiv offline.

  7. Hallo sprinter,

    für tcp funktioniert das Tool super. Leider zeigt er mir bei jedem udp port den ich remote prüfe „OPEN“ an. Egal ob die Ports dicht sind oder nicht. (Beispielaufruf: „pping.exe -address=192.168.240.61 -ports=1333 -udp“)

  8. Hi,

    hätte ein paar Erweiterungsvorschläge:
    1.) Anzahl der Coutns als Errorlevel zurückgeben.
    2.) Open als Errorlevel 0 zurückgeben
    Close als Errorlevel 1 zurückgeben
    3.) Verhalten von 1 oder 2 per Parameter konfigurierbar

    LG Andreas

  9. Super Sache.
    Aber kann es sein das der Timeout nur auf Portebene funktioniert und bei nicht vorhandenen Adressen nicht funktioniert bzw. viel länger als eingestellt ist?
    Könntest du den Timeout (oder evtl. einen zusätzlichen Parameter) auch auf Adressebene einbauen?

    1. Hallo Hans. Ich habe bereits Ähnliches festgestellt, allerdings scheint es hier Abhängigkeiten zur Windows-Konfig zu geben. Ich versuche, das noch genauer zu ermitteln. Ich nutze ja leider nur die Basis-Technik von .NET.

  10. Hallo sprinter,

    danke erst mal für das sehr hilfreiche Werkzeug.
    Allerdings sind jetzt viele verschiedene Versionen zum Download angeboten.
    Bei Heise liegt die 1.2.2, in deinem Blog oben die 1.4.4 und unter Tools die aktuelle Version 1.5.4.

    grüße vom it-frosch

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *