![允许普通用户使用他们无法读取的私钥进行 SSH](https://linux22.com/image/72245/%E5%85%81%E8%AE%B8%E6%99%AE%E9%80%9A%E7%94%A8%E6%88%B7%E4%BD%BF%E7%94%A8%E4%BB%96%E4%BB%AC%E6%97%A0%E6%B3%95%E8%AF%BB%E5%8F%96%E7%9A%84%E7%A7%81%E9%92%A5%E8%BF%9B%E8%A1%8C%20SSH.png)
假设我有一组机器(此处称为客户机器),只允许一小部分人(称为支持人员)通过 SSH 访问,每台机器仅使用一个帐户(支持访问帐户)。
支持人员只能使用密钥登录客户的机器。此外,支持人员可以发展,因此离开支持人员的人不允许登录任何客户计算机。因此,禁止工作人员读取用于登录客户机器的私钥。另外,禁止修改authorized_keys
客户机器上的文件。
为了实现该配置,我想到使用支持人员将登录的 SSH 代理(使用 LDAP 身份验证,但这是另一个问题)并且包含私钥。
问题是:如何允许支持人员在无法读取的情况下使用 SSH 私钥?
我相信我必须在代理计算机上创建一个以 root 身份运行的守护进程,它将接受用户的请求并为他们打开 SSH 会话,但我不知道该怎么做。有任何想法吗?
答案1
您真正想做的是使用 SSH CA 并签署每个支持人员使用的密钥(他们应该有自己的 ssh 密钥,如护照),并配置您的客户端服务器以使用TrustedUserCAKeys /etc/ssh/users_ca.pub
/etc/ssh/sshd_config.conf 中的 SSH CA 和签名密钥。这样,服务器将接受由 CA 密钥(您有权访问)签名的任何密钥,并且您将能够撤销不再支持的人员的密钥,甚至无需触及授权密钥。
快速搜索“ssh ca”即可找到本教程:https://www.digitalocean.com/community/tutorials/how-to-create-an-ssh-ca-to-validate-hosts-and-clients-with-ubuntu(向下滚动到“如何配置用户密钥”)-虽然教程提到 Ubuntu 它是独立于发行版的,但您需要支持 SSH CA 的新版本 OpenSSH
关于该主题的另一个很好的博客文章是https://ef.gy/hardening-ssh(向下滚动到“SSH 证书”)。
请特别注意,您可以将密钥签名为在有限时间内有效,因此它们将自动过期!
答案2
我会建议几个选择。
sudo
保护 ssh 密钥并要求您的支持团队使用。您可以使用包装器透明地完成此操作。比如说,调用包装器,/usr/local/bin/ssh-support
并让它包含类似这样的内容(未经测试):#!/bin/bash export PATH=/usr/local/bin:/usr/bin:/bin export IFS=$' \t\n' export SUSER=ssupport # Restart if not running under sudo test "X$1" != 'X-S' && exec sudo -u "$SUSER" /usr/local/bin/ssh-support -S "$@" shift export SHOME="$(getent passwd "$SUSER" | cut -d: -f6)" # Extract single argument as hostname LABEL and validate that we have # an RSA private key for it. The target username, real hostname, port, # etc. can be defined in ~/.ssh/config for the user $SUSER (ssupport) label="$1" idfile="$SUSER/.ssh/id_rsa_for_$label" cgfile="$SUSER/.ssh/config" ok=true [[ "$label" =~ '/' ]] && { echo "Invalid label: $label" >&2; ok=; } [[ ! -s "$idfile" ]] && { echo "Missing identity file: $idfile" >&2; ok=; } [[ ! -s "$cgfile" ]] && { echo "Missing configuration file: $cgfile" >&2; ok=; } if test -n "$ok" then logger -t ssh-support "$SUDO_USER requested ssh to $label" exec ssh -i "$idfile" -F "$cgfile" "$label" fi exit 1
这将需要
sudoers
文件中的一个条目允许support
组中的用户使用该工具。此命令允许他们以用户身份运行该ssh-support
工具ssupport
- 您必须创建该用户。它才不是授予任何 root 权限。%support ALL = (ssupport) /usr/local/bin/ssh-support
如果您很高兴支持用户不需要提供自己的密码来运行该工具(根据
sudo
脚本本身内的调用的要求),您可以sudoers
这样修改定义:%support ALL = (ssupport) NOPASSWD: /usr/local/bin/ssh-support
假设
PATH
包含,/usr/local/bin/
那么您将使用 来调用它ssh-support clientname
。还假设您已经像创建证书对一样创建了用户,并且有一个主机条目为ssupport
目标计算机定义了用户、主机、端口等。您可能会明确禁用 X11 转发、端口转发等。像往常一样,该目录需要使用权限进行保护。/home/ssupport
/home/ssupport/.ssh/id_rsa_clientname
/home/ssupport/.ssh/id_rsa_clientname.pub
/home/ssupport/.ssh/config
clientname
/home/ssupport/.ssh
0700
为每个支持成员提供自己的本地用户帐户,并让每个人使用自己的私有 ssh 密钥来访问客户端的服务器。当某人离开支持小组时,您将从客户端服务器中删除他们的 ssh 密钥。这意味着您不再需要担心阻止您的员工知道 ssh 私钥。
答案3
有几个不同的答案,涉及通过 sudo 或 setuid 可执行文件调用的 ssh 包装脚本(对于某些特殊用途非根帐户)。作为nkms 说,将所有参数传递给 ssh 可以让用户使用我们要保护的 ssh 密钥执行任意操作。有些人提出的另一个极端是只允许主机名。
OP 说管理员需要能够上传东西。
您可以有两个不同的固定参数到 ssh 包装器。一个用于登录 shell,另一个用于 scp。除了主机名(和要上传的文件名)之外,没有用户提供的参数。
或者一个包装器脚本,它使用getopt
自身来解析非常有限的选项,并将内容插入到大部分固定的 ssh 命令中。忽略(或错误)无法识别的选项将是正确的方法。
不要尝试过滤掉“危险”的 ssh 选项,只需编写一个可以执行两件事的包装器:交互式登录或上传文件(本地和远程文件名)。我想你仍然需要在那里进行一些消毒。
其实这还是很容易出错的。您必须找到一种方法来阻止用户将保存 ssh 密钥的文件作为本地文件提供。所以你仍然试图考虑所有需要禁止的事情,而不是从不允许任何事情开始。首先要确保文件名不包含任何@
或:
.
答案4
您的支持人员始终通过该代理计算机进行连接,并且只能通过它进行连接,因此客户可以简单地使用 HostbasedAuthentication 对代理计算机进行身份验证。
假设代理机器是supporters.pc
并且您提供支持customer.pc
客户.pc将会有基于主机的身份验证 是在/etc/ssh/ssd_config
,支持者.pc中列出/etc/ssh/shosts.equiv
,其公钥在 中/etc/ssh/ssh_known_hosts
。
当您的支持人员登录时[电子邮件受保护],并执行ssh customer.pc
,它将产生ssh-keysign(8)(需要设置uid),它将使用您无法读取的文件处理密钥签名,并向supporters.pc提供连接确实来自的证明支持者.pc。作为客户.pc信托支持者.pc,您的员工登录为支持。