通过具有套接字激活功能的systemd用户单元的按需SSH Socks代理未按预期重启


14

为了到达隔离的网络,我使用 -D

为了避免每次我将它们添加到时都需要输入细节~/.ssh/config

$ awk '/Host socks-proxy/' RS= ~/.ssh/config
Host socks-proxy
  Hostname pcit
  BatchMode yes
  RequestTTY no
  Compression yes
  DynamicForward localhost:9118

然后,我创建了一个服务单元定义文件:

$ cat ~/.config/systemd/user/SocksProxy.service 
[Unit]
Description=SocksProxy Over Bridge Host

[Service]
ExecStart=/usr/bin/ssh -Nk socks-proxy

[Install]
WantedBy=default.target

我让守护程序重新加载新的服务定义,启用新服务,启动它,检查其状态,并验证它是否在侦听:

$ systemctl --user daemon-reload
$ systemctl --user list-unit-files | grep SocksP
SocksProxy.service   disabled

$ systemctl --user enable SocksProxy.service
Created symlink from ~/.config/systemd/user/default.target.wants/SocksProxy.service to ~/.config/systemd/user/SocksProxy.service.

$ systemctl --user start SocksProxy.service 
$ systemctl --user status SocksProxy.service 
● SocksProxy.service - SocksProxy Over Bridge Host
   Loaded: loaded (/home/alex/.config/systemd/user/SocksProxy.service; enabled)
   Active: active (running) since Thu 2017-08-03 10:45:29 CEST; 2s ago
 Main PID: 26490 (ssh)
   CGroup: /user.slice/user-1000.slice/user@1000.service/SocksProxy.service
           └─26490 /usr/bin/ssh -Nk socks-proxy

$ netstat -tnlp | grep 118
tcp     0    0 127.0.0.1:9118        0.0.0.0:*             LISTEN     
tcp6    0    0 ::1:9118              :::*                  LISTEN

这按预期工作。然后,我想避免通过使用进行按需(重新)而手动启动该服务或使用永久运行该服务。那没有用,我认为(我的版本)无法接收套接字文件描述符。 ssh

我找到的文档(12),和一个例子使用systemd-socket-proxyd-工具来创建2“包装”服务,“服务”和“插座”:

$ cat ~/.config/systemd/user/SocksProxyHelper.socket 
[Unit]
Description=On Demand Socks proxy into Work

[Socket]
ListenStream=8118
#BindToDevice=lo
#Accept=yes

[Install]
WantedBy=sockets.target

$ cat ~/.config/systemd/user/SocksProxyHelper.service 
[Unit]
Description=On demand Work Socks tunnel
After=network.target SocksProxyHelper.socket
Requires=SocksProxyHelper.socket SocksProxy.service
After=SocksProxy.service

[Service]
#Type=simple
#Accept=false
ExecStart=/lib/systemd/systemd-socket-proxyd 127.0.0.1:9118
TimeoutStopSec=5

[Install]
WantedBy=multi-user.target

$ systemctl --user daemon-reload

似乎有效,直到ssh死亡或被杀死。然后它不会在应有的下一次连接尝试时重新生成。

问题:

  1. / usr / bin / ssh真的不能接受通过systemd的套接字吗?还是只有较新的版本?Mine是up2date Debian 8.9中一个
  2. 仅root用户可以使用该BindTodevice选项吗?
  3. 为什么旧隧道消失后,我的代理服务在第一个新连接上无法正确重生?
  4. 这是设置“按需ssh袜子代理”的正确方法吗?如果不是,您该怎么做?

autossh如果连接失败(尽管不是系统方式),则应注意重新连接。
雅库耶

@Jakuje:谢谢您的评论,但我不希望该连接永久存在。我希望在使用它时生成它,然后(理想情况是在X分钟内无数据发送超时后)自行终止。另外,我以前的解决方案使用autossh
Alex Stragies

Answers:


4
  • / usr / bin / ssh真的不能接受通过systemd的套接字吗?

考虑到以下几点,我认为这并不奇怪。

  • OpenSSH是一个OpenBSD项目
  • systemd仅支持Linux内核
  • systemd支持将需要作为可选的/构建时依赖项显式添加到OpenSSH,因此可能很难做到。

  • 仅root用户可以使用该BindTodevice选项吗?

用户系统实例通常是非常隔离的,例如不能与主pid-0实例通信。诸如依靠用户单位文件中的系统单位之类的事情是不可能的。

BindToDevice提及的文档:

请注意,设置此参数可能会导致将其他依赖项添加到单元(请参见上文)。

由于上述限制,我们可以暗示该选项不适用于用户系统实例。


  • 为什么旧隧道消失后,我的代理服务在第一个新连接上无法正确重生?

据我了解,事件链如下:

  • SocksProxyHelper.socket 开始。
  • SOCKS客户端连接到localhost:8118。
  • systemd启动SocksProxyHelper.service
  • 作为的依赖项SocksProxyHelper.service,systemd也将启动SocksProxy.service
  • systemd-socket-proxyd接受systemd套接字,并将其数据转发给 ssh
  • ssh 死亡或被杀。
  • 系统通知,并SocksProxy.service使其处于非活动状态,但不执行任何操作。
  • SocksProxyHelper.service保持运行并接受连接,但无法连接到ssh,因为它不再运行。

解决方法是添加BindsTo=SocksProxy.serviceSocksProxyHelper.service。引用其文档(添加了重点):

配置需求依赖性,其样式与十分相似Requires=。但是,这种依赖关系类型更强:除了Requires=它的作用还声明,如果绑定到的单元已停止,该单元也将停止。这意味着绑定到另一个突然进入非活动状态的单元的单元也将停止。单元可能由于不同的原因突然进入非活动状态:服务单元主要过程可能会自行终止,设备单元的备用设备可能会被拔出,或者安装单元的安装点可能会在没有涉及的情况下被卸载。系统和服务经理。

当与After=同一单元结合使用时,其性能BindsTo=更强。在这种情况下,绑定到的单元必须严格处于活动状态,此单元也必须处于活动状态。这不仅是指与另一部突然进入非激活状态的单位,也是一个绑定到另一个单元都不会被跳过由于失败的状况检查(如ConditionPathExists=ConditionPathIsSymbolicLink=... -见下文)将被停止,应该的正在运行。因此,在许多情况下,最好与结合BindsTo=使用After=


  • 这是设置“按需ssh袜子代理”的正确方法吗?如果不是,您该怎么做?

可能没有“正确的方法”。这种方法有其优点(一切都是“按需”)和缺点(取决于systemd,由于ssh尚未开始侦听,因此第一个连接没有通过)。也许在autossh中实现systemd套接字激活支持将是一个更好的解决方案。


我已经在该行之后添加BindsTo=SocksProxy.service到文件的Unit部分。现在,当SSH死掉/ gets_killed时,不再需要手动重新启动SocksProxy服务。有没有办法让systemd“保持”初始连接,以便它不进行TCP重置?~/.config/systemd/user/SocksProxyHelper.serviceAfter=SocksProxy.service
Alex Stragies

@Vladimir Panteleev我想澄清一点:对systemd套接字激活的支持可以通过解析$LISTEN_FDS而相对容易地实现,而无需添加依赖sd_listen_fds(),因此它可能仍然很难卖,但也不太难。
阿米尔(Amir)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.