systemd 如何将 sshd 进程放入切片中?

systemd 如何将 sshd 进程放入切片中?

我正在诊断我管理的 SSH 堡垒。这台机器在任何给定时间点都有大约 5500 个带端口转发的 SSH 连接。

最近,我遇到了一个问题,由于包含所有这些 sshd 进程的用户切片达到了 MaxTasks 限制,因此 SSH 连接被拒绝。

这对我来说是新情况,在诊断过程中,我注意到 user.slice 并不像我想象的那样保存所有 sshd 进程。其中大约一半(不准确)由 system.slice 保存。起初我以为那可能是 root 进程,而用户特定的进程(特权分离)由 user.slice 保存。然而,事实并非如此。它似乎是随机的。

我确实注意到 user.slice 持有的进程在每个会话中都很好地分开,而 system.slice 持有的进程只是在 ssh.service 下持有,没有进一步的分离。

# systemd-cgls
[...]
│ ├─user-1031.slice
│ │ ├─session-719.scope
│ │ │ ├─5559 sshd: <user> [priv]
│ │ │ └─6224 sshd: <user>
│ │ ├─session-617.scope
│ │ │ ├─4963 sshd: <user> [priv]
│ │ │ └─5392 sshd: <user>
│ │ ├─session-515.scope
│ │ │ ├─3862 sshd: <user> [priv]
│ │ │ └─4693 sshd: <user>
│ │ ├─session-413.scope
│ │ │ ├─3049 sshd: <user> [priv]
│ │ │ └─3988 sshd: <user>
[...]
└─system.slice
  ├─ssh.service
  │ ├─  338 sshd: <user> [priv]
  │ ├─  352 sshd: <user>
  │ ├─  353 sshd: <user>
  │ ├─  358 sshd: <user>
  │ ├─  385 sshd: <user> [priv]
  │ ├─  391 sshd: <user>
  │ ├─  392 sshd: <user>
[...]
  • systemd 如何决定将进程放在一个切片或另一个切片中?
  • 他们感动了吗?
  • 有没有办法准确可靠地将所有这些会话置于适当的 user.slice 下,以便我可以管理允许的进程数设置的限制?

答案1

OpenSSH 权限分离实现每个连接一个特权进程和一个非特权进程

每个用户切片是 systemd-logind.service 的一个功能,由pam_systemd。我不清楚为什么还有一堆文件在 systemd.slice 中。也许它们使用 PAM 堆栈的方式不同。

单个用户切片可容纳 5500 个 SSH 连接?对于一个用户来说,这比一般情况要多,但你可以这样做。

我建议将用户切片上的 pids.max 设置得非常高,但不要无限大。超过您预期的连接数的两倍。为此,请创建/etc/systemd/logind.conf.d/local.conf并自定义:

[Login]
UserTasksMax=16000

如果 ssh.service 下有几千个以上的任务,也请考虑提高其限制。这次,使用通用资源控制指令,因此定制化程度的下降 /etc/systemd/system/ssh.service.d/local.conf

[Service] 
TasksMax=16000 

答案2

在寻找其他东西时偶然发现了这一点。我不确定,但由于没有其他人回答,我将给出未经证实的理论:

sshd 直接启动其私有进程和用户进程(不通过 systemd)。由于它们不是任何 systemd 进程的子进程,因此无法可靠地检测它们的来去**,而只能猜测。它的猜测似乎基于 pam 会话钩子**,我相信 sshd 确实调用了 pam_session_open 和 pam_session_close****。

如果只是猜测,有时它也会像任何人一样猜错。

假设我的理论是正确的,那么你的问题的答案将是:

systemd 如何决定将进程放在一个切片或另一个切片中?

登录用户的进程(例如 sshd)明确调用 pam_session_open,最终运行 /etc/pam.d 文件中的一系列“会话”条目。(至少在我当前的 debian 上,sshd 将“sshd”作为服务名称传递给 pam,因此 pam 从 /etc/pam.d/sshd“会话”条目开始。)其中一个会话条目是“-session 可选 pam_systemd.so”,它会触发对 pam_systemd.so 的 pam_sm_session_open 的调用,它会与 systemd 本身对话,本质上是说“嘿,用户 xxx 已登录”。我认为 systemd 随后会查找相关进程并声明它们是用户 xxx 切片的一部分。*****

他们感动了吗?

我的答案是,它们只会在 systemd 的脑海中移动,而不会在 linux 进程层次结构中移动 :-)

有没有办法准确可靠地将所有这些会话置于适当的 user.slice 下,以便我可以管理允许的进程数设置的限制?

我的答案是否定的,不修改 sshd 是不行的,但是......

在您的特定情况下,这些进程是否真的需要 systemd?如果它们只是转发到其他地方,那么可能不需要?在这种情况下,您可以调整 /etc/pam.d 文件,以便 sshd 根本不会触发 pam_systemd。那么如果您想限制这些进程,您可以可靠地使用 linux 用户限制吗?

* 我基于 ps -ef | grep sshd 并通过其父母跟踪子进程

** 这是我对于 unix 进程的可能过时的理解,如果它不再准确,我很乐意有人更新我的理解

*** 至少基于答案 1 中提到的“pam_systemd”

****我想我知道这一点,但真的记不起从哪里来的,所以不能说它不是 100%

***** 我相信“sshd”作为服务名称在 sshd 源中是硬编码的,但它们的发行版和版本会调整源代码;pam 文件处理在“man pam”及其“另请参阅”中有详细说明,尽管可能有更易读的描述

答案3

为避免疑问:请确保您使用的是 OpenSSH,并且 sshd 具有 UsePAM=yes。这是 Debian 等操作系统的默认设置,但不是 OpenSSH 上游默认设置。

如果没有 UsePAM=yes,libpam_systemd.so 将永远不会加载,因此它的钩子将永远不会运行。

这也适用于运行 tinysshd、dropbear 或 GNU ssh 的任何人。

相关内容