Linux systemd:在网络真正启动后启动服务(用于WoL)

Linux systemd:在网络真正启动后启动服务(用于WoL),linux,networking,ssh,systemd,Linux,Networking,Ssh,Systemd,我有一台工作中的电脑,有时我会从家里醒来以访问它,但当启动并从我们的DHCP服务器获得另一个IP地址时,我如何访问它 情况和我的“工作流程”如下: 我从家用电脑连接到办公室的VPN ssh连接到office LAN中的专用服务器(具有固定IP地址) 在该服务器上,我调用一个脚本,该脚本用我的办公室PC的MAC地址广播WoL数据包 我的office PC启动了(它确实启动了!) 现在理论上,只要我知道我的办公室电脑的IP地址,我就可以通过SSH连接到它。 有时是一样的,有时是变化的。 为了避免

我有一台工作中的电脑,有时我会从家里醒来以访问它,但当启动并从我们的DHCP服务器获得另一个IP地址时,我如何访问它

情况和我的“工作流程”如下:

  • 我从家用电脑连接到办公室的VPN
  • ssh连接到office LAN中的专用服务器(具有固定IP地址)
  • 在该服务器上,我调用一个脚本,该脚本用我的办公室PC的MAC地址广播WoL数据包
  • 我的office PC启动了(它确实启动了!)
现在理论上,只要我知道我的办公室电脑的IP地址,我就可以通过SSH连接到它。 有时是一样的,有时是变化的。 为了避免这种情况,我有以下想法:

  • 启动后,我的office PC会对office服务器执行SSH,并将其自己的IP地址写入服务器上的某个文本文件中
  • 我在服务器上检查该文件(由于其固定IP,我可以连接到该文件),找到我的office PC的IP地址,然后可以通过SSH从我的家用PC连接到我的office PC
所有计算机都运行Linux;Ubuntu 14.04在家,SLES在办公服务器上,OpenSUSE 13.1在我的办公电脑上。这都不是问题

为了让这一切正常工作,我只需要在我的office PC上安装一个脚本,当网络启动并运行时,它会在启动时运行

我的脚本(publish_ip.sh)如下所示:

# get own IP address:
ip=$(ip addr show | awk '$1=="inet" && $2 !~ /127\.0\.0\.1/ { split($2, a, "/"); print a[1]}');

# SSH to the office server (10.64.5.84) and write own IP address to a file there:
ssh -x -e none 10.64.5.84 "echo $(date) $ip >> office_pc_address.txt"
要在启动时运行此脚本,我为我的office PC创建了一个systemd服务文件publish-ip.service:

[Unit]
Description=publishes own IP address
Wants=network.target
After=network.target

[Service]
Type=oneshot
ExecStartPre=/usr/bin/sleep 30
ExecStart=/home/perldog/bin/publish_ip.sh
User=perldog

[Install]
WantedBy=multi-user.target
linux-tz7m:/usr/lib/systemd/system # systemctl status publish-ip.service
publish-ip.service - publishes own IP address
   Loaded: loaded (/usr/lib/systemd/system/publish-ip.service; enabled)
   Active: failed (Result: exit-code) since Mon 2016-02-29 12:17:34 CET; 4 days ago
  Process: 1688 ExecStart=/home/perldog/bin/publish_ip.sh (code=exited, status=255)
  Process: 1016 ExecStartPre=/usr/bin/sleep 30 (code=exited, status=0/SUCCESS)
 Main PID: 1688 (code=exited, status=255)

Feb 29 12:17:34 linux-tz7m publish_ip.sh[1688]: ssh: connect to host 10.64.5.84 port 22: Network is unreachable
但这是我在办公室电脑上经常看到的:

[Unit]
Description=publishes own IP address
Wants=network.target
After=network.target

[Service]
Type=oneshot
ExecStartPre=/usr/bin/sleep 30
ExecStart=/home/perldog/bin/publish_ip.sh
User=perldog

[Install]
WantedBy=multi-user.target
linux-tz7m:/usr/lib/systemd/system # systemctl status publish-ip.service
publish-ip.service - publishes own IP address
   Loaded: loaded (/usr/lib/systemd/system/publish-ip.service; enabled)
   Active: failed (Result: exit-code) since Mon 2016-02-29 12:17:34 CET; 4 days ago
  Process: 1688 ExecStart=/home/perldog/bin/publish_ip.sh (code=exited, status=255)
  Process: 1016 ExecStartPre=/usr/bin/sleep 30 (code=exited, status=0/SUCCESS)
 Main PID: 1688 (code=exited, status=255)

Feb 29 12:17:34 linux-tz7m publish_ip.sh[1688]: ssh: connect to host 10.64.5.84 port 22: Network is unreachable
显然,我的服务会启动并调用我的脚本,但该脚本中的SSH命令会失败,
网络无法访问

