操作系统:Debian 11 Bullseye
语境:
- Zerotier应用程序添加系统服务并创建虚拟网络接口(当它工作时)。
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.conf
sudo 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.service
吗After=
?
编辑(其他用户的信息):
除了@telkoM提出的解决方案(我感谢你)之外,另一个技巧解决了我的问题:
只需将指令添加ExecStartPost=sleep 10
到zerotier-one.service
或ExecStartPre=sleep 10
到sshd.service
按照你的配置,肯定只有在starts
sshd.service
之后才会启动。但这还不够。需要等到 Zerotier 实际连接成功,这可能会在相当长的一段时间后发生(至少在计算机时间尺度上)。当前甚至没有尝试向以下人员提供该信息:zerotier-one.service
sshd.service
zerotier-one.service
systemd
您可能必须创建一个
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 地址的访问:iptables
或者,如果目标地址不是 192.168.10.10 之外的任何地址,您可以使用删除/拒绝传入连接:DROP
使被阻止的连接尝试挂起,直到超时;如果您希望阻止的连接快速失败,请改用如下规则:如果您使用
ufw
或其他一些防火墙管理系统,可能有一种方法可以为其配置等效规则。任何解决方法都会不断出现问题,因为这是解决问题的不正确层。它不在 systemd 或 Zerotier 上。 sshd 需要允许设置 IP_FREEBIND套接字选项,以允许它侦听“尚未”或“曾经”配置的地址。}
这是执行此操作的补丁https://bugzilla.mindrot.org/attachment.cgi?id=2763,它是正确的,但不幸的是 openSSH 开发人员没有接受它。