Internet Draft: Let 'localhost' be localhost
tools.ietf.org
tools.ietf.org
First, the lack of confidence that "localhost" actually resolves to
the loopback interface encourages application developers to hard-code
IP addresses like "127.0.0.1" in order to obtain certainty regarding
routing. This causes problems in the transition from IPv4 to IPv6
(see problem 8 in [draft-ietf-sunset4-gapanalysis]).
That does remind me of the times I was dealing with weird connection issues in some critical services.It turned to be related to the use of "localhost" in the configuration. It resolves to ipv6 on some systems and that breaks everything because the target app is only listening to the ipv4 address.
Went as far as removing all references to localhost and added lint errors in the configuration system so that noone could ever be able to give localhost as a setting in anything.
If you're on a POSIX system, I'd argue that this is a bug in the client. Typically, the client should call getaddrinfo(3); as part of that, the application would either specify directly that it's only interested in AF_INET results, or just filter out non-AF_INET results.
(Further, if you support IPv6 in the client, and thus request such results from getaddrinfo, you should skip to the next result if the connection fails.)
On the server, you can also bind to both the IPv4 and the IPv6 addresses. If you listen to ::, you should get IPv4 connections too. (Through this[1] mechanism.)
[1]: https://en.wikipedia.org/wiki/IPv6_address#Transition_from_I...
The IPv4-mapped IPv6 addresses thing is a terrible idea that ends up turned off everywhere it makes a difference. Like all of these "transition" ideas, it tries to help, but it just hurts by causing admins/ops/devs to just make sure ipv6 is off everywhere they run into it.
If all IPv6 was just opt-in everywhere, we wouldn't need all significant applications to detect and work-around broken ipv6 (in the local network, in the ISP, in the server, in the peer application). If IPv6 was only explicitly enabled, and fully consciously handled when it was, then practically everything would have opted into IPv6 years ago. As it is, things started getting IPv6 support around 2005/2006, and then disabling it around 2007/2008 because it was fake/broken ipv6 in too many places (windows teredo, 6in4, etc).
OS X had to disable IPv6 in one release and then re-enable after implementing happy-eyeballs in everything. Firefox had to do that. I know about these cases in particular, but I bet all significant network applications had to have a bunch of "detect broken IPv6" code added. Major websites had to disable IPv6 on their main domains (and sometimes added an "ipv6." subdomain). The reason was that some people had broken IPv6 and their computer would try to use it to access their site and fail (but other ipv4 only websites worked). Things are getting better now, but it was a 10 year set-back. So much time and effort could have been saved if people with good-intentions didn't add automagic transition technologies and just waited for IPv6 to be explicitly added on both ends.
So in this sense all were doomed to fail.
Remarkably the CGN devices are actually the best practical idea for this. Fake IPv4 addresses for the dumb ossified clients and that's it. If something important enough for the end user doesn't work, they'll finally upgrade.
Some US corporations did this already, rather than fuss with being "dual stack" and potentially introducing new IPv4-only services or systems, they switched wholesale to IPv6 and add converters at the edges. By choosing to do this they get most of the benefits of a future IPv6-only Internet today. For example, numbering internally is a breeze, they can auto-number almost everything because the address space is so vast there is no need to "plan" any of it.
Lots of other US corporations are still IPv4-only, indeed that's why the Google graph earlier has a distinct weekday vs weekends / holidays step change in it. At home a very large proportion of people in industrialised countries have IPv6, major ISPs supply it, common household routers understand how to use it, every modern OS groks it. But at work IPv6 is often disabled by policy, in favour of cumbersome IPv4 because that works and changing things at work is forbidden.
And it's finally starting to catch on, 10 years late: Google's primary web domains, Facebook, AWS, Comcast and Time Warner cable internet in the US, most LTE cell service in the US.
Some systems, like OpenBSD, don't even support disabling IPV6_V6ONLY and therefore don't support dual binding at all. OpenBSD contentiously argues that dual binding is likely to lead to security exploits as applications that naively bind to "::" might not expect to de-queue IPv4-mapped IPv6 addresses, consequentially possibly breaking their local access control logic. For example, they may setup firewalls rules that restrict access to the IPv6 port but forget to set the same restrictions on IPv4 ports.
I'm not sure I agree with OpenBSD's approach, but in any event applications should explicitly disable the IPV6_V6ONLY socket option if they're relying on dual binding. Ideally they should use two different sockets; one for each address family. If the application stack doesn't make it easy to listen on multiple sockets, that's a strong hint that the design is broken.
Make it work like expected.
Especially when changing infrastructure like IPV4->IPV6 - don't break existing userbase code! (This is a fundamental precept of Linux development.)
And your comment about never breaking existing userbase code is as ridiculous as it is unreasonable. This would only be a reasonable expectation if only correct code were possible to run. Since it's possible to run broken code (as this anecdote demonstrates) then it must be possible to fix the system even if that breaks some poorly written, but popular systems.
Does anyone want a world of e.g. Windows where decades old bugs have to be replicated because we can't dare break programs so old all the authors are retired or dead? I don't. Backwards compatibility has a cost and I'm not willing to pay it unconditionally.
Expected by code or by the progammer(s)?
That said, strong API guarantees are the way, documentation should note the bug, introduce a fixed version for the API, maybe schedule deprecation in 10-15 years, and carry on with life.
It's not worth it to hunt down every client and make them fix your honest mistake.
https://en.m.wikipedia.org/wiki/Happy_Eyeballs
Can be a source of race conditions.
But a lot of standard libraries (including parts of Java and Go) get this wrong, and pick exactly one IP address arbitrarily. When you combine a buggy client with a buggy server, and their preferences for IPv4/IPv6 disagree, then all hell breaks loose.
These are the open bugs I'm aware of:
The "localhost" interface will either designate the ipv4 127.0.0.1 interface or the ipv6 ::1 interface. That's the realm of undefined behavior and system specifics.
This whole IETF draft looks like a mess. They should reserve the names localhost4 and localhost6.
absolutely not true. Neither for IPv4 nor IPv6, where it's even the default to have a multitude of addresses on an interface.
> The "localhost" interface will either designate the ipv4 127.0.0.1 interface or the ipv6 ::1 interface. That's the realm of undefined behavior and system specifics.
no it won't. My loopback (lo) interface has both 127.0.0.1 and ::1 as its addresses.
Eh?
$ ifconfig lo
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)Just to point out, while the behaviour of any one OS is a useful data point for the discussion, it's not super useful to say "because OS 'foo' does things in a certain way, a well used programming language should limit it's design to that OS's way of doing things." :)
Hmmm, I guess I'm trying to say that (at least) Go should be fairly OS agnostic about this.
My guess is that it was some hack they tried to disable IPv6, but aside from the insane load it added to the DNS infrastructure, the other result is that if these machines talk to a malicious resolver, their traffic destined for the loopback interface could end up going anywhere and being captured by anyone.
Great job!
I suspect that removing the "localhost." record was nothing to do with IPv6 and everything to do with a corporate policy to not have anything other than the Microsoft default contents in hosts files, possibly because of concerns relating to malware prevention. The problem is possibly the result of the default hosts content changing in Windows NT 6.1.
* https://support.microsoft.com/en-gb/help/972034/
As of Windows NT 6.1, lookups of "localhost." are handled internally within (as I understand) the DNS Client, and never require inspecting a hosts file or sending a query to a DNS server. So the new default hosts file content no longer contains a "localhost." record. But use the Windows NT 6.1 or later default hosts file content on earlier versions of Windows NT, and one will see "localhost." queries being sent by the DNS Client to a server.
Handling "localhost." within the DNS Client is -- reportedly -- so that the DNS Client can inspect the local machine's protocol support and only return non-empty AAAA and A resource record sets if IPv6 or IPv4 is actually enabled on the machine.
You just found a major bug in the application and should complain to the developer. Applications that do not support IPv6 are simply broken and should be avoided at all cost by now.
Which I find to be a very practical solution for connecting to localhost over https, it frees you from having to install a self-signed certificates/CAs on your machine.
https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016...
Standards, practices, tradition, culture. They mean nothing when a devops lead has commit rights to the ansible playbook and a will to deliver a fix in 5 seconds flat.
It's easy to type and easy to remember and should always do a good job of expressing intent of usage.
If they do use your domain name then they have to trust that nobody has subsequently seized the name in court, nobody has hacked or DDOSed your nameservers, there's not an interruption of network connectivity between them and your servers, and that the ISPs forwarding the DNS queries didn't substitute a different response for the one you intended to return (since currently your leaf records aren't DNSSEC-signed).
Being able to test locally while using the full internet name resolution system is a valuable thing as well. Though if this is your use case I wouldn't trust lacolhost: register your own domain.
(I feel like "ocalhost", "locahost", or "localhos" would be more common typos.)
The other commentators here are right, it won't solve a good number of the issues in this proposal, but works well if you need something for developing against subdomains.
http://www.cryonet.org/cgi-bin/dsp.cgi?msg=6289
Henson: (patiently) It's at 127.0.0.1. This is a loop back address. This is a troll.
Lieberman: what's a troll?
Henson: it comes from the fishing where you troll a bait along in the water and a fish will jump and bite the thing, and the idea of it is that the internet is a very humorous place and it's especially good to troll people who don't have any sense of humor at all, and this is a troll because an ftp site of 127.0.0.1 doesn't go anywhere. It loops right back around into your own machine.
Annoying.
I think it's a legend.
That was part of it. What's weird is that the Mozilla suite had the same thing before firefox even existed, in many ways firefox was a step backward. I believe opera did this years earlier too.
Old wisemen may refer to it as a fire-breathing reptile, others a bird clad in flames. And despite suffering from declining market share in recent years, prophecy foretold that it will one day rise from the red ashes, stronger and more resilient than ever!
(Apologies for running away with the joke)
anoying
I have found that failing to include a localhost entry in the HOSTS file can lead to some strange behavior.
If there are "computers" out there that have no /etc/hosts or deny the computer's owner access to it, then maybe it might be time for an Internet Draft from Joe User.
There should always be a mechanism for the user to override the internet DNS. And applications should continue to respect it.
Spent the better part of a year just remembering to not type "www." until one day they made the domain redirect to the canonical name (breaking both).
After asking around a bit, someone showed me where the Windows equivalent of /etc/hosts was, and lo-and-behold, there was an outdated entry for www.hotmail.com there. Deleting the offending line fixed the problem.
Desktop computers are actually the odd one out in letting people manually override DNS -- if you want to fix the DNS for a phone or smart tv or thermostat or video game console, you need to configure DHCP and a resolver on a router in the middle.
Which is, bizarrely, etc\hosts (somewhere in C:\Windows\). I've always wondered why they felt the need to make an 'etc' folder just to have the hosts file in it.
and, if i remember correctly from my windows days, not only did they make the whole 'etc' folder just to put the hosts file in, the strangely-named 'drivers' folder didn't have anything else in it either.
It's not running. But ... you could have fun with that.
This enables the following on Solaris and similar systems:
$ ping elvis
elvis is aliveRight now, section 3 of this draft would prohibit all SRV queries for localhost, which may hinder development and deployment of a SRV based application. That's an immediate problem.
But not only are there existing applications to which it is immediately applicable - it is a design error in HTTP that plain address records are used for resolution. One day this will be corrected, in which case measures like this should continue to apply.
* http://jdebp.eu./FGA/dns-srv-record-use-by-clients.html
But what should such a standardized SRV lookup for _proto1._proto2.localhost. yield as the answer? For starters, what port numbers?
For ports we have the list of well-known services maintained by IANA, for which an extract appears on many systems in /etc/services. Local configuration can adjust as necessary.
Both for safeguarding internal use, and making a global TLD reserved on the global DNS zones. You'll find organisations using in production .local .dev (Taken by Google on 2014-11-20, followed by .app in 2015) *.zone (Taken by a LLC on 2014-01-09 ) as internal domains, with potential conflicts with the Internet's DNS resolution.
More importantly .dev [1] and .zone [2] are now valid TLDs, so watch out people!
macOS has been using .app as its application extension for decades. Now when you want to search for a specific app on the browser you'll have to be more careful.
The fact that they allowed .dev, which is a fairly common TLD for development, is pretty unbelievable.
I haven't seen any evidence that by allowing companies to register these TLDs we've brought forth some kind of improvement or benefit to users.
There's a recent issue with TLDs that makes me particularly angry. There's ongoing work on this homenet spec. Originally it proposed using .home to route exclusively within the local network. But since .home is already used by a large number of people for private purposes, they changed it to .home.arpa. How the heck have we gotten to the point where we can justify allowing .google as a TLD, but we can't reserve something nice and short for non-companies?
* http://jdebp.eu./FGA/dns-use-domain-names-that-you-own.html
No that's not a typo
However, I expect many application developers to mistakenly assume that only 127/8 and ::1 are valid loopback interface addresses.
As an end user, I use /etc/hosts not only as a substitute for DNS but also in addition to it.
For example I may block/redirect a mostly noxious domain via wildcard in a customized root zone file on computer1 (an "authoritative nameserver" for a "recursive cache" that serves computer2) but then edit the HOSTS file on computer2 to make an impromptu single exception for a particular subdomain. Ideally I would prefer to run local DNS and local proxies on computer2 like computer1, but with many of today's "computers" this is infeasible; so computer2 might use computer1 for name lookups, routing, etc., as suggested by another commenter.
There are other ways to make these adjustments but editing a text file that is always present and in the same location is quick and dirty, immediate and particularly easy. This is only one use. HOSTS is quite useful in a variety of situations.
IMHO, the use of local computer1 as a gateway/server for another such as local computer2 only becomes even more important as we see a rise in "computers" that are resistant to manual control by the end user, such as those mentioned by another commenter.
Without having the ability to do IP forwarding, packet filtering, run localhost DNS servers and localhost proxies, as an end user I would struggle to control the internet traffic[1] of many of today's "computers" where the manufacturers have preconfigured them to serve their own interests and attempted to lock users out from making changes.
1. e.g., ad blocking, disabling incessant phone home behavior and other bandwidth conservation measures
In short, I need to be able to control the address for "localhost" without relying on or having to worry about DNS. HOSTS achieves that without the complexity and politics of DNS.
* dnscache from djbdns has handled "localhost." queries internally all along, since 1999. It maps "localhost." to 127.0.0.1 and bgack again. Various people, including me, have since added code to do the same thing with the mappings between "localhost." and ::1. (http://jdebp.eu./Softwares/djbwares/guide/dnscache.html) I implemented implicit localhost support in my proxy DNS servers for OS/2, as well.
* It is conventional good practice to have a db.127.0.0 and a master.localhost "zone" file on BIND that do this. This is in Chapter 4 of the book by Albitz and Liu, for example.
* Unbound has built-in "local zone" defaults mapping between "localhost." and both 127.0.0.1 and ::1.
On the other hand, this proposal explicitly rules out all of the aforementioned existing practice, by demanding that both proxy and content DNS servers instead return "no such domain" answers for the domain name "localhost.". That seems like a fairly pointless deviation from what is fast approaching two decades of existing practice, for which no rationale is given and none is apparent.
Took a while to track that was down. Was both bewildering and sort of satisfying to figure it out in the end.
Are there any software or networking patterns that currently rely on localhost _not_ resolving to the loopback?
EDIT: The RFC mentions that MySQL currently differentiates between the two, but that's it.
www.localhost.mydomain.com?
The domain "localhost.", and any names falling within ".localhost.",
are known as "localhost names". Localhost names are special in the
following ways […]
Is this not implemented on macOS or am I just misunderstanding? ~ ping test.localhost
ping: cannot resolve test.localhost: Unknown host
~ ping localhost.test
ping: cannot resolve localhost.test: Unknown hostThe RFC draft is talking about domains ending in ".localhost.", not any domain containing ".localhost." (so abc.localhost.example.com wouldn't be localhost).
All domains have to end with a period, or they're not fully qualified. "example.com" could mean "example.com.my.domain." if whatever you're using uses "my.domain." as the root. But "example.com." is always "example.com."
Nowadays that feature isn't used very often, as the root of domains not ending in a period is usually assumed to be in the root zone.
Or software relying on badly written DNS resolvers.
> First, the lack of confidence that "localhost" actually resolves to the loopback interface encourages application developers to hard-code IP addresses like "127.0.0.1" in order to obtain certainty regarding routing. This causes problems in the transition from IPv4 to IPv6 (see problem 8 in [draft-ietf-sunset4-gapanalysis]).
>Second, HTTP user agents sometimes distinguish certain contexts as "secure"-enough to make certain features available. Given the certainty that "127.0.0.1" cannot be maliciously manipulated or monitored, [SECURE-CONTEXTS] treats it as such a context. Since "localhost" might not actually map to the loopback address, that document declines to give it the same treatment. This exclusion has (rightly) surprised some developers, and exacerbates the risks of hard-coded IP addresses by giving developers positive encouragement to use an explicit loopback address rather than a localhost name.
>This document hardens [RFC6761]'s recommendations regarding "localhost" by requiring that DNS resolution work the way that users assume: "localhost" is the loopback interface on the local host. Resolver APIs will resolve "localhost." and any names falling within ".localhost." to loopback addresses, and traffic to those hosts will never traverse a remote network.
Mods: can RFC be removed from the title? [Edit: thanks for updating the title!]
Very roughly, a Standards Track document in the IETF goes through four stages:
1. Someone submits an I-D as an individual. Literally anyone can do this and such a document carries no weight.
2. A working group (WG) "adopts" the I-D and proceeds to work on the document as a group. The document still carries no weight at this stage.
3. The I-D is published as an RFC. When this happens, the document finally has real weight. The document can no longer be changed, although it can be updated or obsoleted by another RFC.
4. When the RFC matures, it can be promoted to an Internet Standard.
Let localhost be localhost is still in the first stage.
For example many of you will have used Let's Encrypt, the whole of Let's Encrypt is built upon a standard issuance and management protocol, ACME. But ACME is still only an Internet Draft, albeit it's likely to go to RFC before the end of this year. So it didn't matter that in your view it "has no weight", it had millions of people using it.
If this I-D takes off and is widely accepted by, say, Microsoft and Apple, even if it never becomes an RFC it has a real effect. On the other hand, if it becomes a standards track RFC but Apple decides to ignore it and never promise that "localhost is localhost" in their operating systems then it's worthless despite the "Standard" tag.
First, if you publish a container's port in docker, such as with the -p flag, e.g.,
docker run --rm -p 8080:80/tcp nginx:latest
Docker will listen, on the host, on ::; it will accept IPv4 connections on that bind. (Through IPv4-mapped IPv6 addresses[1], which is a transition mechanism.)But even if we force Docker to bind to only IPv4, curl will still work:
docker run --rm -p 127.0.0.1:8080:80/tcp nginx:latest
curl will attempt an IPv6 connection first in this case (since localhost resolves to ::1), and fallback when it fails (since localhost also resolves to 127.0.0.1). If you pass -v to curl, it will tell you as much: * Trying ::1...
* TCP_NODELAY set
* connect to ::1 port 8080 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
Perhaps there is some pathological case where Docker and curl and IPv6 and localhost don't all work together, but one would need more information to tell. But it doesn't "basically break" Docker.[1]: https://en.wikipedia.org/wiki/IPv6_address#Transition_from_I...
Watch this ASCII recording to see the issue
https://asciinema.org/a/xM8m0iqOepkSwCRBTIP9hYXGU
We run into the issue on RPi/Raspbian - curl hangs indefinitely. I had someone report to me that he couldn't access localhost:8080 in a web-browser using a Docker container for FaaS because it was resolving to this IPv6 - he was on Arch Linux.
Perhaps you can reverse your hasty down-voting?
It's unfortunate, however, that the creator of the video did not capture the output of curl -v, or perhaps even an strace. The logic presented in my first post is nonetheless what curl does, and should apply, so something else is going wrong here. I still think there's a wide difference between "in this particular case, something is causing the IPv6 address to hang" and "Localhost resolving to IPv6 basically breaks with Docker".
Usually 127.0.0.1 is limited to the computer's internal network via a loopback network interface and `localhost` should be resolving just to that, but this RFC makes it so that no matter what `localhost` will point locally instead of somewhere else which helps people who want to bind to just the internal loopback and nothing else.
Building it into the network stack means that entire class of errors stops happening.