Perl 服务器中基于 SSH 密钥的身份验证

Perl 服务器中基于 SSH 密钥的身份验证

我有一个用 Perl 编写的服务器,客户端连接到该服务器以执行一些管理任务。不谈细节,我想实现两件事:

  1. 加密服务器和客户端之间的连接通道——可以使用 IO::Socket::SSL 来完成。
  2. 使用 SSH 密钥对客户端进行身份验证 - 我还不知道如何做到这一点。

最好的解决方案是将这两个要求合并为一个,并拥有一个与 SSH 连接/身份验证完全相同的机制。这可能吗?

谢谢。

答案1

您想使用 SSH 隧道。这将加密您的通信并使用 SSH 密钥进行身份验证。

如果您希望客户端用 perl 编写,那么请使用类似 Net::SSH::Perl 模块:http://search.cpan.org/~turnstep/Net-SSH-Perl-1.34/lib/Net/SSH/Perl.pm

如果不了解有关您的设置的更多信息,我真的无法帮助您完全实现 SSH 隧道。

答案2

SSH 使用密钥,而 SSL 倾向于使用 X.509 证书(顺便说一下,SSH 不是基于 SSL)。

(公钥) 证书不仅仅是一个公钥:它是公钥、标识符(例如主题 DN)和其他属性之间的关联,整个过程都经过签名(由 X.509 证书的颁发者签名)。

例如,当使用 RSA 时,可以提取公钥材料(模数和公钥指数)并将其转换为证书。此模型缺少的是 SSH 密钥,它们不是像 X.509 证书那样“签名”或“颁发”的。您将在模型中缺少 SSL 中经常使用的 PKI 方面。解决这个问题的一个简单方法是用它制作一个自签名证书。然后,您必须在客户端中明确导入它以使其受信任,或者在第一次连接到它时导入它(毕竟,这与第一次连接到 SSH 服务器时发生的情况非常相似)。

SSH 和 X.509 的 RSA 密钥格式不同,因此您需要编写一些代码来从 SSH 密钥中读取模数和指数,并以 SSL 堆栈可用的格式生成 X.509 证书和私钥。

StackOverflow 上的问题应该是有趣的(尽管它是反过来的)。

答案3

除了简单地通过 SSH 隧道建立连接之外,Chris Ting 指出

您可以实现 SSH 子系统,这样您的程序就可以与 SSH 无缝集成。对于用户来说,您的程序看起来只是使用 SSH 密钥和加密(由于实际使用 SSH,因此实际上确实如此)。尽管 OpenSSH SFTP 客户端和服务器在某种程度上是自文档化的,但该过程并没有得到很好的文档记录。

这需要进行大量重写,具体取决于客户端的连接方式和协议的语法。但明显的好处是,它可以无缝地融入用户的 SSH 配置中。

答案4

我之前写过类似的服务器/客户端应用程序。基本设计:

  • 服务器不进行网络操作,它是通过 stdin/stdout 流进行通信的简单脚本(类似于 inetd 执行的守护进程);
  • 所有网络和身份验证工作均由 ssh/sshd 完成,客户端使用基于密钥授权的 ssh,服务器有一个带有 command="" 选项的 authorized_keys 文件 - 该密钥始终执行我的服务器,不能用于访问 shell 或其他程序;

示例.ssh/authorized_keys文件:

no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding,from="10.0.0.1",command="/usr/local/bin/fsdumps-receiver" ssh-rsa AAAA.... key_comment

注意 from="<ip>" 选项 - 本例中的访问仅限于一个 IP。

服务器代码可以访问一些有用的环境变量。例如:

  • $ENV{'SSH_ORIGINAL_COMMAND'} - “命令”(不是真的)传递为ssh server_ip that_command
  • $ENV{'SSH_CLIENT'} - 客户端 IP

您可以使用 SSH_ORIGINAL_COMMAND 在服务器中选择管理任务。客户端代码可以使用此任务名称作为参数生成 ssh(或使用 Net::SSH::Perl),然后向服务器发送数据或从服务器接收数据。

相关内容