SSHFP 不工作

fze*_*arg 10 ssh dnssec

我有两台运行 OpenBSD v6.9 的机器。让我们原创一下,将它们称为客户端和服务器。

我使用以下命令在服务器上生成了 SSHFP 记录:

ssh-keygen -r host.domain.tld
Run Code Online (Sandbox Code Playgroud)

在 DNS 区域中,我使用以下行添加了 SSHFP 记录:

host      IN      SSHFP 1 2   02323a6fb8a12eba9288930ce2513fc94970e5575996ebede1ee352bd039c531
host      IN      SSHFP 4 2   3eef5929fe85038b2e2a7de70897175e7b0d68328b41ef6466a2fa06f9a8bb49
Run Code Online (Sandbox Code Playgroud)

sshd 配置为仅使用 Ed25519 主机密钥,但我也保留 RSA 主机密钥以备将来需要。

DNS 区域使用 DNSSEC 进行签名,所有内容均通过“https://dnsviz.net/”和“https://dnssec-debugger.verisignlabs.com/”进行验证。

在客户端,有一个带有 DNSSEC 验证器的 Unbound 解析器:

dig host.domain.tld -t SSHFP

; <<>> dig 9.10.8-P1 <<>> host.domain.tld -t SSHFP
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9525
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;host.domain.tld.              IN      SSHFP

;; ANSWER SECTION:
host.domain.tld.       3600    IN      SSHFP   4 2 3eef5929fe85038b2e2a7de70897175e7b0d68328b41ef6466a2fa06 f9a8bb49
host.domain.tld.       3600    IN      SSHFP   1 2 02323a6fb8a12eba9288930ce2513fc94970e5575996ebede1ee352b d039c531

;; Query time: 182 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon May 17 17:15:46 CEST 2021
;; MSG SIZE  rcvd: 137
Run Code Online (Sandbox Code Playgroud)

上面没有提到,但如果我在查询中添加 +dnssec,则会显示 RRSIG SSHFP。

以及 SSH 客户端配置文件:

Host host.domain.tld
    AddressFamily inet
    HostName host.domain.tld
    Port 22
    Protocol 2
    User username
    CheckHostIP yes
    PasswordAuthentication no
    ChallengeResponseAuthentication no
    PubkeyAuthentication yes
    VerifyHostKeyDNS yes
    IdentityFile ~/.ssh/id_ed25519_host.domain.tld
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试从客户端连接到服务器时,SSHFP 似乎不起作用:

ssh host.domain.tld
The authenticity of host 'host.domain.tld (server_ip_address)' can't be established.
ED25519 key fingerprint is SHA256:Pu9ZKf6FA4suKn3nCJcXXnsNaDKLQe9kZqL6Bvmou0k.
Matching host key fingerprint found in DNS.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Run Code Online (Sandbox Code Playgroud)

根据互联网指南,我不应该被要求接受密钥。

所以,总结一下:

  • 服务器上生成的SSHFP记录,
  • 添加到 DNS 区域的 SSHFP 记录,
  • 使用 DNSSEC 签名的 DNS 区域,
  • 客户端能够查询 SSHFP 记录并验证 DNSSEC,
  • 带有选项“VerifyHostKeyDNS”的 SSH 配置文件,
  • 它不起作用。

这是连接的详细信息:

ssh -v host.domain.tld
OpenSSH_8.6, LibreSSL 3.3.2
debug1: Reading configuration data /home/username/.ssh/config
debug1: /home/username/.ssh/config line 2: Applying options for host.domain.tld
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Connecting to host.domain.tld [server_ip_address] port 22.
debug1: Connection established.
debug1: identity file /home/username/.ssh/id_ed25519_host.domain.tld type 3
debug1: identity file /home/username/.ssh/id_ed25519_host.domain.tld-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_8.6
debug1: Remote protocol version 2.0, remote software version OpenSSH_8.6
debug1: compat_banner: match: OpenSSH_8.6 pat OpenSSH* compat 0x04000000
debug1: Authenticating to host.domain.tld:22 as 'username'
debug1: load_hostkeys: fopen /home/username/.ssh/known_hosts2: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256@libssh.org
debug1: kex: host key algorithm: ssh-ed25519
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: SSH2_MSG_KEX_ECDH_REPLY received
debug1: Server host key: ssh-ed25519 SHA256:Pu9ZKf6FA4suKn3nCJcXXnsNaDKLQe9kZqL6Bvmou0k
debug1: found 2 insecure fingerprints in DNS
debug1: matching host key fingerprint found in DNS
debug1: load_hostkeys: fopen /home/username/.ssh/known_hosts2: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory
debug1: load_hostkeys: fopen /home/username/.ssh/known_hosts2: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory
debug1: hostkeys_find_by_key_hostfile: hostkeys file /home/username/.ssh/known_hosts2 does not exist
debug1: hostkeys_find_by_key_hostfile: hostkeys file /etc/ssh/ssh_known_hosts does not exist
debug1: hostkeys_find_by_key_hostfile: hostkeys file /etc/ssh/ssh_known_hosts2 does not exist
The authenticity of host 'host.domain.tld (server_ip_address)' can't be established.
ED25519 key fingerprint is SHA256:Pu9ZKf6FA4suKn3nCJcXXnsNaDKLQe9kZqL6Bvmou0k.
Matching host key fingerprint found in DNS.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Run Code Online (Sandbox Code Playgroud)

