Traceroute mit UDP statt ICMP?

Traceroute mit UDP statt ICMP?

Ich spiele ein Spiel namens „Planetside 2“ und seit einigen Tagen haben viele Benutzer, mich eingeschlossen, Probleme mit einem hohen Ping auf einem bestimmten Server, während dies bei anderen nicht der Fall ist.

Daher wollte ich versuchen, die Server-IP per Traceroute/Ping zu verfolgen, um herauszufinden, welcher Serverknoten die Probleme mit dem hohen Ping verursacht.

Es scheint jedoch, als ob der Server eine Art Firewall hat, die ihn vor ICMP-Pings schützt. Immer wenn ich „ping 69.174.216.23“ verwende (die IP ist bei Google öffentlich, daher kann ich sie hier teilen), erhalte ich eine Timeout-Antwort.

Also habe ich Wireshark verwendet, um herauszufinden, wie der Spieleclient mit dem Server kommuniziert, und ich habe herausgefunden, dass er UDP verwendet, um den IP:Port des Servers anzupingen.

Der Server hat jedoch nur wenige Ports geöffnet, beispielsweise für die Server-IP: 69.174.216.23. Die folgenden Ports sind die einzigen, mit denen er kommuniziert: { 20112, 20113, 20143, 20156, 20157, 20164, 20168, 20175 }

Wenn ich das simuliere, indem ich ein 1-Byte-UDP-Paket an den Server sende, funktioniert es nicht, aber wenn ich einen der Ports dahinter, 69.174.216.23:20112, hinzufüge und ein 1-Byte-UDP-Paket sende, erhalte ich eine Antwort.

Ich habe ein einfaches Python-Skript wie dieses erstellt, das für diesen Zweck gut funktioniert:

import socket
import time

def udp_ping(destination_ip, destination_port):
    try:
        # Create a UDP socket
        udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        # Set a timeout for receiving responses (in seconds)
        udp_socket.settimeout(5)
        
        # Record the time just before sending the message
        start_time = time.time()
        
        # Send a message to the destination
        udp_socket.sendto(b'PONG', (destination_ip, destination_port))
        
        # Receive a response
        response, address = udp_socket.recvfrom(1024)
        
        # Record the time when the response is received
        end_time = time.time()
        
        # Calculate round-trip time (RTT) in milliseconds
        rtt_ms = (end_time - start_time) * 1000
        
        print("Received response from {}: {} (RTT: {:.2f} ms)".format(address, response.decode(), rtt_ms))
    
    except socket.timeout:
        print("No response received.")

    finally:
        udp_socket.close()

destination_ip = '69.174.216.23'
destination_port = 20112 
udp_ping(destination_ip, destination_port)

Da ich also nicht in der Lage bin, die Server-IP über ICMP zu verfolgen oder anzupingen, frage ich mich, ob es eine andere Möglichkeit gibt, beispielsweise einen Ansatz wie den, den ich stattdessen mit UDP IP:Port verwendet habe?

Ich habe ein bisschen gesucht und herausgefunden, dass Sie ein UDP-Traceroute verwenden können, das seine Sonde jedoch auf der UDP-Portnummer 33434 verwendet und da die Zielserver-IP nur auf wenigen Ports (20112, 20113, 20143, 20156, 20157, 20164, 20168, 20175) lauscht/antwortet.

Also habe ich es folgendermaßen versucht:

using (UdpClient udpClient = new UdpClient())
{
    udpClient.Client.ReceiveTimeout = 3000;

    for (short ttl = 1; ttl <= maxHops; ttl++)
    {
        string message = $"Traceroute[{ttl}]: ";

        // Set the TTL option for the UDP socket
        udpClient.Client.Ttl = ttl;

        // Send a UDP packet to the target
        udpClient.Send(new byte[1], 1, targetIp, targetPort);

        message += $"UDP packet sent to {targetIp}:{targetPort}";

        try
        {
            // Receive response from the target or an intermediate router
            UdpReceiveResult result = await udpClient.ReceiveAsync();

            IPAddress senderIp = result.RemoteEndPoint.Address;

            if (senderIp.Equals(targetIp))
            {
                targetReached = true;
                message += " - Target reached";
            }
            else
            {
                message += $" - Received response from {senderIp}";
            }
        }
        catch (SocketException ex)
        {
            if (ex.SocketErrorCode == SocketError.TimedOut)
            {
                message += " - Timeout";
            }
            else
            {
                message += $" - Error: {ex.Message}";
            }
        }
        catch (Exception ex)
        {
            message += $" - Error: {ex.Message}";
        }

        if (targetReached)
        {
            break;
        }
    }
}

Das Problem hier ist jedoch, dass es, sobald ich udpClient.Client.Ttl = ttl;es einstelle, nichts mehr bekommt, UdpReceiveResult result = await udpClient.ReceiveAsync();aber wenn ich das TTL auskommentiere, funktioniert es einwandfrei.

Jetzt stecke ich also fest und frage mich, ob es eine andere Möglichkeit gibt, die IP-Adresse zurückzuverfolgen?

Egal, welche Umgebung, Linux, C#, Python, Powershell, ich bin damit zufrieden, nur um einen Eindruck zu bekommen.

Antwort1

Traceroute-Sonden erfordern nicht, dass der Server etwas geöffnet hat, da ihr Zweck darin besteht, Antworten vomdazwischenliegendRouter, nicht vom Endhost; sie erreichen den Endhost nie wirklich. Der tatsächliche Typ der Sonde spielt keine Rolle; alle führen zur gleichen Art von Antwort.

Aber auch wenn die Probe UDP war, ist die Antwort von Traceroute-Probes kein UDP-Paket und wird nicht über Receive() übermittelt – stattdessen erhalten Sie immer ein ICMPTTL Exceeded FehlerPaket, das möglicherweise als Ausnahme gemeldet wird oder eine spezielle Socket-Option erfordert.

(Die einzige Ausnahme hiervon ist die „letzte“ Probe, die eine ausreichend große TTL hat, um den Host tatsächlich zu erreichen. Wenn der Host nicht antwortet, bleibt die Spur an diesem Punkt hängen, aber Sie sollten für diese Situation Timeouts haben, weil ZwischenrouterAuchdürfen nicht antworten.)

verwandte Informationen