我正在尝试在所有接口上发送 WOL 包,以唤醒网关(这是 DHCP 服务器,因此机器还没有 IP)。

而且似乎我只能将套接字绑定到IP和端口对......

所以问题是:如何创建绑定到没有 IP 的 NIC 的套接字(或其他东西)?(任何语言都可以。c# 优先)

@克塔克:我知道WOL是通过MAC地址完成的...我的问题是Windows仅在Windows认为是主NIC的NIC上发送UDP广播(这甚至不是我的Vista机器上具有默认路由的NIC)。我似乎无法找到一种方法将套接字绑定到没有 IP 地址的接口。(就像 DHCP 客户端这样做一样)

@阿诺特:为什么不?客户端知道网关的MAC地址。我只想像 DHCP 客户端最初那样发送 WOL 数据包...(DHCP 发现数据包声称来自 0.0.0.0)我不介意是否必须逐字节构造整个数据包...

有帮助吗?

解决方案

看来,我发现了一个解决方案。人们可以利用WinPcap的注入数据包到任何接口。 而且有很好的包装为.NET: http://www.tamirgal.com /home/dev.aspx?Item=SharpPcap

(I会者优先,其需要安装无额外的库中的溶液...)

更新:这里是我想出了所有接口上发送WOL包:

//You need SharpPcap for this to work

private void WakeFunction(string MAC_ADDRESS)
{
    /* Retrieve the device list */
    Tamir.IPLib.PcapDeviceList devices = Tamir.IPLib.SharpPcap.GetAllDevices();

    /*If no device exists, print error */
    if (devices.Count < 1)
    {
        Console.WriteLine("No device found on this machine");
        return;
    }

    foreach (NetworkDevice device in devices)
    {
        //Open the device
        device.PcapOpen();

        //A magic packet is a broadcast frame containing anywhere within its payload: 6 bytes of ones
        //(resulting in hexadecimal FF FF FF FF FF FF), followed by sixteen repetitions 

        byte[] bytes = new byte[120];
        int counter = 0;
        for (int y = 0; y < 6; y++)
            bytes[counter++] = 0xFF;
        //now repeat MAC 16 times
        for (int y = 0; y < 16; y++)
        {
            int i = 0;
            for (int z = 0; z < 6; z++)
            {
                bytes[counter++] =
                    byte.Parse(MAC_ADDRESS.Substring(i, 2),
                    NumberStyles.HexNumber);
                i += 2;
            }
        }

        byte[] etherheader = new byte[54];//If you say so...
        var myPacket = new Tamir.IPLib.Packets.UDPPacket(EthernetFields_Fields.ETH_HEADER_LEN, etherheader);

        //Ethernet
        myPacket.DestinationHwAddress = "FFFFFFFFFFFFF";//it's buggy if you don't have lots of "F"s... (I don't really understand it...)
        try { myPacket.SourceHwAddress = device.MacAddress; }
        catch { myPacket.SourceHwAddress = "0ABCDEF"; }//whatever
        myPacket.EthernetProtocol = EthernetProtocols_Fields.IP;

        //IP
        myPacket.DestinationAddress = "255.255.255.255";
        try { myPacket.SourceAddress = device.IpAddress; }
        catch { myPacket.SourceAddress = "0.0.0.0"; }
        myPacket.IPProtocol = IPProtocols_Fields.UDP;
        myPacket.TimeToLive = 50;
        myPacket.Id = 100;
        myPacket.Version = 4;
        myPacket.IPTotalLength = bytes.Length - EthernetFields_Fields.ETH_HEADER_LEN;           //Set the correct IP length
        myPacket.IPHeaderLength = IPFields_Fields.IP_HEADER_LEN;

        //UDP
        myPacket.SourcePort = 9;                
        myPacket.DestinationPort = 9;           
        myPacket.UDPLength = UDPFields_Fields.UDP_HEADER_LEN;


        myPacket.UDPData = bytes;
        myPacket.ComputeIPChecksum();
        myPacket.ComputeUDPChecksum();

        try
        {
            //Send the packet out the network device
            device.PcapSendPacket(myPacket);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

        device.PcapClose();
    }
}

其他提示

WOL由MAC,而不是IP进行。 下面是一个例子

WOL 是一种非常灵活的协议,可以通过多种不同的方式实现。

最常见的是:

  • 发送 WOL 作为以太网数据包的有效负载。
  • 发送 WOL 作为 UDP 数据包的有效负载(用于通过网络路由)。

一旦它到达本地网络,它就会使用广播 MAC 地址传递到网络上的所有主机。

对于以太网数据包,其结构为:

  • 目标MAC:FF:FF:FF:FF:FF:FF(广播)
  • 神奇的数据包有效负载

对于 UDP 数据包,其结构为:

  • 目标MAC:FF:FF:FF:FF:FF:FF(广播)
  • UDP端口:9
  • 神奇的数据包有效负载

魔法有效负载包括:

  • 同步流:FFFFFFFFFFFF(即 6 对或 6 个字节的 FF)
  • 您向 WOL 发送信号的计算机的 16 个 MAC 副本
  • 0、4 或 6 字节的可选密码。

要从互联网接收 WOL 数据包(通过防火墙/路由器):

  • 配置路由器端口 9 转发到 IP 255.255.255.255(广播 IP)
  • 设置目标IP:路由器的外部IP

笔记:这只能使用 UDP 示例来实现,因为以太网数据包缺乏通过互联网路由数据包所需的 IP 层。IE,以太网数据包是仅限本地网络的选项。通过 UDP 发送 WOL 数据包的问题是安全性,因为您必须将路由器设置为启用 IP 广播 (255.255.255.255)。启用 IP 广播通常被认为是一个坏主意,因为会增加网络内部攻击的风险(Ping 泛洪、缓存欺骗等)。

有关协议的更多信息(包括示例捕获)请参阅 这个网站.

如果您想要一个快速而肮脏的命令行工具来生成 WOL 数据包(并且您在 debian、linux mint 或 Ubuntu 上运行),您可以安装一个已经执行此操作的工具。

只需使用命令行进行安装:

sudo apt-get install wakeonlan

更新:

下面是一个使用当前版本的 SharpPcap 生成 WakeOnLan 数据包的工作示例。

using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using PacketDotNet;
using SharpPcap;

namespace SharpPcap.Test.Example9
{
    public class DumpTCP
    {
        public static void Main(string[] args)
        {
            // Print SharpPcap version
            string ver = SharpPcap.Version.VersionString;
            Console.WriteLine("SharpPcap {0}, Example9.SendPacket.cs\n", ver);

            // Retrieve the device list
            var devices = CaptureDeviceList.Instance;

            // If no devices were found print an error
            if(devices.Count < 1)
            {
                Console.WriteLine("No devices were found on this machine");
                return;
            }

            Console.WriteLine("The following devices are available on this machine:");
            Console.WriteLine("----------------------------------------------------");
            Console.WriteLine();

            int i = 0;

            // Print out the available devices
            foreach(var dev in devices)
            {
                Console.WriteLine("{0}) {1}",i,dev.Description);
                i++;
            }

            Console.WriteLine();
            Console.Write("-- Please choose a device to send a packet on: ");
            i = int.Parse( Console.ReadLine() );

            var device = devices[i];

            Console.Write("What MAC address are you sending the WOL packet to: ");
            string response = Console.ReadLine().ToLower().Replace(":", "-");

            //Open the device
            device.Open();

            EthernetPacket ethernet = new EthernetPacket(PhysicalAddress.Parse(
                "ff-ff-ff-ff-ff-ff"), PhysicalAddress.Parse("ff-ff-ff-ff-ff-ff"),
                EthernetPacketType.WakeOnLan);
            ethernet.PayloadPacket = new WakeOnLanPacket(
                PhysicalAddress.Parse(response));
            byte[] bytes = ethernet.BytesHighPerformance.Bytes;

            try
            {
                //Send the packet out the network device
                device.SendPacket(bytes);
                Console.WriteLine("-- Packet sent successfuly.");
            }
            catch(Exception e)
            {
                Console.WriteLine("-- "+ e.Message );
            }

            //Close the pcap device
            device.Close();
            Console.WriteLine("-- Device closed.");
            Console.Write("Hit 'Enter' to exit...");
            Console.ReadLine();
        }
    }
}

笔记:这是一个功能齐全的 LAN 唤醒数据包发送控制台应用程序,基于可在 SharpPcap 源代码中找到的 Example09 构建。

本示例中使用的在 .NET 框架中找不到的库有:

using PacketDotNet;

该库 (.dll) 与 SharpPcap 一起打包。它负责 SharpPcap 内的所有数据包构建和解析。这是 WakeOnLan 类所在的位置。

笔记:数据包构建/解析代码最初捆绑在 SharpPcap.dll 中。它被迁移到自己的库,因为 SharpPcap 旨在成为 winpcap 的包装器。它的许多用户负责设计协议和/或处理原始网络数据包。

using SharpPcap;

SharpPcap 包含所有 winpcap(windows)/libpcap(*nix) 包装器代码。需要选择接口并通过线路发送实际的数据包。

.NET作为虚拟机(在CLR)进行操作,所以它抽象了许多潜在的真机。例如,它仅提供了TCP和UDP网络,这是您要讨论什么网络协议栈更高的接口。你也许可以找到一个第三方组件,提供访问较低级别的接口,但我不会指望它(我已经看了过去对.NET和Java)。

有关访问在网络协议栈低,则可能需要在C代码相关的OS的系统调用。你会发现这个最容易在Python中,你会发现在Python的或第三方的库已经实现了这个功能。举例来说,我建议采取看看扭曲的网络库。这是的,我转向Python的大部分我的工作的原因之一。

最佳的愿望。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top