在 SFTP 登录不再工作并出现错误 127 后,我们发现 SSH 连接通过安装在 /etc/profile.d/ 中的脚本创建了一些输出。
以前版本的 sshd 有一个名为“UseLogin”的选项,默认设置为“no”,因此不会执行配置文件中的内容。现在该选项似乎不再存在,并且默认行为似乎已更改。
在 sshd_config 中我现在替换了
Subsystem sftp /usr/lib/ssh/sftp-server
经过
Subsystem sftp internal-sftp
这似乎工作得更好(SFTP 正在工作)。
但众所周知:如果你不明白它为什么起作用,它就没有被修复。
有人可以解释一下吗?也许建议一个更好的“修复”?
更新SLES15.4(openssh-server-8.4p1)
答案1
SFTP 使用 SSH 作为传输。任何 SFTP 客户端都希望 SSH 服务器与 SFTP 服务器建立通信(如sftp-server
)。
至少对于 OpenSSH,当 SSH 服务器被告知运行某些内容时,它会使用目标用户的 shell 来执行此操作。
Subsystem …
可以通过在 中添加条目来定义子系统(可能是自定义子系统)sshd_config
。即使这样,所提供的命令也将在用户的 shell 中执行。当标准sftp
子系统指定为 时,您就发生了这种情况/usr/lib/ssh/sftp-server
。
当您的 SFTP 客户端期望与 SFTP 服务器通信时,如果 shell(或其他任何东西)打印出一些“垃圾”,则它超出了 SFTP 协议的范围,因此通信会中断。
只要 SSH 服务器使用用户的 shell,就没有任何选项可以完全可靠地使一切正常工作。这是因为一般来说:
- 用户的外壳可以是任何东西。
- 即使是理智的 shell 也会获取一些文件。某些 shell 可能被告知不要这样做,但没有可移植的选项,并且客户端无法告诉 SSH 服务器在调用 shell 时使用自定义选项。
- 源文件可能会打印一些东西;或者他们可能会运行一些打印东西的东西。
避免用户 shell 的唯一方法是使用由 SSH 服务器内部处理的子系统。 AFAIK 目前sshd
OpenSSH 中唯一的内部子系统是internal-sftp
.
internal-sftp
解决了你的问题,因为它不依赖于外壳。
另一种修复方法是确保除 SFTP 服务器之外的任何其他服务器都使用 SSH 服务器提供的标准流。该解决方案包括使用户的 shell 静音和shell 在运行实际请求的命令(例如/usr/lib/ssh/sftp-server
.在服务器上具有 root 访问权限的人或用户自己可能很容易破坏这一点。
一些有趣的案例,供比较:
一个不幸的编辑将
.bashrc
用户锁定在外。这通过 SSH 自行修复的唯一方法是internal-sftp
。如果internal-sftp
尚未启用,用户将需要使用 SSH 以外的某些协议来修复问题(例如,联系管理员就是此类协议)。一个用户想要跑步命令不受(可能是愚蠢的)远程 shell 的任何干扰。
答案2
没关系。
有人进入了LD_LIBRARY_PATH=/some/path
/ /etc/profile.d/xxx
some/path ,其中包含过时的库(例如 libcrypto),以使一些古老的东西可以工作。我只想说我不觉得好笑。这也是破坏 sftp-server 的原因
/usr/lib/ssh/sftp-server: symbol lookup error: /usr/lib/ssh/sftp-server: undefined symbol: EVP_KDF_CTX_new_id, version OPENSSL_1_1_1d
更新目前尚不清楚修复上述问题是否会使 sftp-server 再次工作,因为仍然存在从 profile.d 创建的输出。我没试过。它可能只会有固定的错误/退出代码 127,但随后会生成不同的错误。
由于内部 sftp 既不使用坏库也不创建登录 shell(有关详细信息,请参阅@kamil-maciorowski 的回答),因此这可能是唯一的出路。除了将 profile.d 中的脚本调整为仅对某些 uid 执行(例如不针对 uid 0),因此在某些情况下不会生成任何输出。