如何通过没有 IP 地址的网卡发送 WOL 包(或任何东西)?
-
22-07-2019 - |
题
我正在尝试在所有接口上发送 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的大部分我的工作的原因之一。
最佳的愿望。