重新启动 Systemd 服务的顺序

重新启动 Systemd 服务的顺序

操作系统:Debian 11 Bullseye

语境:

  • 泽罗蒂尔应用程序添加zerotier-one.service系统服务并创建虚拟网络接口(当它工作时)。
  • 服务器sshd默认监听所有地址0.0.0.0

在那之前,我一切都很好

现在我引入自定义配置,/etc/ssh/sshd_config.d/my-sshd.conf添加ListenAddress 192.168.10.10我的sshd服务器仅接受 Zerotier 接口地址的调用。

现在我怀疑sshd.service之前启动过,zerotier-one.service因为重新启动计算机后:

$ sudo systemctl status sshd.service
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Thu 2023-09-14 17:21:27 CEST; 28s ago
       Docs: man:sshd(8)
             man:sshd_config(5)
    Process: 524 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
    Process: 551 ExecStart=/usr/sbin/sshd -D $SSHD_OPTS (code=exited, status=255/EXCEPTION)
   Main PID: 551 (code=exited, status=255/EXCEPTION)
        CPU: 21ms

systemd[1]: Starting OpenBSD Secure Shell server...
sshd[551]: error: Bind to port 22 on 192.168.10.10 failed: Cannot assign requested address.
sshd[551]: fatal: Cannot bind any address.
systemd[1]: ssh.service: Main process exited, code=exited, status=255/EXCEPTION
systemd[1]: ssh.service: Failed with result 'exit-code'.
systemd[1]: Failed to start OpenBSD Secure Shell server

所以我添加了使用以下命令After=进行更改的选项:/etc/systemd/system/ssh.service.d/override.confsudo systemctl edit sshd.service

[Unit]
After=network.target auditd.service

到:

[Unit]
After=network.target auditd.service network-online.target zerotier-one.service

现在看起来像这样:

$ sudo systemctl cat sshd.service
# /lib/systemd/system/ssh.service
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
Alias=sshd.service

# /etc/systemd/system/ssh.service.d/override.conf
[Unit]
After=network.target auditd.service network-online.target zerotier-one.service

但重启电脑后,仍然出现该错误

当我现在做时sudo systemctl restart sshd.service我得到:

$ sudo systemctl status sshd.service
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
    Drop-In: /etc/systemd/system/ssh.service.d
             └─override.conf
     Active: active (running) since Thu 2023-09-14 17:40:43 CEST; 2s ago
       Docs: man:sshd(8)
             man:sshd_config(5)
    Process: 3065 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
   Main PID: 3066 (sshd)
      Tasks: 1 (limit: 9423)
     Memory: 1.0M
        CPU: 21ms
     CGroup: /system.slice/ssh.service
             └─3066 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups

systemd[1]: Starting OpenBSD Secure Shell server...
sshd[3066]: Server listening on 192.168.10.10 port 22.
systemd[1]: Started OpenBSD Secure Shell server.

我的印象是sshd.service之前还在开始zerotier-one.service

是否缺少某些内容或可以进行不同的检查吗?

除了添加之外我还应该做点别的zerotier-one.serviceAfter=

编辑(其他用户的信息):

除了@telkoM提出的解决方案(我感谢你)之外,另一个技巧解决了我的问题:

只需将指令添加ExecStartPost=sleep 10zerotier-one.serviceExecStartPre=sleep 10sshd.service

答案1

按照你的配置,sshd.service肯定会启动之后zerotier-one.service 开始。但这还不够。需要sshd.service等到 Zerotier 实际上连接成功,这可能会发生相当晚的时间(至少在计算机时间尺度上)。和当前的zerotier-one.service甚至没有试图将该信息提供给systemd

[Unit]
Description=ZeroTier One
After=network-online.target network.target
Wants=network-online.target

[Service]
ExecStart=/usr/sbin/zerotier-one
Restart=always
KillMode=process

[Install]
WantedBy=multi-user.target

您可能必须创建一个Type=oneshot服务(可以称为zerotier-wait-online.service)来运行一个脚本,该脚本包含一个循环,该循环调用 例如zerotier-cli listnetworks或 justip addr show并查找 IP 地址 192.168.10.10。如果不可用,脚本将休眠几秒钟并重试。

当脚本看到地址出现时,脚本将退出 - 这将告诉systemd配置为运行的任何服务After=zerotier-wait-online.service现在可以继续。 (与默认服务Type=simple和其他几种服务类型不同,服务仅在其主进程启动Type=oneshot后才被视为“启动”ExecStart成功退出- 这正是您所需要的。

一旦您使该服务正常工作,您可以将sshd.service覆盖更改为After=zerotier-wait-online.service,然后它应该按您想要的方式工作。

请注意,您不能简单地要求zerotier-wait-online.service运行Before=network-online.target,因为zerotier-one.service它本身会运行After=network-online.target。试图设立这样的要求会造成不可能的情况。


问题的根源在于,使用ListenAddress会带来启动时指定地址必须已经存在的要求sshd

如果您需要sshd监听 Zerotier IP 地址仅有的,但不必特别使用ListenAddress来实现它,您可以使用其他方法来实现限制。

在 中/etc/ssh/sshd_config,您可以添加Match这样的块,以拒绝对除 Zerotier 之外的任何本地 IP 地址的访问:

Match LocalAddress *,!192.168.10.10
    DenyUsers *

iptables或者,如果目标地址不是 192.168.10.10 之外的任何地址,您可以使用删除/拒绝传入连接:

iptables -I INPUT 1 -p tcp --dport 22 \! -d 192.168.10.10/32 -j DROP

DROP使被阻止的连接尝试挂起,直到超时;如果您希望阻止的连接快速失败,请改用如下规则:

iptables -I INPUT 1 -p tcp --dport 22 \! -d 192.168.10.10/32 -j REJECT --reject-with tcp-reset

如果您使用ufw或其他一些防火墙管理系统,可能有一种方法可以为其配置等效规则。

答案2

任何解决方法都会不断出现问题,因为这是解决问题的不正确层。它不在 systemd 或 Zerotier 上..它是 sshd 需要允许设置 IP_自由绑定套接字选项允许它侦听“尚未”或“曾经”配置的地址。 }

这是执行此操作的补丁https://bugzilla.mindrot.org/attachment.cgi?id=2763,这是正确的,但不幸的是 openSSH 开发者没有接受它。

相关内容