Traceroute using UDP instead of ICMP?

56 views Asked by At

I am playing a game named "Planetside 2" and since a few days many users including me have high ping issues on a specific server, while others have not.

Therefore I wanted to try to traceroute / ping the Server IP, to find out which server node causes the high ping issues.

However it seems like the Server has some kind of Firewall that protects itself from being pinged by ICMP. Whenever I use "ping 69.174.216.23" (the ip is public on google so I can share it here) I get a timeout response.

So I used Wireshark to find out how the Game Client communicates with the Server and I found out that it's using UDP to ping the Server IP:Port.

However the Server has only a few Ports open for example for the Server IP: 69.174.216.23 The following ports are the only ones that it communicates with: { 20112, 20113, 20143, 20156, 20157, 20164, 20168, 20175 }

If I simulate that, sending a 1Byte UDP Packet to the Server it does not work, but if I add one of the Ports behind it 69.174.216.23:20112 and send a 1Byte UDP Packet I get a response.

I made a simple python script like that which works fine for that purpose:

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)

So since I am not able to traceroute or ping the Server IP using ICMP, I wonder if there is another possible way, like using an approach like I did with udp ip:port instead?

I searched around a bit and found out that you can udp traceroute but that uses its probe on UDP port number 33434 and since the Targets Server IP only listens / responds to a few ports (20112, 20113, 20143, 20156, 20157, 20164, 20168, 20175).

So I tried it this way:

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;
        }
    }
}

However here the issue is that as soon as i set udpClient.Client.Ttl = ttl; it doesn't get any anymore here UdpReceiveResult result = await udpClient.ReceiveAsync(); but if I comment the TTL out it works fine.

So now I am stuck and wonder if there is another possible way to traceroute the IP?

Doesn't matter which enviroment, linux, c#, python, powershell im fine with that, just to get an idea.

0

There are 0 answers