你知道这个问题吗?

提前致谢。

Joh*_*ene 6

OpenSSH v6.9 非常非常非常老了。最新的是 OpenSSH v9.0。我查看了dns.cOpenSSH 存储库的 V_6_9 分支。调试输出中要注意的关键是:

\n
found 2 insecure fingerprints in DNS\n
Run Code Online (Sandbox Code Playgroud)\n

意味着 DNSSEC 查找host.domain.tld不是有效的 DNS 记录(完全不安全),尽管通常已找到两 (2) 个不同的SSHFP资源记录(安全或不安全)。

\n

这也意味着delv host.domain.tld.不会在第一行中输出预期的消息:

\n
$ delv host.domain.tld.\n; fully validated\n...\n
Run Code Online (Sandbox Code Playgroud)\n

虽然 DNSSEC 故障排除的范围非常广泛,但在本文中并不容易找到解决方案。

\n

我建议您将其插入domain.tld两个出色的在线 DNSSEC 疑难解答程序之一,然后从那里开始:

\n\n

当然,作为最后的手段,[dnssec]ServerFault(另一个 StackExchange 组)和您最喜欢的标签上有标签。搜索引擎,但聘请内部 DNSSEC 专家来满足您的需求会更快。

\n

安全考虑

\n

当然,您确实已启动并运行 DNSSEC 吗?

\n

SSHFP 的保护只能通过 DNSSEC 正确签名的资源记录来保证,但是……但是大多数人(以及许多 ISP)不会指示他们的 DNS 解析器仅返回由 DNSSEC 确定的有效 DNS 记录;话虽如此,SSHFP 被劫持的可能性仍然存在。

\n

这里的问题不是公钥的机密性(它不是\xe2\x80\x99t机密)。

\n

我们遇到的问题是保存该公钥的 DNS 记录的完整性。虽然您的问题陈述中的 SSHFP 密钥数据是正确的,但该错误更多的是 \xe2\x80\x9clack of clarity\xe2\x80\x9d 但逻辑在防御上仍然正确。

\n

这就是这个原始问题帖子的结束。但我将概述一些更多的安全警告。

\n

更多注意事项

\n

如果不安全地分发(通过 DNSSEC),此类 SSHFP DNS 记录很容易被篡改或替换为其他密钥。因此,在信任和使用SSHFP.

\n

如果伪造的 SSH CA 服务器配置了错误的公钥(其私钥在其他人手中),则客户端最终会信任其他人。

\n

注意:SSHFP 记录使用不当可能会造成严重的安全后果;请遵循以下规则以避免造成安全漏洞:

\n
    \n
  • 不要在不受 DNSSEC 保护的区域中创建 SSHFP 记录。
  • \n
  • 切勿将 SSH 客户端配置为对不受 DNSSEC 保护的域使用 SSHFP。
  • \n
  • VerifyHostKeysDNS yes除非当前解析器正确验证 DNSSEC 批准的查询或使用我使用简单命令创建的有效的支持 DNSSEC 的解析器delv domain.tld.列表作为其 DNSSEC 功能的测试,否则切勿配置要使用的 SSH 客户端。
  • \n
  • 请确保 SSH 客户端直接使用的所有 DNS 解析器都具有“可访问的 DNSSEC”;这意味着在每个 ISP 处测试您的流动笔记本电脑以获得该; fully validated检查。
  • \n
  • 最重要的是,始终、始终执行delv ssh.domain.tld.并检查第一行的; fully validated输出或通过强制执行 DNSSEC /etc/resolv.conf(稍后会详细介绍)。
  • \n
