
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.)