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


152

如果我拥有可以使用ssh密钥登录到的服务器A,并且具有“ sudo su-otheruser”的能力,则将丢失密钥转发,因为已删除了env变量,并且套接字只能由原始用户读取。有没有办法可以通过“ sudo su-otheruser”桥接密钥转发,以便可以使用转发的密钥(在本例中为git clone和rsync)在服务器B上做一些事情?

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

简而言之:

$ sudo -HE ssh user@host
(success)
$ sudo -HE -u otheruser ssh user@host
Permission denied (publickey). 

Answers:


182

如前所述sudo,出于安全原因,环境变量被删除。

但是幸运的sudo是,它是可配置的:由于中的env_keep配置选项,您可以准确地告诉它要保留哪些环境变量/etc/sudoers

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

Defaults    env_keep+=SSH_AUTH_SOCK

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

1
这是正确答案,应予以标记。
Xealot 2011年

41
只是工作,如果user2上面root!否则,user2将正确设置SSH_AUTH_SOCK,但是user2将无法访问例如/ tmp / ssh-GjglIJ9337 /。root确实具有该访问权限。因此,这可能会解决部分问题,但不能解决部分操作问题:“ 并且套接字只能由我的原始用户读取”
Peter V.Mørch

6
Defaults>root env_keep+=SSH_AUTH_SOCK应该确保它仅在根进行sudoing时才转发。出于安全原因,您始终不想对其他用户执行此操作。最好为其他其他服务器运行单独的ssh-agent,并添加适当的密钥。
Paul Schyska 2014年

1
sudo su -不适用于我,大概是因为它不是sudo在Shell启动时保存的,因此无法保存环境。sudo su似乎有效。
亚历克斯·福图纳

3
我从来不明白人们为什么要使用sudo su。如果你需要一个root shell,这就是sudo -s或者sudo -i是。
eaj 2016年

68
sudo -E -s
  • -E将保护环境
  • -s运行命令,默认为shell

这将为您提供一个根shell,且原始密钥仍处于加载状态。


2
与上面的注释一样,这仅解决了您是否要成为root用户的问题,因为在这种情况下,root用户可以绕过$ SSH_AUTH_SOCK的常规访问权限。
doshea '16

35

在切换到其他用户之前,例如通过正确的ACL,允许其他用户访问$SSH_AUTH_SOCK文件及其目录。该示例假定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$

更安全,也适用于非root用户;-)


6
请记住,使用此方法时,其他otheruser用户也可以使用您的ssh身份验证进行登录。
gitaarik 2013年

这对我有用,除了我必须将“ sudo su-otheruser”更改为“ sudo su otheruser”(删除-)。
查尔斯·芬克尔2014年

1
为什么rwx而不是rw(或根本不r)?
anatoly techtonik 2014年

3
@anatolytechtonik从man 7 unix-在Linux上,连接到套接字需要对该套接字具有读写权限。另外,您需要在创建套接字的目录上具有搜索(执行)和写入权限,或者在连接到此套接字时仅具有搜索(执行)权限。因此,在上述答案中,对套接字的执行权限是多余的。
mixel

而不必编辑/ etc / sudoers文件,你可以使用sudo -u otheruser --preserve-env=HOME -s
二段

14

我发现这也有效。

sudo su -l -c "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK; bash"

正如其他人指出的那样,如果您要切换到的用户没有$ 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"

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


6
这是非常危险的。授予其他用户使用SSH代理的权限等同于为他们提供所有凭据(并且,如果您曾经使用sudo或su,则向他们授予系统上所有其他用户以及ssh所使用的所有其他系统的root用户权限!) 。永远不要这样做!
Matija Nalis 2014年

4
我不同意“永远不要这样做!”这一说法。在很多情况下,这种风险是可以接受的。例如,一个小团队,每个人都具有相同的权限,而您信任所有其他用户。如果不了解其所涉及的风险,则决不能这样做。但是一旦了解了这些风险,有时风险就可以接受了。
phylae 2014年

6

如果您被授权使用sudo su - $USER,那么您可能有一个很好的论据,可以被允许ssh -AY $USER@localhost使用$ USER的主目录中的有效公共密钥来进行替代。然后,您的身份验证转发将随身进行。


他在问题的底部提到了这一点,并表示很难做到。
Fahad Sadah 2010年

这可能是最好的解决方案,但如果$ USER是Real Person(tm),它就会变得很毛茸茸-他们可能会从authorized_keys中删除SA的密钥或更改其密码...
voretaq7

您可以删除他们对authorized_keys的写访问权限(尽管如果他们确实设置为拒绝Florian访问,他们可以删除并重新创建它,因为它位于他们拥有的目录中)
Fahad Sadah 2010年

4

您始终可以通过代理转发将ssh转到localhost,而不是使用sudo:

ssh -A otheruser@localhost

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

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


如果您只能otheruser通过sudo而不是通过SSH来访问,则此方法不起作用(例如,您想以SCP的身份访问www-data
Gert van den Berg

3

不要用sudo su - USER,而是用sudo -i -u USER。为我工作!


您有什么版本的sudo?我的(1.6.7p5,CentOS 4.8)的手册页中没有-i。
David Mackintosh,2010年

Sudo version 1.6.9p17在Debian Lenny上运行。试试sudo -s
Fahad Sadah'1

6
对我不起作用。

在Ubuntu上,使用sudo 1.8.9p5,既不sudo -s也不是sudo -i为我工作...
乔恩·L.

2

结合其他答案中的信息,我得出了以下结论:

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

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

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


1

我认为您的命令中的-(破折号)选项存在问题su

sudo su - otheruser

如果阅读su的手册页,您可能会发现该选项-, -l, --login以登录shell身份启动shell环境。otheruser无论您在何处运行env变量,都将为环境提供支持su

简而言之,破折号会破坏您从中传递的任何东西sudo

相反,您应该尝试使用以下命令:

sudo -E su otheruser

正如@ joao-costa指出的那样,-E它将在您运行的环境中保留所有变量sudo。然后没有破折号,su将直接使用该环境。


0

不幸的是,当您向另一个用户求助(甚至使用sudo)时,您将失去使用转发密钥的能力。这是一项安全功能:您不希望随机用户连接到ssh-agent并使用密钥:)

“ ssh -Ay $ {USER} @localhost”方法有点麻烦(并且正如我对David的答案容易破损的评论所指出的那样),但这可能是您可以做到的最好的方法。


1
嗯,但是如果我使用ssh进行操作,则无论如何该用户都可以访问我的代理,还是我错了?

如果通过代理转发将SSH SSH到目标用户,则代理请求将弹回“真实”代理所在的任何位置。当您远离原始用户su或sudo时,将无法(或不应)访问SSH代理套接字-SSH代理套接字所在的目录为模式700,且由原始用户拥有。(显而易见的警告:如果您要切换到root用户并重置SSH_AUTH_SOCK环境,它可能会起作用,但我不会依靠它)
voretaq7'2

1
在我的服务器(Ubuntu 12.04,ssh版本OpenSSH_5.9p1 Debian-5ubuntu1.1,OpenSSL 1.0.1,2012年3月14日)上,ssh具有-a-A参数。-a完全相反,将禁用代理转发!因此,在Ubuntu的最新版本(可能是所有版本)下,用于-A启用代理转发。
knite

@knite您是正确的-这是我的答案中的一个(3岁!)错字。立即修复:-)
voretaq13年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.