\n

如果不遵守这些规则,攻击者可能会为其 SSH 服务器创建欺骗性 SSHFP 记录来冒充您的服务器,从而使与服务器的 SSH 连接不安全且容易受到攻击。

\n

您可以通过让主机的库在解析时执行此操作(通过解析器(3)而不是 gethostbyname(3) 函数调用)来避免“始终执行delv ssh.domain.tldfor )。如果您必须要求绝对 DNSSEC 验证的 DNS 查询您的所有 DNS 需求,您可以将以下内容插入到您的文件中(仅当您有 glibc v2.38 或更高版本时):; fully validatedglibc/etc/resolv.conf

\n

文件:/etc/resolv.conf

\n
.\n.\n.\noptions edns0\noptions trust-ad\noptions ndots:2\n.\n.\n.\nsearch domain.tld\nnameserver 192.168.1.1\n
Run Code Online (Sandbox Code Playgroud)\n

一旦获得 DNSSEC 保护,就需要执行几个步骤来排除SSHFPDNS 记录和 SSH 客户端机制的故障。

\n

验证 SSHFP 设置

\n

列出七 (7) 个步骤是为了尝试(在前面的步骤通过之前不要执行下一步)。

\n
    \n
  1. Ping host.domain.tld,获得 ICMP 响应。

    \n
  2. \n
  3. 执行delv host.domain.tld.并确保第一行输出显示; fully validated.请注意主机名末尾添加的句点 ( )。

    \n
  4. \n
  5. EDNS(0)使用此EDNS(0) 在线测试仪针对您的相关服务器进行正确的练习。

    \n
  6. \n
  7. 从有问题的 SSH 服务器获取 SSH 指纹以开始比较;执行ssh-keyscan -D host.domain.tld. (注意-D选项)。

    \n
  8. \n
\n
found 2 insecure fingerprints in DNS\n
Run Code Online (Sandbox Code Playgroud)\n

其输出:

\n
host.domain.tld IN SSHFP 4 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nhost.domain.tld IN SSHFP 4 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 从在其区域数据库文件中保存 SSHFP 的权威名称服务器的 DNS 查询中,使用 获取SSHFP记录delv host.domain.tld. SSHFP
  2. \n
\n
$ delv host.domain.tld.\n; fully validated\n...\n
Run Code Online (Sandbox Code Playgroud)\n

生成以下输出:

\n
; fully validated\nhost.domain.tld.        86400   IN  SSHFP   1 1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\nhost.domain.tld.        86400   IN  SSHFP   1 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXX\nhost.domain.tld.        86400   IN  SSHFP   3 1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\nhost.domain.tld.        86400   IN  SSHFP   3 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXX\nhost.domain.tld.        86400   IN  SSHFP   4 1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\nhost.domain.tld.        86400   IN  SSHFP   4 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXX\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. SSHFP将实际 SSH 指纹与DNS 记录的内容进行比较。算法 (1-6) 和哈希 ID(1 或 2)也必须匹配。
  2. \n
\n

必须匹配的命名算法 ID 为:1=RSA、2=DSA、3=ECDSA、4=Ed25519、6=Ed448。

\n

必须匹配的名称的哈希 ID 为:1=SHA1、2=SHA256。

\n
    \n
  1. 尝试ssh -oVerifyHostKeyDNS=yes -oStrictHostKeyChecking=yes host.domain.tld. 如果此步骤有效,请将这两个选项集成到您的 SSH 客户端配置文件中。
  2. \n
\n

如果指纹不匹配,则始终是需要更新的 DNS 记录。

\n

出现警告

\n

使用较新的 OpenSSH,您甚至可能在初始 SSH 登录期间收到以下讨厌的提示:

\n
ssh host.domain.tld\n
Run Code Online (Sandbox Code Playgroud)\n

可能会输出以下内容:

\n
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\nIT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\nSomeone could be eavesdropping on you right now (man-in-the-middle attack)!\nIt is also possible that a host key has just been changed.\nThe fingerprint for the ED25519 key sent by the remote host is\nSHA256:XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx.\nPlease contact your system administrator.\nUpdate the SSHFP RR in DNS with the new host key to get rid of this message.\nWarning: Permanently added \'[host.domain.tld.]:22,[999.999.999.999]:22\' (ED25519) to the list of known hosts.\n</etc/motd content goes here>\nuser@host.domain.tld.\'s password: \n
Run Code Online (Sandbox Code Playgroud)\n

