与我的团队一起,我们需要共享一些私钥并将它们存储在经过存储库。
因此,我不是提取密钥并将其以明文形式存储在文件系统上,而是寻找一种仅将解密版本短暂保留在内存中的方法:
$ sftp -i <(pass foo) user@host
Warning: Identity file /dev/fd/63 not accessible: No such file or directory.
知道为什么 sftp 无法读取临时文件描述符吗?如何修复它?
答案1
知道为什么
sftp
无法读取临时文件描述符吗?
几个事实:
- 进程
<(pass foo)
替换将导致bash
创建一个管道,pass foo
异步运行命令,其输出连接到管道的写入端,并将 替换<(...)
为 形式的路径/dev/fd/63
,其中63
是引用管道读取端的文件描述符。 - 这
/dev/fd/63
是一个特殊的路径,允许进程stat()
重新打开其文件描述符之一引用的文件。 - shell forks + execs
sftp
,然后sftp
本身 forks 和 execsssh
,导致63
文件描述符通过继承向下传递。 ssh
将要关闭其所有文件描述符使用该函数的 0、1、2 除外closefrom()
。这也将关闭 fd63
。
由于63
不再是进程中打开的文件描述符ssh
,因此stat()
on/dev/fd/63
将失败并出现来自 OP 的错误。
如何修复它?
将密钥临时存储在内存中的文件系统中。在我的Debiansystemd
下为我提供了tmpfs/run/user/<myUID>
。除了我(当然还有root)之外,任何人都无法访问该挂载点。
请注意,在您的用户(或根用户)下运行的恶意进程可以读取该文件。但是这样的过程也可以从原始方法中sshd
的文件描述符中读取。63
或者,当没有可用的安全 tmpfs 时:
创建临时 fifo。注意
mktemp
不能直接执行此操作。安全的方法是创建一个临时私有的目录然后mkfifo
在里面。确保fifo本身的权限较窄,否则
ssh
会报错。跑步
sftp -i "/temp_dir/the_fifo" user@host
并行运行
pass foo > "/temp_dir/the_fifo"
。一个怪癖:你需要这样做两次;至少在我的 Debian 中ssh
读取密钥两次。以下命令似乎在我的测试中有效:cat ~/.ssh/id_rsa > "/temp_dir/the_fifo" && cat ~/.ssh/id_rsa > "/temp_dir/the_fifo"
。也许类似的重复命令适合您:pass foo > "/temp_dir/the_fifo" && pass foo > "/temp_dir/the_fifo"
您可以之前在后台运行它
sftp
(除非pass
是交互式的,我根本不熟悉该工具)。最后删除 fifo 和目录。
尽管如此,在您的用户(或 root)下运行的恶意进程仍然可以先从 fifo 中读取ssh
数据。