lib/api: Treat *.localhost as valid localhost addresses (#7412) (ref #4815)

This loosens the ‘is this localhost?’ check to include *.localhost host
names.

This allows for clearer (hence better) names to be used in browsers,
e.g. when accessing a remote syncthing instance ‘foo’ using a ssh port
forward, one can use foo.localhost to remind oneself which one is which.
💡 Without these changes, Syncthing shows a ‘Host check error’ when
pointing a browser at http://foo.localhost/, and with these changes, the
interface loads as usual.

The .localhost top level domain is a reserved top-level domain (RFC 2606):

> The ".localhost" TLD has traditionally been statically defined in
> host DNS implementations as having an A record pointing to the
> loop back IP address and is reserved for such use.  Any other use
> would conflict with widely deployed code which assumes this use.
> – https://tools.ietf.org/html/rfc2606

As Wikipedia puts it:

> This allows the use of these names for either documentation purposes
or in local testing scenarios. – https://en.wikipedia.org/wiki/.localhost

On Linux systems, systemd-resolved resolves *.localhost, on purpose:
https://www.freedesktop.org/software/systemd/man/systemd-resolved.service.html

See also #4815, #4816.
This commit is contained in:
wouter bolsterlee 2021-02-27 08:52:49 +01:00 committed by GitHub
parent 428c5c02ce
commit 25151b14e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 9 additions and 4 deletions

View File

@ -1772,8 +1772,13 @@ func addressIsLocalhost(addr string) bool {
// There was no port, so we assume the address was just a hostname
host = addr
}
switch strings.ToLower(host) {
case "localhost", "localhost.":
host = strings.ToLower(host)
switch {
case host == "localhost":
return true
case host == "localhost.":
return true
case strings.HasSuffix(host, ".localhost"):
return true
default:
ip := net.ParseIP(host)

View File

@ -995,14 +995,14 @@ func TestAddressIsLocalhost(t *testing.T) {
{"[::1]:8080", true},
{"127.0.0.1:8080", true},
{"127.23.45.56:8080", true},
{"www.localhost", true},
{"www.localhost:8080", true},
// These are all non-localhost addresses
{"example.com", false},
{"example.com:8080", false},
{"localhost.com", false},
{"localhost.com:8080", false},
{"www.localhost", false},
{"www.localhost:8080", false},
{"192.0.2.10", false},
{"192.0.2.10:8080", false},
{"0.0.0.0", false},