为什么我无法 ssh 到本地(单标签)主机名:“ssh:连接到主机 myserver 端口 22:无效参数”?

为什么我无法 ssh 到本地(单标签)主机名:“ssh:连接到主机 myserver 端口 22:无效参数”?

(我发现这与有关nscd;请参阅问题的底部)

我正在尝试通过笔记本电脑连接到无头服务器;它们通过 Linksys 无线路由器和 TP-Link 以太网交换机共享有线链路。我在两台机器上运行 Arch Linux,使用非常默认的 Systemd 设置和 dhcpcd 进行网络配置。

最近在笔记本电脑上进行系统升级后,当我尝试 ssh 到服务器(我们称之为“myserver”)时出现以下错误:

$ ssh -v -v -F /dev/null myserver
OpenSSH_7.7p1, OpenSSL 1.1.0h  27 Mar 2018
debug1: Reading configuration data /dev/null
debug2: resolving "myserver" port 22
debug2: ssh_connect_direct: needpriv 0
debug1: Connecting to myserver [fe80::9cd8:b045:5974:c5cf] port 22.
debug1: connect to address fe80::9cd8:b045:5974:c5cf port 22: Invalid argument
ssh: connect to host myserver port 22: Invalid argument

运行相同的命令strace显示错误来自connect

connect(3, {sa_family=AF_INET6, sin6_port=htons(22), inet_pton(AF_INET6, "fe80::9cd8:b045:5974:c5cf", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)

但是,ping myserver效果很好:

$ ping myserver    
PING myserver(myserver (fe80::9cd8:b045:5974:c5cf)) 56 data bytes
64 bytes from myserver (fe80::9cd8:b045:5974:c5cf%en0): icmp_seq=1 ttl=64 time=0.533 ms
64 bytes from myserver (fe80::9cd8:b045:5974:c5cf%en0): icmp_seq=2 ttl=64 time=0.549 ms

通常我有一个本地named转发 DNS 查询,但是当我返回直接使用路由器的 DNS 服务器时,错误仍然存​​在:

$ sudo cat /etc/resolv.conf
# Generated by resolvconf
nameserver 192.168.1.1

错误是间歇性的:每隔几分钟我就能成功连接。当我能够成功连接时,我看到它connect正在使用 IPv4 地址:

connect(3, {sa_family=AF_INET, sin_port=htons(22), sin_addr=inet_addr("192.168.1.149")}, 16) = 0

但是,host无论连接正常还是中断,该命令都会显示相同的 IPv4 地址:

$ host myserver                   
myserver has address 192.168.1.149

看完之后问题 我想到手动指定接口(ssh -v -v -F /dev/null -B en0 myserver)。这可以在错误发生时消除错误,但对我来说这不是永久的解决方案,也不能解释为什么错误突然出现。

while在我的 shell 中使用了一个循环来确定从工作到不工作以及反之亦然的最接近秒数的时间ssh,并且我无法将这些事件与输出中的任何内容(journalctl包括dhcpcd消息)关联起来。

我最初在 Network Engineering 上发布了这篇文章,但那里的主机配置与主题无关。在该网站上,用户瑞奇·比姆发布了部分答案:

无论执行主机名解析的是什么,返回的都是对所选接口(即“任何”)无效的本地链路 IPv6 地址。本地链路地址必须指定接口 - 例如 fe80:...:1%eth0

不知道您为什么会得到链接本地地址。也许熟悉 Arch Linux 的人可以提供进一步的帮助。


更新:这似乎是nscd“名称服务缓存守护程序”的问题,这解释了我遇到的间歇性问题(可能与缓存过期有关)。已修复:

sudo systemctl stop nscd.service

当我停止 ncsd 时,ssh就可以使用链路本地地址进行连接,但这次调用connect还指定了我的主接口“en0”,并且成功了:

connect(3, {sa_family=AF_INET6, sin6_port=htons(22), inet_pton(AF_INET6, "fe80::9cd8:b045:5974:c5cf", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=if_nametoindex("en0")}, 28) = 0
write(2, "debug1: Connection established.\r"..., 33) = 33

我想剩下的问题(我可以单独问)是,这是 nscd 中的一个错误吗?我应该使用 nscd 吗?

答案1

当我将 Raspberry Pi 接入网络时,这个问题以一种新的方式表现出来,我最终能够对其进行诊断。

该问题与有关systemd-resolved。这已经影响到其他用户,例如请参阅 Ask Ubuntu 的nslookup 找到 ip,但 ping 不通 或者systemd-resolved 不会查询 DNS 服务器以获取本地域

我曾假设这ssh myserver会触发 DNS 查找 myserver。但是,在我的系统上并非如此,以下是默认的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
...

resolve组件是systemd-resolvedLennart Poettering 项目,旨在实现 零配置 协议多播 DNS链路本地多播名称解析

[!UNAVAIL=return]意味着当systemd-resolved可用时,永远不会使用 DNS 主机解析。通常这不是问题,因为systemd-resolved也可以创建 DNS 查询。但是,它显然不会对单标签主机名(如)执行此操作 myserver,即使 DNS 服务器位于我的本地路由器 (192.168.1.1) 上也是如此。这是因为单标签主机名不应该暴露给外部网络,正如 Lennart 在这个 Github 线程

host myserver这解释了产生 IPv4 地址(来自路由器)同时ssh myserver产生 IPv6 地址(来自多播 DNS 或 LLNR,不确定是哪一个)的事实。

我对此感到困惑,因为我从未了解过多播 DNS 或 LLNR 或 IPv6。我从未了解过这些技术,因为我认为熟悉的 IPv4 和 DNS 技术对我来说已经足够了。

显然,systemd-resolved不仅对于生成 Zeroconf 请求是必要的,对于回复这些请求也是必要的。我接入网络的 Raspberry Pisystemd-resolved由于某种原因停止了运行,因此尽管我能够使用 和 查找主机名 ,hostdig我无法通过ssh或看到它ping

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

这让我找到了上面的第一个 Ask Ubuntu 错误报告,并找到了解决方案。如果我systemd-resolved在 Pi 上启动,那么我就可以pingssh它连接。但是,如果我systemd-resolved 在本地禁用,那么我也能够和Pi 连接pingssh

现在我已经systemd-resolved在所有系统上禁用了,

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

因为它似乎会给 GNU libc 带来问题nscd,而且它要求我学习 IPv6、mDNS 和 LLNR 等技术,而这些技术我目前不需要——因为我的计算机都连接到一个基本的消费者路由器,它提供了开箱即用的熟悉的 DNS 和 NAT 技术。

感谢那些对我的原始问题发表评论的人,但最终没有必要通过“在您的家用路由器中进行设置(如果它不是一团糟)”或“对您的 ISP 大喊大叫”来“为自己配置一个 ULA 前缀,或获得全球 IPv6 连接,或两者兼而有之”。我只需要禁用 Lennart 的一些新软件,就可以远离前沿技术。Github 线程对软件是否真正正常运行进行了一些讨论,但我发现自己与许多其他用户处于相同的位置:在花了几个小时的时间找出罪魁祸首之后systemd-resolved,我宁愿不花更多的时间来了解如何修复它,因为禁用它是如此容易。

相关内容