如何处理从后台任务运行器运行的命令的 SSH 转发?

如何处理从后台任务运行器运行的命令的 SSH 转发?

为了处理 Web 应用程序的任务,我有一个由 systemd 管理的后台“任务运行器”:

[Unit]
Description=Background Job Runner
After=network.target mariadb.service

[Service]
Type=simple
Restart=always
User=sitesdb
ExecStart=/bin/scl enable rh-git29 rh-php71 "/var/www/sitesdb/current/bin/console --env=prod jms-job-queue:run -v"

[Install]
WantedBy=multi-user.target

Web 应用程序将作业排队以供任务运行器执行,而任务运行器会不断寻找要运行的新作业。

其中一个作业在另一台服务器上运行远程 SSH 命令,并且需要将“sitesdb”用户的 SSH 密钥转发到该服务器

由于 systemd 正在启动作业运行器,这如何工作?我需要确保 SSH 代理正在运行,然后需要将用户的 SSH 密钥添加sitesdb到其中,因为该用户是拥有该进程的用户。

一个想法是将启动命令更改为:

eval `ssh-agent -s` && ssh-add && /bin/scl enable rh-git29 rh-php71 "/var/www/sitesdb/current/bin/console --env=prod jms-job-queue:run -v"

但这合适吗?我认为这会在每次我的作业运行器命令终止并必须重新启动时启动多个 SSH 代理(并且它配置为每 15 分钟自动终止一次)。

答案1

代理转发存在一些安全风险,而且在很多情况下,解决问题的方法比使用代理转发更好。我建议您仔细查看要求,看看是否可以在不需要代理转发的情况下解决这些问题。

有时最好的解决方案确实是使用代理转发。因此,我们假设您的场景就是其中之一。

我建议不要使用eval `ssh-agent -s`仅在单个命令持续时间内需要的代理。相反,您可以使用ssh-agent command在这种情况下ssh-agent将运行command并且一旦command退出ssh-agent也将退出。这通常有点简单,但更重要的是,一旦不再需要它,它就会自动清理ssh-agent。对于交互式用例,您可以使用如下命令:

ssh-agent bash

现在您的案例不是交互式的,因此您的命令需要看起来与此略有不同。以下命令不起作用:

ssh-agent ssh-add && /bin/scl enable rh-git29 rh-php71 "/var/www/sitesdb/current/bin/console --env=prod jms-job-queue:run -v"

这是因为ssh-agent只会启动ssh-add命令。一旦将密钥添加到代理,它将关闭,并且命令scl将在没有代理的情况下运行。相反,您可以使用:

ssh-agent sh -c 'ssh-add && /bin/scl enable rh-git29 rh-php71 "/var/www/sitesdb/current/bin/console --env=prod jms-job-queue:run -v"'

如果你觉得这个命令太复杂,可以使用 shell 脚本来使其更清晰。例如:

ssh-agent /usr/local/bin/scl-wrapper-script enable rh-git29 rh-php71 "/var/www/sitesdb/current/bin/console --env=prod jms-job-queue:run -v"

并且/usr/local/bin/scl-wrapper-script可能包含:

#!/bin/bash -e
ssh-add
exec /bin/scl "$@"

显然,变化的可能性是无穷无尽的。例如,您可能不想将所有参数传递scl给包装器脚本。相反,包装器脚本本身可以包含部分或全部参数。

答案2

当用户(站点数据库) 运行 ssh (或 scp、sftp) 它会自动从用户处加载 ssh 密钥 (站点数据库,可能位置/主页/sitesdb/.ssh/) 并将它们提供给远程服务器进行身份验证。

远程服务器检查.ssh/授权密钥ssh 密钥的公钥部分。如果匹配,则会话打开。

为了实现这一点你需要创建ssh 密钥对于 sitesdb 用户没有密码。如果没有密码,您就不需要 ssh-agent。

在远程服务器上,以您登录的用户身份(也是 sitesdb?)配置 ssh 密钥的公共部分。使用命令ssh-复制-id

如果你手动设置.ssh/授权密钥在远程服务器上,目录的文件模式位.ssh应该是 700,对于文件授权密钥600

使用 ssh 手动测试,它应该会将您登录到远程服务器。如果没有,则 ssh 密钥设置不正确。

編輯:

您有 3 台服务器:

  • 本地人
  • B:远程跳跃服务器,有 ssh 公钥
  • C:远程cmd服务器

SSH 密钥验证在 A 和 B 之间有效。

为了“转发” ssh 密钥以使其在 C 服务器上工作,您必须在 C 上进行交互式登录并准备与 B 相同的 ssh 密钥。

您可以使用工具预计自动从 B 到 C 进行 ssh 登录,例如执行ssh-复制-id预计

在不同的语言中,expect 有多种实现。

https://core.tcl.tk/expect/index

https://pexpect.readthedocs.io/en/stable/

相关内容