System.Net.NetworkInformation.Ping doesn't work if options with TTL are provided

We need to trace network route to our servers to debug player’s network connectivity problems, similar to what tracert cmd win utility does. For that we use simple code featuring Ping (System.Net.NetworkInformation.Ping) with gradually increasing TTL values:

public static async Task TraceRoute()
{
    string host = "8.8.8.8";
    short maxHops = 30;
    int timeout = 5000;
    
    byte[] sendBuffer = Encoding.ASCII.GetBytes("abcdefghijklmnopqrstuvwabcdefghi");
    
    using Ping ping = new();
    
    for (int ttl = 1; ttl <= maxHops; ttl++)
    {
        PingOptions options = new PingOptions(ttl, true);
        PingReply reply = await ping.SendPingAsync(host, timeout, sendBuffer, options);

        Debug.LogError($"{reply?.Address}: {reply?.RoundtripTime / 2} ({reply?.Status})");
    }
    
    Debug.LogError("Finished tracing");
}

It works as intended outside Unity (regular C# project). But When we try using it in unity (2023 and 6, both editor and build) it either ignores the TTL setting completely and ping the final destination from the get go or gives an exception “Unexpected socket error during ping request: MessageSize”. If we remove the options parameter (containing TTL) from call - it works fine in Unity as well, so it definitely has nothing to do with sendBuffer size. We also can’t use Raw ICMP sockets to perform ping manually as they require administrator priveleges in Windows which is unacceptable for us. Neither we can use Unity Ping as it doesn’t have TTL option.

So the question is: is this behaviour an expected one (limitations of current Unity backends) or does it have to do with something else? And can we perform network route tracing in some other way from our game build?

1 Like

That and the fact that Unity provides its own Ping class indicate that Unity’s (Mono’s) implementation of the .NET Ping feature differs respectively requires different code paths for some platforms as noted in the manual.

So yes, it seems expected behaviour.

I do wonder how something like traceroute would help you detect connectivity issues. If the client has Internet access, any connectivity issues that the client may be having is almost certainly to be with his own device (eg settings like manually overridden DNS service) or the device through which they access Internet (router, public wifi, ISP provided DNS).

A minor but still possible blockage could occur at the ISP level, in cases (countries) where ISPs perform traffic filtering or run custom DNS services to disallow the use of VPNs or other means to use the Internet uncensored.

On the route between the ISP and your endpoint about the only thing that could prevent the packets from reaching your endpoint would be a state-owned “firewall” (think: China, Russia, North Korea, … and others). Or a choking central traffic route but you’re unlikely to find these in highly populated areas or not unless some ship scrapes the seafloor with its anchor as was the case between Finland and the Baltics recently.

Thus for analysis of your problem my hunch is that it would be more valuable to record the device locale and its network config (DNS addresses, public IP in order to reverse identify the ISP) and any system settings (OS, latest update, installed software, etc). Then you may be able to identify common ground such as the use of the same security software or connecting from a specific region.