通过不同子网实现 LAN 唤醒

通过不同子网实现 LAN 唤醒

我有 3 个 IP 块和 3 个 Cisco 交换机。每个交换机都有自己的 IP 块 - 10.45.100.0/24、10.45.101.0/24 和 10.45.102.0/24

我有一台位于 10.45.100.0/24 块上的 PC。我可以用 C# 唤醒此 IP 块中的全部计算机(包括 IP 地址、Mac 地址、子网、端口)。

但是当我尝试从不同的 IP 块唤醒另一台机器时,它不起作用。

这是网络问题还是代码问题?我该如何解决?

答案1

这是一个根本问题:睡眠呼吸暂停仅在子网内有效,因为 WOL 魔术包不是有效的 IP 包,因此无法在本地 LAN 之外进行路由。

维基百科条目概述了此问题的解决方案(子网定向广播),但我从未见过实际操作。解决此问题的另一种方法可能是创建一个 WOL 代理,将 WOL 数据包转发到其他子网(即作为 UDP 数据包)。

答案2

如果您有三个不同的子网,那么如果没有路由器,这些子网就无法相互通信。

这是 100% 故意为之。

你尝试执行 WOL 的机器的默认网关必须明确地知道如何到达其他子网,否则它会将您的数据包发送到互联网上,然后您的 ISP 会立即丢弃它。

因此,您有两个选择:

  1. 在子网之间设置正确的路由
  2. 将子网掩码减小到 255.255.0.0 (/16) 之类的值,以便所有计算机都位于同一子网中。我不建议这样做,因为我确信您的计算机彼此之间划分子网是有原因的。

答案3

一个可能的解决方案:在控制 PC 上添加第二张(甚至第三张)NIC 卡,然后配置其他 IP 地址以直接与其他路由器连接。然后,魔术包将根据 WOL 命令中的目标 IP(IP、MAC、子网、端口)传递关联的 NIC。

答案4

我有一个解决方案,但它适用于固定 IP 地址。我不知道,但也许可以更改代码来修复动态地址的问题。

您只需要将一个魔术包发送到您计算机的固定地址即可。我创建了一个小实用程序。

我的子网是 172.17.111.0/24,数据包从 172.17.105.0/24 发送

class Program
{
    static readonly Tuple<string, byte[]>[] Addr = {
        new Tuple<string, byte[]>("**-**-30-9D-98-61", new byte[] { 172, 17, 111, 91 }),
        new Tuple<string, byte[]>("**-**-D9-7B-9D-E9", new byte[] { 172, 17, 111, 70 }),
    };

    static void Main(string[] args)
    {
        var id = args.Length > 0 ? int.Parse(args[0]) : 0;

        WolClass client = new WolClass();
        client.Connect(new IPAddress(Addr[id].Item2),  0x9); 
        client.SetClientToBrodcastMode();
        //set sending bites
        int counter = 0;
        //buffer to be send
        byte[] bytes = new byte[1024];   
        //first 6 bytes should be 0xFF
        for (int y = 0; y < 6; y++)
            bytes[counter++] = 0xFF;
        //now repeate MAC 16 times
        for (int y = 0; y < 16; y++)
        {
            int i = 0;
            for (int z = 0; z < 6; z++)
            {
                bytes[counter++] = byte.Parse(Addr[id].Item1.Substring(i, 2), 
                                              NumberStyles.HexNumber);
                i += 3;
            }
        }

        //now send wake up packet
        client.Send(bytes, 1024);
    }
}

public class WolClass : UdpClient
{
    //this is needed to send broadcast packet
    public void SetClientToBrodcastMode()
    {
        if (this.Active)
            this.Client.SetSocketOption(SocketOptionLevel.Socket,
                SocketOptionName.Broadcast, 0);
    }
}

相关内容