runtime: System.Net.Dns.GetHostAddresses() does not return all local ip addresses on Linux/.NET Core (it works in .NET Framework)

A call to

System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName())

returns only the first local IP address when running on Linux.

Tested with .NET Core 2.1.3

Here is the repro code:

using System;
using System.Net;
using System.IO;

namespace ConsoleDnsTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string hostname = Dns.GetHostName();
            Console.WriteLine("My hostname is '{0}'", hostname);
            Console.WriteLine("My ip addresses are:");
            foreach (var address in Dns.GetHostAddresses(hostname))
                Console.WriteLine("\t{0}", address);
        }
    }
}

Here is the (wrong) output I get on my Linux Debian 9:

root@inim-test:~# dotnet ConsoleDnsTest.dll
My hostname is 'inim-test'
My ip addresses are:
	172.22.28.132
root@inim-test:~#

If I run the very same code under Mono, it works, and this is the correct output I get:

root@inim-test:~# mono ConsoleDnsTest.exe
My hostname is 'inim-test'
My ip addresses are:
	172.22.28.132
	172.22.28.133
	172.22.28.134
	172.22.28.138
	10.128.0.1
root@inim-test:~#

On Windows both .NET Core and .NET Framework versions work well.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 30 (25 by maintainers)

Most upvoted comments

GetAllNetworkInterfaces() (and many other NetworkInfo functions) are bloated 😭 It would be interesting to see getifaddr(). But point taken.

I have did quick test on Windows 10 system with 2 interfaces. My second NIC is private network and the address is NOT in DNS. Running example above gives that IP address as well. Interestingly, IPv4 loopback (127.0.0.1) is not in the list. (nor ::1) If we want consistent behavior, adding special case for own name makes sense to me. (instead of relying on external DNS)

We should have our APIs be able return all IP addresses which include all of those bound to network interfaces as well as “127.0.0.1” and “::1” (loopback adapter addresses).

Note that on systems supporting IPv6 this will include the link-local addresses as well, i.e: from my “ipconfig /all” on my Windows machine:

fe80::24c4:1dc4:c84e:aa99%5
fe80::cc10:d2a8:c0da:21c0%17

Please correct me if I’m wrong, but the desired behavior on all OSes is:

That “best” behavior appears to be to have all the loopback adapter IP addresses (i.e. 127.0.0.1) as well as the other IP addresses assigned to all network interfaces in the system.

Unless someone express disagreement here I’ll try to look into it.

So the question now is whether we adopt the mono implementation or not? @davidsh and @wfurt

Are you talking about changing our implemention in .NET Core to do the below?

The Mono implementation of GetHostAddresses() is very different. If the hostname passed to the function matches the local hostname, then the function ends up calling a specific internal routine which enumerates local ipaddresses through a SIOCGIFCONF ioctl call on a local socket. I believe that the same approach should be taken here, or at least make use of getifaddr(), although I’m not sure if this call is available on any unix flavor or linux version.

The bottom line is that we should try to get the best and consistent behavior across all platforms (Windows, Linux, Mac). That “best” behavior appears to be to have all the loopback adapter IP addresses (i.e. 127.0.0.1) as well as the other IP addresses assigned to all network interfaces in the system.

@stephentoub @geoffkizer Comments?

This is because it depends on network configuration @ManickaP. Local hostname may or may not be in DNS. And it also depends on what DNS server you are pointing at. According to documentation https://docs.microsoft.com/en-us/dotnet/api/system.net.dns.gethostaddresses?view=netcore-3.0#System_Net_Dns_GetHostAddresses_System_String_

The GetHostAddresses method queries the DNS subsystem for the IP addresses associated with a host name. If hostNameOrAddress is an IP address, this address is returned without querying the DNS server.

So I’m not sure if it is reasonable to expect all local addresses if they are not in DNS. I think it works on Windows because it is part of name resolution service.

If we want to change this, I think we should take path @bpress suggested. That would make it more consistent across OSes. Also as Mono will blend in in 5.0 it would be reasonable to preserve their behavior. That should probably also work on OSX.

GetHostXXX will get incorrect result.You can use System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces() to get ip address.