Why can't I ssh to a local (single-label) hostname: "ssh: connect to host myserver port 22: Invalid argument"?

When I brought a Raspberry Pi onto the network, this problem manifested itself in a new way and I was able to finally diagnose it.

The problem is related to systemd-resolved. This has been affecting other users, see for example Ask Ubuntu's nslookup finds ip, but ping doesnt or systemd-resolved does not query dns server for local domain.

I had assumed that ssh myserver would trigger a DNS lookup of myserver. However, that is not the case on my system, here is the default nsswitch.conf:

$ cat /etc/nsswitch.conf
# Name Service Switch configuration file.
# See nsswitch.conf(5) for details.
...
hosts: files mymachines myhostname resolve [!UNAVAIL=return] dns
...

The resolve component is systemd-resolved, which is a Lennart Poettering project to implement the Zeroconf protocols Multicast DNS and Link-Local Multicast Name Resolution.

The [!UNAVAIL=return] means that when systemd-resolved is available, DNS host resolution is never used. Usually this is not a problem because systemd-resolved is also able to create DNS queries. However it apparently does not do this for single-label hostnames like myserver, even when the DNS server is on my local router (192.168.1.1). This is because it is reasoned that single-label hostnames should not be exposed to the outside network, as explained by Lennart in this Github thread.

This explains the fact that host myserver produced an IPv4 address (from the router) while ssh myserver produced an IPv6 address (from Multicast DNS or LLNR, not sure which).

I was confused by this because I never learned about Multicast DNS or LLNR or IPv6. I never learned about these technologies because I thought the familiar technologies of IPv4 and DNS were sufficient for me.

Apparently systemd-resolved is necessary not just for producing Zeroconf requests, but also for replying to them. The Raspberry Pi which I brought onto my network had its systemd-resolved stopped for some reason, so although I was able to look up the hostname with host and dig, I was not able to see it via ssh or ping:

$ ping raspberrypi
ping: raspberrypi: Name or service not known
[2]$ host raspberrypi
raspberrypi has address 192.168.1.135

This led me to the first Ask Ubuntu bug report above, which led me to the solution. If I start systemd-resolved on the Pi then I am able to ping and ssh it. However, if I disable systemd-resolved locally then I am also able to ping and ssh to the Pi.

For now I have just disabled systemd-resolved on all my systems,

$ sudo systemctl stop systemd-resolved.service
$ sudo systemctl disable systemd-resolved.service

since it seems to create problems with GNU libc's nscd and since it requires me to learn about technologies like IPv6, mDNS, and LLNR, which I don't currently need - because my computers are all connected to a basic consumer router which provides familiar technologies of DNS and NAT out-of-the-box.

Thanks to those who commented on my original question, but in the end it was not necessary to "configure yourself a ULA prefix, or get global IPv6 connectivity, or both" via "a setting in your home router, if it's not a complete piece of ****" or "to yell at your ISP". I just had to disable some of Lennart's new software to take myself away from the bleeding edge. The Github thread has some discussion about whether the software is actually behaving correctly, but I find myself in the same position as many other users: after spending hours of time figuring out that systemd-resolved is the culprit, I'd rather not spend more hours trying to understand how to fix it, when disabling is so easy.