病情描述

病情描述

病情描述

我在 Ubuntu 18.04.3 LTS 上使用 systemd 和 ssh 遇到了奇怪的情況

我檢查了設備的狀態ssh.socket

$ systemctl status ssh.socket
● ssh.socket - OpenBSD Secure Shell server socket
   Loaded: loaded (/lib/systemd/system/ssh.socket; disabled; vendor preset: enabled)
   Active: inactive (dead)
   Listen: [::]:22 (Stream)
 Accepted: 0; Connected: 0

它處於非活動狀態,但我同時使用 ssh 登錄,並且服務本身正在運行,並且 SSH 的套接字和相應連接埠已開啟:

$ lsof -P -i -n | grep sshd
sshd      26785            root    3u  IPv4 14858764      0t0  TCP 10.200.130.28:22->10.100.40.141:42188 (ESTABLISHED)
sshd      26875          xxx_root    3u  IPv4 14858764      0t0  TCP 10.200.130.28:22->10.100.40.141:42188 (ESTABLISHED)
sshd      63859            root    3u  IPv4   238437      0t0  TCP *:22 (LISTEN)
sshd      63859            root    4u  IPv6   238439      0t0  TCP *:22 (LISTEN)

所以我查看了 ssh.socket 的單元檔案/lib/systemd/system/ssh.socket

[Unit]
Description=OpenBSD Secure Shell server socket
Before=ssh.service
Conflicts=ssh.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Socket]
ListenStream=22
Accept=yes

[Install]
WantedBy=sockets.target

由於Before=ssh.service指令應該在 ssh 服務之前啟動,並且Conflicts=ssh.service指令將導致它在 ssh 服務啟動時停止。

這解釋了為什麼它發生在單元文件方面,但提出了其他問題。

問題

為什麼 ssh.socket 單元的非活動狀態對實際的 ssh 套接字沒有影響?

為什麼維護者加入了該Conflict指令?例如,如果您檢查docker.socket它的單元檔案沒有設定為與docker.service. sshd 的情況有何不同?

附加資訊

我還在舊的 Fedora 30 工作站上檢查了這一點。它具有相同的條件,但有細微的差別:它使用sshd.service和作為單元名稱,並且單元檔案中sshd.socket沒有指令。Beforesshd.socket

在這兩個系統上,我沒有註意到這種情況造成的任何問題,我懷疑它有某種目的,但找不到。

答案1

systemd 套接字是一種特殊類型的單元,它使 systemd 本身綁定到連接埠(或其他資源,例如 unix 網域套接字檔案路徑),並為任何連接產生一個新的服務實例。啟用 ssh.service 後,其 sshd 會連續運作並綁定到套接字,如 lsof 所示。相反,啟用 ssh.socket 意味著 sshd 不會連續運行,而是僅呼叫它的一個實例來處理一個客戶端。相反,它會顯示 systemd 正在偵聽端口 22。

答案2

需要理解的重要一點是,您所看到的是「套接字」單元的一種特定用法,總共有:http://0pointer.de/blog/projects/inetd.html

所以在 的具體情況下ssh.socket,這相當於舊式類似inetd的調用(核心套接字單元設定:)Accept=yes,其中連接埠 22 上的每個傳入請求(由 systemd 管理)都會導致單獨的啟動[email protected] 實例

另請參閱 systemd.socket 手冊頁:https://www.freedesktop.org/software/systemd/man/systemd.socket.html

如果設定 Accept=yes,則服務模板[電子郵件受保護]必須存在,為每個傳入連線實例化服務

所以,一共有兩種不同的方式來啟動 sshd:

  • ssh.servicesshd.service只是一個別名)啟動主 sshd 進程,然後該進程處理所有傳入連接、生成子進程等。
  • ssh.socket+ [email protected],這裡 systemd 將來自套接字管理連接埠的每個傳入連線連接到一個新實例[電子郵件受保護],inetd 風格。這就是為什麼在模板服務中,StandardInput=socket、 和ExecStart=/usr/sbin/sshd-i選項。

顯然,一次只能使用一種方法,因此Conflicts=請確保兩種方法不會同時運行。 (順便一提:該節的實際位置Conflicts=並不重要,可以在 ssh.service 中編寫等效的一節,但一個就足夠了)

相關內容