Holger Stehle

Softwareentwicklung und -architektur

« Traceroute durchführen

Dieser Beitrag soll ein einfaches Tracerouting per C# nachbilden. Dazu implementieren wir im Folgenden eine einfache (und wie üblich auf das Wesentliche reduzierte) Klasse, welche die Funktionalität durch sukzessive Erhöhung des TTL-Wertes für schlichte Ping-Pakete umsetzt:

public class Traceroute : IDisposable {
    private static readonly byte[] buffer = [
        0x01, 0x03, 0x03, 0x07
    ];  // Daten zur Übertragung

    private readonly Ping ping = new();

    public IEnumerable<PingReply> Send(string hostNameOrAddress, int timeout = 3000) {
        // Paket mit TTL=1 initialisieren
        PingOptions pingOptions = new(1, false);

        PingReply pingReply = null;

        do {
            pingReply = this.ping.Send(hostNameOrAddress, timeout, Traceroute.buffer, pingOptions);

            // TTL für nächsten Schritt inkrementieren
            pingOptions.Ttl++;

            yield return pingReply;
        } while(pingReply.Status != IPStatus.Success);
    }

    public void Dispose() => this.ping.Dispose();
}

Die Verwendung gestaltet sich nun sehr einfach:

using(Traceroute traceroute = new Traceroute()) {
    foreach(PingReply pingReply in traceroute.Send("coders-online.net")) {
        Console.WriteLine(pingReply.Address);
    }
}

Um die entsprechenden Hostnamenzu den jeweiligen IP-Adressen zu ermitteln, kann beispielsweise die Methode Dns.GetHostEntry(…) dienen:

using(Traceroute traceroute = new Traceroute()) {
    foreach(string hostNameOrAddress in traceroute.Send("coders-online.net").Select(pR => {
        try {
            return Dns.GetHostEntry(pR.Address).HostName;
        } catch {
            return pR.Address.ToString();
        }
    })) {
        Console.WriteLine(hostNameOrAddress);
    }
}