我尝试了我的服务文件中的所有内容,以便它只在网络启动后运行,但我没有得到它。我尝试了
Wants=network.target
After=network.target
WantedBy=multi-user.target
,甚至插入了一个
ExecStartPre=/usr/bin/sleep 30
。什么都没用。 当调用脚本并尝试通过SSH连接到office服务器时,我总是发现网络不可访问

问题:我的服务文件中需要哪些设置,以便它仅在通过SSH访问office server之后运行

注意:当我在办公室并且我的office PC启动并运行时,我的脚本和服务都能正常工作,即
systemctl start publish ip.service

工作正常。

以前有一个名为arpwatch的工具,它记录所有联网设备的IP地址和MAC地址,因此您可以简单地查询计算机的MAC并获取IP

还有一个叫做arping的工具,你可以通过grep搜索MAC地址的输出

另一种选择是保持计算机上的随机端口打开,并使用nmap扫描整个网络以查找特定端口,或者nmap扫描整个网络以查找已启动的主机并grep查找您的MAC地址

nmap -sP 192.168.1.0/24

这不是一个完整的解决方案,但我在计算机启动后设置了一个SSH隧道;它每5秒重新启动一次,以防止在网络仍处于关闭状态时因垃圾邮件而被杀死;如果您可以将固定IP系统用作堡垒主机,您可以将类似的内容与WOL结合使用:

[Unit]
Description=Keep open a reverse tunnel to my home server
After=network.target

[Service]
ExecStart=/usr/bin/ssh -NT hometunnel
RestartSec=5
Restart=always

[Install]
WantedBy=multi-user.target
root.ssh/config的相关部分:

Host                    hometunnel
HostName                <redacted>
IdentityFile    /root/.ssh/<redacted>
User                    <redacted>
RemoteForward   <redacted> localhost:22
ExitOnForwardFailure yes
ServerAliveInterval 60
ServerAliveCountMax 5
hosthometunnel
主机名
IdentityFile/root/.ssh/
使用者
RemoteForward本地主机:22
ExitOnForwardFailure是
ServerAliveInterval 60
ServerAliveCountMax 5

我尝试了所有这些目标,它们都是在DHCP获得IP地址之前到达的。想象一下:

  • 网络在线。目标
  • 远程fs.目标
  • nfs客户端。目标
  • dbus.service
是什么工作促成了这两个目标:

systemctl enable systemd-networkd.service systemd-networkd-wait-online.service
然后设置

After=systemd-networkd-wait-online.service
Wants=systemd-networkd-wait-online.service
现在它是在DHCP获得IP地址后启动的。(A,但也可能是你的服务)


(在debian9/stretch上)

您可以通过添加ping循环作为ExecStartPre脚本来延迟作业的启动:

[Service]
   ExecStartPre=/bin/sh -c 'until ping -c1 google.com; do sleep 1; done;'

谢谢,但我的office server上没有安装arpwatch、arping和nmap:-(我已经搜索了“如何从MAC地址获取IP地址”,但没有结果。这就是为什么我想到了我的方法。我承认这太复杂了。@PerlDog,ARP就是将第三层(IP)地址重新写入第二层(MAC地址)根据你的评论,这听起来与你想要的正好相反。有一个地方你可以从MAC地址到IP地址查找,那就是DHCP服务器,假设主机使用DHCP分配其IP地址。@RonMaupin谢谢,但我尝试了所有这些
ping-b 10.64.255.255;arp-na | grep$MAC
建议。它们都不起作用我很确定我没有访问我们网络中DHCP服务器的“查询”权限(我不是根用户)。所以我想到了这个发布ip脚本,但它也不起作用:-(因为它在网络启动之前运行)。@PerlDog、ip和以太网从来都不是为局域网发现而设计的。你可以获得一个源(DHCP服务器)这正是您所需要的。许多主机现在都有防火墙,防火墙可以并且通常可以阻止ping和其他可用于LAN发现的东西。静态分配的主机(带有连接到有线以太网交换机的软件防火墙)在LAN上几乎是看不见的。您可以有一个永远发送ARP请求的应用程序“局域网上可能有一个IP地址,但这可能是非常多的地址,而且需要很长时间。@RonMaupin当然。为了避免这种情况,我的脚本开始了。如果你愿意,它有点像穷人的DynDNS,也就是说,它将IP发布到一个众所周知的位置。我想我应该重新表述我的问题(或发布一个新的问题)所以它更强调了systemd/network up的问题。我写了所有这些东西是因为我想避免出现一个。看起来我也可以尝试
ExecStartPre=/bin/sh-c',直到ping-c1 google.c