ssh-agent 转发和 sudo 到另一个用户

177 ssh sudo agent forwarding ssh-agent

如果我有一个服务器 A,我可以使用我的 ssh 密钥登录,并且我有能力“sudo su - otheruser”,我会丢失密钥转发,因为 env 变量被删除并且套接字只能由我的原始用户读取。有没有一种方法可以通过“sudo su - otheruser”桥接密钥转发,这样我就可以使用转发的密钥(在我的情况下为 git clone 和 rsync )在服务器 B 上做一些事情?

我能想到的唯一方法是将我的密钥添加到其他用户的授权密钥和“ssh otheruser@localhost”,但对于我可能拥有的每个用户和服务器组合来说,这很麻烦。

简而言之:

$ sudo -HE ssh user@host
(success)
$ sudo -HE -u otheruser ssh user@host
Permission denied (publickey). 
Run Code Online (Sandbox Code Playgroud)

Min*_*ark 203

正如您所提到的sudo,出于安全原因,环境变量由 删除。

但幸运的sudo是相当配置:您可以准确地告诉它你想保留多亏了哪些环境变量env_keep在配置选项/etc/sudoers

对于代理转发,您需要保留SSH_AUTH_SOCK环境变量。为此,只需编辑您的/etc/sudoers配置文件(始终使用visudo)并将env_keep选项设置为适当的用户。如果要为所有用户设置此选项,请使用如下Defaults行:

Defaults    env_keep+=SSH_AUTH_SOCK
Run Code Online (Sandbox Code Playgroud)

man sudoers 更多细节。

您现在应该可以做这样的事情(提供user1的公钥是存在于~/.ssh/authorized_keysuser1@serverAuser2@serverB,和serverA/etc/sudoers文件是上面所示的设置):

user1@mymachine> eval `ssh-agent`  # starts ssh-agent
user1@mymachine> ssh-add           # add user1's key to agent (requires pwd)
user1@mymachine> ssh -A serverA    # no pwd required + agent forwarding activated
user1@serverA> sudo su - user2     # sudo keeps agent forwarding active :-)
user2@serverA> ssh serverB         # goto user2@serverB w/o typing pwd again...
user2@serverB>                     # ...because forwarding still works
Run Code Online (Sandbox Code Playgroud)

  • 这*仅*有效,如果上面的`user2`是`root`!否则,`user2` 将正确设置SSH_AUTH_SOCK,但`user2` 将无法访问例如/tmp/ssh-GjglIJ9337/。`root` 确实具有该访问权限。所以这可能会解决部分问题,但不能解决 OP:“*和* 套接字只能由我的原始用户读取” (53认同)
  • `Defaults>root env_keep+=SSH_AUTH_SOCK` 应该确保它只在 sudoing *to* root 时转发。出于安全原因,您不想对其他用户这样做。最好为 otherother 运行一个单独的 ssh-agent,并添加适当的密钥。 (6认同)
  • 我一直不明白人们为什么要使用 `sudo su`。如果你需要一个 root shell,这就是 `sudo -s` 或 `sudo -i` 的用途。 (5认同)
  • 无需配置整个 `sudo`。只需将其作为 `sudo --preserve-env=SSH_AUTH_SOCK` 运行。 (3认同)
  • @eaj 历史原因。`sudo -i` 最初不存在,后来添加了。所以很多人养成了`sudo su`的习惯,很多文档都是用旧的方式写的。虽然它已经可用了大约 15 年。 (2认同)

Joa*_*sta 87

sudo -E -s
Run Code Online (Sandbox Code Playgroud)
  • -E 将保护环境
  • -s 运行命令,默认为 shell

这将为您提供一个仍然加载原始密钥的 root shell。

  • 您还可以使用 `sudo --preserve-env=SSH_AUTH_SOCK` 指定只保留 `SSH_AUTH_SOCK` 环境变量而不是保留所有环境变量 (9认同)
  • 与上面的评论一样,这仅解决了您成为 root 时的问题,因为在这种情况下,root 能够绕过 $SSH_AUTH_SOCK 的通常访问权限。 (3认同)

小智 40

