GNOME Bugzilla – Bug 629021
/etc/hosts modifications cause Python to detect localhost6.localdomain6 as FQDN
Last modified: 2010-12-17 04:53:58 UTC
NetworkManager now modifies /etc/hosts from 127.0.0.1 localhost 127.0.1.1 balanced-tree to 18.111.118.108 balanced-tree # Added by NetworkManager 127.0.0.1 localhost.localdomain localhost ::1 balanced-tree localhost6.localdomain6 localhost6 127.0.1.1 balanced-tree This has an undesirable side effect on applications that use Python’s socket.getfqdn(): $ python -c 'import socket; print socket.getfqdn()' localhost6.localdomain6 Previously this would return the real hostname (balanced-tree).
Hmm. So the reason you're getting 'localhost6.localdomain6' is that this *is* an FQDN. 'balanced-tree' is not an FQDN at all (it has no dots) so it makes sense that python returns 'localhost6.localdomain6' when you call getfqdn() instead of your machine's hostname. If you change your machine's hostname to an actual FQDN (like balanced-tree.mydomain) does the python call work correctly? Second, if after NM connects you remove the entire "::1" line, what does socket.getfqdn() return?
Hi Dan, thanks for looking into this. > If you change your machine's hostname to an actual FQDN (like > balanced-tree.mydomain) does the python call work correctly? My machine, like most machines, doesn’t have an “actual” FQDN; it’s a laptop using DHCP to get different addresses on different networks. But yes, if I give it a hostname containing a ., socket.getfqdn() gives me that hostname as expected. > Second, if after NM connects you remove the entire "::1" line, what does > socket.getfqdn() return? If I remove the entire ::1 line, socket.getfqdn() returns ‘balanced-tree’ like I expect. Alternatively, if I only remove ‘balanced-tree’ from the ::1 line, leaving the rest: ::1 localhost6.localdomain6 localhost6 then it also returns ‘balanced-tree’ like I expect. (The algorithm socket.getfqdn() uses is described at http://docs.python.org/library/socket.html#socket.getfqdn .)
I almost died a little when I read socket.getfqdn()'s procedure... :( Unfortunately I believe that socket.getfqdn() is pretty broken here, and it's probably not what you want to use. I'd suggest doing what that code does, but getting back the actual list of stuff that 'gethostbyname' or 'getaddrinfo' returns, and ignoring entries that contain 'localhost'. socket.getfqdn() just blindly returning the first thing with a dot doesn't inspire confidence... IPv6 is a bit whacky here since we still need ::1 to map back to your hostname so IPv6 apps work correctly, but glibc itself will just look for *any* loopback address (IPv4 or IPv6, it doesn't care) and return that when doing queries, apparently. So that's where the localhost6 junk comes from. Id' have thought that glibc would ignore entries on ::1 lines when it's asked to do IPv4 lookups, but apparently that's not the case.
> I almost died a little when I read socket.getfqdn()'s procedure... :( I agree that socket.getfqdn()’s algorithm isn’t exactly confidence-inspiring (but neither is an algorithm that looks for the hardcoded substring “localhost”). Anyway, since the entire point of editing /etc/hosts in the first place is to help out broken applications, like you said in your commit message: This helps out services that do a lookup on the machine hostname to determine the IP address, which while a broken behavior (since there are too many edge-cases) is pretty wide-spread and thus we should support it. , we should try to do so in such away that doesn’t break other applications. > IPv6 is a bit whacky here since we still need ::1 to map back to your hostname > so IPv6 apps work correctly, Hmm, in what way have IPv6 apps not been working correctly in the years before this change? At least Debian/Ubuntu have always used ::1 localhost ip6-localhost ip6-loopback > but glibc itself will just look for *any* loopback address (IPv4 or IPv6, it > doesn't care) and return that when doing queries, apparently. I’m not sure what you mean by this. We are not asking glibc to look for a loopback address (is that even possible to ask?), but rather for an address that matches the system hostname. glibc returns all matching addresses; it happens to put the IPv6 addresses before IPv4 addresses. If the intent is to appease applications that try to find the external IP by looking up the system hostname, then it seems to me we should make sure that the system hostname only resolves to external IPs, rather than a mix of external IPv4 with internal IPv6. (As an aside, I’m not sure this appeasement is actually a good idea to begin with. Looking up the address of the system hostname is also a common way to get an internal connection to the local machine, because the other ways require hardcoding “localhost” or hardcoding the loopback address in some particular family. And it seems poor to break those internal connections when an external dynamic IP address changes.)
Is this "supporting broken but allegedly widespread behavior" (to paraphrase a quote from an earlier post) at least optional ? If so, how can I turn it off ? By this I mean stopping the undesired modification of /etc/hosts specifically, not setting a persistent hostname via the 'keyfile' plugin (which then still gets written to /etc/hosts, which is what I'm trying to prevent). I have a working DNS infrastructure to resolve non-local host names and IP addresses, thankyouverymuch, and I'd rather not spend time reverse engineering why all of a sudden some component of my system decides to start being "helpful" by screwing with configuration files I thought I had control over. This so-called "feature" should have been off by default, and those who actually find it "helpful" should have been given the opportunity to opt in if they so desire. Instead, from a cursory google search, it looks like countless people are wasting 2-3 hours of their lives trying to figure out just WTF happened to their machines, and end up 'chattr +i'-ing their /etc/hosts file to make this annoyance go away... Thanks, --Mike
I'm seeing problems from the host name being added to the ::1 line when ipv6 is disabled in the network configuration. See the comment I added to a Fedora bug report on this before I tracked the issue to here: https://bugzilla.redhat.com/show_bug.cgi?id=643443#c4 It seems to break a number of applications in the particular circumstance that the system is not configuring ipv6. This doesn't really make sense when ipv6 is set to "ignore" in the applet. If ipv6 is enabled, then NetworkManager could add the host name with the external ipv6 address just like it does with the ipv4 external address and there is no problem. If ipv6 is enabled and there is no external ipv6 address, then you can claim that the configuration is broken anyway for applications that require hostname to resolve to a valid non-local-loopback ip address, just like the situation is in ipv4. But when ipv6 is disabled/ignored, if NetworkManager adds the hostname to the ::1 line in /etc/hosts anyway then that breaks everything that is using gethostbyname(gethostname) or equivalent to make sure that the hostname resolves to a valid non-local ip address. Can this at least be disabled for the ipv6 line when ipv6 is not being used?
We'll actually be removing the /etc/hosts update functionality from NetworkManager entirely because it's causing too many problems. You can still use the dispatcher script 'hostname' event to update /etc/hosts manually if you like, or you could install nss-myhostname to ensure the current hostname remains resolvable in all cases.