上面的输出中需要注意的关键是以下行:

\n
Update the SSHFP RR in DNS with the new host key to get rid of this message.\n
Run Code Online (Sandbox Code Playgroud)\n

这正是它的意思。

\n

本地 SSH 客户端配置VerifyHostKeyDNS yes中的\n控制该输出;配置位于$USER/.ssh/config或 中/etc/ssh/ssh_config

\n

上述决定基于以下之间的简单比较:

\n
    \n
  • 持有SSHFP该区域数据的权威名称服务器host.domain.tld
  • \n
  • host.domain.tld提供公钥的SSH服务器
  • \n
\n

此消息涵盖了以下 99.999% 的潜在场景。

\n
    \n
  • sshd没有使用相同的公钥,可能是由于:\n
      \n
    • ssh-keygen通过(最常见)生成了不同的公钥
    • \n
    • 一组不同的配置文件(通过sshd -c <config_file>
    • \n
    • AuthorizedKeyFile已经改变
    • \n
    • 指纹哈希 ( FingerprintHash) 设置已更改
    • \n
    • PubkeyAcceptedKeyTypes已被改变
    • \n
    • CASignatureAlgorithms已被改变
    • \n
    • TrustedCAUserKeys已被改变
    • \n
    \n
  • \n
\n

另外 0.001% 的时间在许多不太常见的场景之一中发生故障:

\n
    \n
  • 指向不同的 SSH 服务器\n
      \n
    • 新的端口号已打开(合法或非法)。如果您的ssh_config/$HOME/.ssh/config使用了不同的端口号,则可能会发生这种情况(罕见但有人恶意发生)
    • \n
    • 一个(不同的?)Dockerized 容器重用相同的 IP 地址
    • \n
    • MAC 地址已更改为指向克隆服务器
    • \n
    • IP 过滤器(或 nftables)重新路由您常用的 SSH 端口
    • \n
    • IP 路由已更改(通过路由表或各种 IP 路由协议,如 BGP、OSPF、RIP)
    • \n
    • 出现了一个幽灵守护进程,使得您的服务器的 rougesshd守护进程通过 SysV init 启动(service XXXX startsystemd start XXXX.servicesystem start XXXX.timer或通过 crond/atd 作业甚至偷偷地启动rc.local),并使用自己的 SSH 服务器公钥。
    • \n
    \n
  • \n
  • 指向不同的sshd可执行文件。这需要通过包工具(您的发行版的包工具)进行文件验证,以确定它\xe2\x80\x99s 的校验和值、修改时间、文件路径、安全上下文以及sshd可执行文件及其引用库的属性(请参阅 参考资料ldd/usr/sbin/sshd)都是计算并正确设置。
  • \n
\n

无论如何,一旦你消除了剩下的 0.001%,事情就很简单了:

\n
    \n
  • 生成新的SSHFPDNS 记录 ( ssh-keyscan -r host.domain.tld); 将输出保存到编辑器缓冲区
  • \n
  • 识别权威名称服务器domain.tlddig domain.tld. soa并记下MNAMESOA 记录数据的部分)。
  • \n
  • 以 root 身份登录该MNAME权威名称服务器host.domain.tld
  • \n
  • 转到名称服务器的正确配置文件(ISC Bind9 是/etc/named.conf;较新的 Bind v9.11+ 通过显示默认配置named -V
  • \n
  • 记下该区域的数据库文件名domain.tld。(ISC Bind9 是file /var/lib/bind/db.domain.tld
  • \n
  • 将目录更改为该区域数据库文件所在的位置
  • \n
  • 编辑db.domain.tld文件。
  • \n
  • SSHFP粘贴您在第一步中保存的编辑器缓冲区中的新DNS 记录。
  • \n
\n

可能希望将该句点 ( .) 符号直接放在每个数据记录的主机名末尾SSHFP(该数据记录是在关闭该区域数据库文件之前生成的ssh-keyscan;这样:

\n
; note the extra ending period \'.\' after hostnames\nhost.domain.tld. IN SSHFP 4 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nhost.domain.tld. IN SSHFP 4 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n
Run Code Online (Sandbox Code Playgroud)\n

享受!

\n

来源:

\n\n