在切换到其他用户之前,允许其他用户访问$SSH_AUTH_SOCK文件及其目录,例如通过正确的 ACL。

该示例假设Defaults:user env_keep += SSH_AUTH_SOCK/etc/sudoers“主机”机器上:

$ ssh -A user@host
user@host$ setfacl -m otheruser:x   $(dirname "$SSH_AUTH_SOCK")
user@host$ setfacl -m otheruser:rwx "$SSH_AUTH_SOCK"
user@host$ sudo su - otheruser
otheruser@host$ ssh server
otheruser@server$
Run Code Online (Sandbox Code Playgroud)

更安全,也适用于非 root 用户

  • 请记住,使用此方法时,以 `otheruser` 身份登录的其他人也可以使用您的 ssh 身份验证。 (7认同)
  • @anatolytechtonik 来自`man 7 unix` - 在 Linux 上连接到套接字需要对该套接字的读写权限。您还需要对创建套接字的目录进行搜索(执行)和写入权限,或者在连接到此套接字时仅需要搜索(执行)权限。所以在上面的答案中,对套接字的执行权限是多余的。 (3认同)

phy*_*lae 14

我发现这也有效。

sudo su -l -c "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK; bash"
Run Code Online (Sandbox Code Playgroud)

正如其他人所指出的那样,如果您要切换到的用户没有对 $SSH_AUTH_SOCK 的读取权限(除了 root 用户,它几乎是任何用户),这将不起作用。您可以通过设置 $SSH_AUTH_SOCK 和它所在的目录来解决这个问题,以获得 777 的权限。

chmod 777 -R `dirname $SSH_AUTH_SOCK`
sudo su otheruser -l -c "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK; bash"
Run Code Online (Sandbox Code Playgroud)

不过这是相当冒险的。您基本上是在授予系统上的所有其他用户使用您的 SSH 代理的权限(直到您注销)。您也可以设置组并将权限更改为 770,这样会更安全。但是,当我尝试更改组时,出现“不允许操作”。

  • 这是极其危险的。授予所有其他用户使用您的 SSH 代理的权限等同于向他们提供您的所有凭据(如果您曾经使用 sudo 或 su,则授予他们对系统上所有其他用户以及您通过 ssh 连接的所有其他系统的 root 权限!) . 这绝对不能做! (7认同)
  • 我不同意“永远不要这样做!”的说法。在很多情况下,这种风险是可以接受的。例如,一个小团队,每个人都拥有相同的权限,并且您信任所有其他用户。在不了解它所涉及的风险的情况下,绝不应该这样做。但是一旦了解了这些风险,有时风险是可以接受的。 (5认同)

Dav*_*osh 6

如果您被授权sudo su - $USER,那么您可能有一个很好的理由被允许ssh -AY $USER@localhost使用 $USER 主目录中的有效公钥来代替。然后您的身份验证转发将与您一起完成。


git*_*rik 6

您始终可以使用代理转发 ssh 到本地主机,而不是使用 sudo:

ssh -A otheruser@localhost
Run Code Online (Sandbox Code Playgroud)

缺点是你需要重新登录,但是如果你在 screen/tmux 选项卡中使用它,那只是一次努力,但是,如果你与服务器断开连接,套接字(当然)会再次断开. 因此,如果您不能始终保持屏幕/tmux 会话处于打开状态,这并不理想(但是,SSH_AUTH_SOCK如果您很酷,可以手动更新您的环境变量)。

另请注意,使用 ssh 转发时,root 始终可以访问您的套接字并使用您的 ssh 身份验证(只要您使用 ssh 转发登录)。因此,请确保您可以信任 root。


war*_*iuc 6

结合其他答案的信息我想出了这个:

user=app
setfacl -m $user:x $(dirname "$SSH_AUTH_SOCK")
setfacl -m $user:rwx "$SSH_AUTH_SOCK"
sudo SSH_AUTH_SOCK="$SSH_AUTH_SOCK" -u $user -i
Run Code Online (Sandbox Code Playgroud)

我喜欢这个,因为我不需要编辑sudoers文件。

在 Ubuntu 14.04 上测试(必须安装acl软件包)。