通过 SSH 使用仅适用于池名称的主机证书连接到池成员

通过 SSH 使用仅适用于池名称的主机证书连接到池成员

我正在为主机池使用 OpenSSH 证书。也就是说,在 中~/.ssh/known_hosts有一个如下所示的条目:

@cert-authority service.redacted.com ssh-rsa ...

...并且service.redacted.com是一个循环 DNS 条目,其中涉及的每个系统都有一个主机证书(参见HostCertificate中的条目man sshd_config),该证书被签名为对 有效service.redacted.com

当想要从池中连接到随机选择的系统时,这可以完美地工作 - 但是如果有人想要从池中连接到单个特定的系统,并使用给定的证书颁发机构验证其主机密钥是否合法,该怎么办?


我尝试过的一件事是:

service_name=service.redacted.com
specific_host=1.2.3.4
ssh -v -oHostKeyAlias="$service_name" "$specific_host"

...结果如下:

debug1: Host 'service.redacted.com' is known and matches the RSA-CERT host certificate
Certificate invalid: name is not a listed principal
The authenticity of host 'service.redacted.com (1.2.3.4)' can't be established.

service.redacted.com相当肯定证书中列出的主体;1.2.3.4不是。

答案1

从当前上游 OpenSSH-portable master 开始 (https://github.com/openssh/openssh-portable/commits/773dda25e828c4c9a52f7bdce6e1e5924157beab), 这不可能。

相关逻辑在于check_host_key() 函数,它只调用check_host_cert()一次——最初传入的主机名ssh_login()仅通过将所有字符标准化为小写进行修改。传递的相同主机名resolve_host()以获取addrinfo *用于实际连接的结构;resolve_host()尊重一些选项(选择要使用的地址系列),但不提供覆盖机制。


也就是说,所需的更改很短(目前已提交给上游邮件列表并等待审核):

From 367fd8323d864daaf486047850f93c2167c66f37 Mon Sep 17 00:00:00 2001
From: Charles Duffy <[email protected]>
Date: Tue, 17 Feb 2015 09:49:32 -0600
Subject: [PATCH] Allow HostKeyAlias to match a host certificate principal if
 HostName does not

---
 sshconnect.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sshconnect.c b/sshconnect.c
index df921be..666c3ff 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -902,7 +902,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
                debug("Found %s in %s:%lu", want_cert ? "CA key" : "key",
                    host_found->file, host_found->line);
                if (want_cert && !check_host_cert(hostname, host_key))
-                       goto fail;
+                       if (options.host_key_alias == NULL || !check_host_cert(options.host_key_alias, host_key))
+                               goto fail;
                if (options.check_host_ip && ip_status == HOST_NEW) {
                        if (readonly || want_cert)
                                logit("%s host key for IP address "
--
2.0.0

相关内容