如果我拥有可以使用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). 


#1 楼

如您所述,出于安全原因,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@serverA中提供了user2@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


评论


这是正确答案,应加以标记。

– Xealot
2011年1月2日,15:33

仅当上面的user2是root时,这才有效!否则,user2将正确设置SSH_AUTH_SOCK,但是user2将无法访问例如/ tmp / ssh-GjglIJ9337 /。 root确实具有该访问权限。因此,这可能会解决部分问题,但不能解决OP:“并且套接字只能由我的原始用户读取”

– Peter V.Mørch
2011年11月4日21:00



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

–Paul Schyska
2014年8月24日10:32



我从来不明白为什么人们仍然使用sudo su。如果您需要root shell,那就是sudo -s或sudo -i的目的。

–eaj
16年11月16日14:46

@eaj的历史原因。 sudo -i最初不存在,后来又添加了。因此,很多人养成了sudo su的习惯,并且许多文档都是用旧方法编写的。尽管它已经有15年的历史了。

– Zoredache
19-10-9在21:20

#2 楼

sudo -E -s



-E将保留环境
-s运行命令,默认为shell

,这将为您提供带有原始密钥仍在加载。

评论


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

– doshea
16年8月13日在8:29



您还可以通过使用sudo --preserve-env = SSH_AUTH_SOCK来指定仅保留SSH_AUTH_SOCK环境变量,而不保留所有环境变量。

–泰勒·里克(Tyler Rick)
20 Jan 3 '20在1:49



@TylerRick给出了正确的答案。

–greatvovan
20年5月1日在23:29

#3 楼

切换到其他用户之前,例如通过正确的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用户;-)

评论


请记住,使用此方法时,以其他用户身份登录的其他人也可以使用您的ssh身份验证。

–gitaarik
13年11月27日在14:49

这对我有用,除了我必须将“ sudo su-otheruser”更改为“ sudo su otheruser”(删除-)。

–查尔斯·芬克尔
2014年3月17日在18:09

为什么选择rwx而不选择rw(或完全取消r)?

–anatoly techtonik
2014年10月21日在21:21

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

– mixel
17年3月18日在15:21

不必编辑/ etc / sudoers,可以使用sudo -u otheruser --preserve-env = HOME -s

–秒
19年1月31日,12:29

#4 楼

我发现这也可以。

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,这可能更安全。但是,当我尝试更改组时,出现“不允许操作”。

评论


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

– Matija Nalis
2014年6月6日18:11

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

– phylae
2014年3月7日在22:52



#5 楼

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

评论


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

–法哈德·萨达(Fahad Sadah)
2010-1-28的16:46

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

–voretaq7
2010-1-28的16:48

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

–法哈德·萨达(Fahad Sadah)
2010-1-28的16:52

#6 楼

您总是可以通过代理转发将ssh切换到localhost,而不是使用sudo:屏幕/ tmux选项卡,这只是一次工作,但是,如果断开与服务器的连接,套接字(当然)将再次断开。因此,如果您无法始终保持屏幕/ tmux会话始终处于打开状态(这很不理想)(但是,如果凉爽的话,您可以手动更新SSH_AUTH_SOCK env var)。

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

评论


如果您只能通过sudo而不是通过SSH访问其他用户,则此方法将无效(例如,您想将SCP内容作为www-data)

– Gert van den Berg
19-09-27在9:31

这使用原始的ssh用户而不是su用户解决了我的mysql命令问题,这可能是其自动用户检测便利例程中的一些错误。

– Malhal
20年1月2日在20:45

#7 楼

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

评论


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

–大卫·麦金托什(David Mackintosh)
10年1月28日在20:58

在Debian Lenny上运行的Sudo 1.6.9p17版本。尝试sudo -s吗?

–法哈德·萨达(Fahad Sadah)
2010-1-30在7:48

对我不起作用。

–弗洛里安·舒尔茨(Florian Schulze)
2010年2月1日于12:31

在Ubuntu上,使用Sudo 1.8.9p5,sudo -s和sudo -i都不适合我...

–乔恩·L。
2014年12月29日在16:12

#8 楼

结合其他答案中的信息,我得出了这样的结论: >已在Ubuntu 14.04上测试(必须安装sudoers软件包)。

#9 楼

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

如果您阅读su的手册页,您可能会发现-, -l, --login选项以登录身份启动外壳程序环境贝壳。无论运行otheruser的env变量如何,这都会加载su的环境。
简单地说,连字符会破坏您从sudo传递的任何内容。
相反,您应该尝试以下命令:
sudo -E su otheruser

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

#10 楼

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

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

评论


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

–弗洛里安·舒尔茨(Florian Schulze)
2010-2-1在12:34

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

–voretaq7
2010-2-1在16:14



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

– knite
2013年6月26日在2:25



@knite您是正确的-这是我的答案中的一个(3岁!)错字。现在已修复:-)

–voretaq7
2013年6月26日17:13

#11 楼

我使用了以下组合:
$ chmod g+rwx -R $(dirname $SSH_AUTH_SOCK)
$ sudo -HPEu ubuntu bash
$ ssh-add -L
ssh-rsa AAAA..kd /home/kolypto/.ssh/id_rsa


赋予ssh代理套接字更多的权限
以另一个用户(-u)的身份运行命令(bash),从而保护环境(-E) ,保留原始用户组(-P)并正确设置$HOME-H
验证ssh密钥是否可用