在 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...
从而允许相同的系统用户可以在 Subversion()上下文中重复使用不同的“身份” svnserve
。
我该如何编写一个像svnserve
我这样的服务,允许指定隧道的使用以及在这些情况下数据究竟是如何传输的?特别是实例如何svnserve
“知道”通过哪种方式输出数据或读取输入?在这种情况下,这一切都是通过stdout
和发生的吗stdin
?如果是这样,是否有办法区分stderr
?
我想象子系统和command=
使用相同的机制,但如果我错了,请纠正我。
(no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty
为了简洁我省略了它们,但我知道它们以及它们在场景中的用途。)
答案1
首先,请注意,它command=
不会调用 SSH 子系统。它只是运行命令,就像在 SSH 客户端的命令行上给出命令一样;例如
ssh yourhost "svnserve -t --tunnel-user=alice"
ssh yourhost "git upload-pack /pub/git/myproject.git"
ssh yourhost "ls -la"
上述示例应该更清楚地表明,与svnserve
或git
的通信ls
与任何其他 SSH 交互一样,通过相同的 stdio(stdin/stdout/stderr)进行。对于 SVN 和 Git,客户ssh
端仅用作远程调用命令的工具。
Subsystem
使用中的选项配置的“真实”子系统sshd_config
并没有太大区别。唯一的主要区别是它们可以通过静态、众所周知的名称调用,而不是依赖远程登录 shell(bash、zsh 等)来查找正确的可执行文件。例如,SFTP 服务器可以位于/usr/lib/ssh/sftp-server
一台机器上,MULTINET_COMMON_ROOT:[MULTINET]SFTP-SERVER2.EXE
另一台机器上,内置sshd
在第三台机器中(子系统 sftp internal-sftp),但在所有情况下客户端仍然可以使用名称找到它sftp
。
至少在 OpenSSH 中,子系统可以像通过 stdin/stdout/stderr 与客户端通信的普通程序一样编写。但是,似乎不允许传递任意命令行参数,因此您不能只svnserve
为所有用户配置一个子系统。