OpenSSH 子系统(或 command= option)背后的原理是什么?

0xC*_*22L 3 openssh svn-server ssh-tunnel

在 OpenSSH 中,可以在配置文件 ( /etc/ssh/sshd_config) 中声明一个子系统或强制执行命令,例如svnserve通过将其包含在authorized_keys特定键的行中,如下所示:

command="svnserve -t --tunnel-user=alice" ssh-dss AAAA...
command="svnserve -t --tunnel-user=bob" ssh-dss AAAA...
Run Code Online (Sandbox Code Playgroud)

从而允许同一系统用户在 Subversion ( svnserve) 上下文中被重用为不同的“身份” 。

我将如何编写像svnserve我这样的服务,允许指定隧道的使用以及在这些情况下数据传输的确切方式?特别是svnserve实例如何“知道”通过哪种方式输出数据或读取输入?在这种情况下,这一切是否都是通过stdout和发生的stdin,如果是这样,是否也有区分的方法stderr

我想象子系统和command=它们使用相同的机制,但如果我错了,请纠正我。

no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty为了简洁起见,我省略了,但我知道它们以及它们在场景中的用途。)

use*_*686 5

首先,请注意command=不会调用 SSH 子系统。它只是运行命令,就好像它是在 SSH 客户端的命令行上给出的一样;例如

ssh yourhost "svnserve -t --tunnel-user=alice"

ssh yourhost "git upload-pack /pub/git/myproject.git"

ssh yourhost "ls -la"
Run Code Online (Sandbox Code Playgroud)

上述例子中应该让该通信更清晰svnservegitls发生在相同的标准输入输出(标准输入/输出/ stderr的)任何其它SSH相互作用。对于SVN和Git,ssh客户端只是作为远程调用命令的工具。


使用 中的Subsystem选项配置的“真实”子系统sshd_config并没有太大不同。唯一的主要区别是它们可以通过静态的、众所周知的名称调用,而不是依赖远程登录 shell(bash、zsh、&c)来查找正确的可执行文件。例如,SFTP 服务器可以/usr/lib/ssh/sftp-server在一台机器上,MULTINET_COMMON_ROOT:[MULTINET]SFTP-SERVER2.EXE在另一台机器上,内置sshd在第三个(子系统 sftp internal-sftp)中,但在所有情况下,客户端仍然可以使用名称找到它sftp

至少在 OpenSSH 中,子系统可以像通过 stdin/stdout/stderr 与客户端通信的普通程序一样编写。但是,似乎不允许传递任意命令行参数,因此您不能只svnserve为所有用户配置一个子系统。