操作系统: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.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
答案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 开发者没有接受它。