Как отправить пакет WOL (или что-нибудь вообще) через ник, который не имеет IP-адреса? - PullRequest
7 голосов
/ 15 января 2009

Я пытаюсь отправить пакет WOL на все интерфейсы, чтобы разбудить шлюз (который является сервером DHCP, поэтому у машины еще не будет IP).

И похоже, что я могу связывать сокеты только с парами IP и портов ...

Итак, вопрос таков: как создать сокет (или что-то еще), связанный с сетевым адаптером, у которого нет IP? (Любой язык в порядке. C # предпочтительнее)

@ ctacke: Я знаю, что WOL выполняется по MAC-адресу ... Моя проблема заключается в том, что Windows отправляет только широковещательные рассылки UDP на сетевую карту, которую Windows считает основной сетевой картой (которая даже не является сетевой картой с включенным маршрутом по умолчанию). моя виста машинка). И я не могу найти способ привязать сокет к интерфейсу, который не имеет IP-адрес. (как это делают клиенты DHCP)

@ Арно: Почему бы и нет? Клиенты знают MAC-адрес шлюза. Я просто хочу отправить WOL-пакет, как это делает изначально DHCP-клиент ... (DHCP обнаруживает, что пакеты обнаруживаются с 0.0.0.0) Я не возражаю, если мне придется создавать весь пакет байт за байтом ...

Ответы [ 4 ]

8 голосов
/ 15 января 2009

Кажется, я нашел решение. Можно использовать winpcap для внедрения пакетов в любой интерфейс. И есть хорошая обертка для .net: http://www.tamirgal.com/home/dev.aspx?Item=SharpPcap

(я бы предпочел решение, которое не требует установки дополнительных библиотек ...)

ОБНОВЛЕНИЕ: Вот что я пришёл для отправки пакета 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();
    }
}
2 голосов
/ 10 ноября 2010

WOL - это очень гибкий протокол, который может быть реализован несколькими различными способами.

Наиболее распространенными являются:

  • Отправка WOL в качестве полезной нагрузки пакета Ethernet.
  • Отправка WOL в качестве полезной нагрузки пакета UDP (для маршрутизации по сети).

Как только он попадает в локальную сеть, он передается всем хостам в сети, используя широковещательный MAC-адрес.

Для пакета Ethernet структура:

  • MAC-адрес получателя: FF: FF: FF: FF: FF: FF (широковещательная передача)
  • Полезная нагрузка пакета магии

Для пакета UDP структура:

  • MAC-адрес получателя: FF: FF: FF: FF: FF: FF (Broadcast)
  • UDP-порт: 9
  • Полезная нагрузка пакета магии

Магическая полезная нагрузка состоит из:

  • Поток синхронизации: FFFFFFFFFFFF (это 6 пар или 6 байтов FF)
  • 16 копий MAC-адреса компьютера, на который вы посылаете WOL
  • Необязательный пароль 0, 4 или 6 байтов.

Для получения пакетов WOL из Интернета (через брандмауэр / маршрутизатор):

  • Настройка порта 9 маршрутизатора для переадресации на IP 255.255.255.255 (Broadcast IP)
  • Установка IP-адреса получателя: внешний IP-адрес маршрутизатора

Примечание. Этого можно достичь только на примере UDP, поскольку в пакетах Ethernet отсутствует уровень IP, необходимый для маршрутизации пакета через Интернет. IE, Ethernet-пакеты доступны только для локальной сети. Проблема с отправкой пакетов WOL через UDP связана с безопасностью, поскольку необходимо настроить маршрутизатор для включения IP-вещания (255.255.255.255). Включение широковещательной передачи по IP обычно считается плохой идеей из-за дополнительного риска внутренней атаки в сети (переполнение Ping, подмена кэша и т. Д.).

Подробнее о протоколе, включая пример захвата, см. этот сайт .

Если вам нужен быстрый и грязный инструмент командной строки, который генерирует пакеты WOL (и вы работаете в Debian, Linux Linux или Ubuntu), вы можете установить инструмент, который уже делает это.

Просто установите с помощью командной строки:

sudo apt-get install wakeonlan

Обновление:

Вот рабочий пример, который генерирует пакет WakeOnLan с использованием текущей версии SharpPcap.

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();
        }
    }
}

Примечание. Это полнофункциональное консольное приложение для отправки пакетов Wake-On-Lan, созданное на примере Example09, которое можно найти в источнике SharpPcap.

Библиотеки, используемые в этом примере, которые не могут быть найдены в .NET Framework:

using PacketDotNet;

Эта библиотека (.dll) поставляется в комплекте с SharpPcap. Он отвечает за всю конструкцию пакета и его разбор в SharpPcap. Здесь находится класс WakeOnLan.

Примечание. Код создания / синтаксического анализа пакета изначально был включен в SharpPcap.dll. Он был перенесен в свою собственную библиотеку, потому что SharpPcap предназначен для работы с winpcap. Многие из его пользователей занимаются разработкой протоколов и / или обработкой необработанных сетевых пакетов.

using SharpPcap;

SharpPcap содержит весь код оболочки winpcap (windows) / libpcap (* nix). Нужно выбрать интерфейс и отправить фактические пакеты по сети.

2 голосов
/ 15 января 2009

WOL выполняется MAC, а не IP. Вот пример .

0 голосов
/ 15 января 2009

.NET работает как виртуальная машина (CLR), поэтому абстрагируется от значительной части базовой машины. Например, он предоставляет только интерфейсы для сетей TCP и UDP, которые в стеке сетевых протоколов намного выше того, что вы обсуждаете. Возможно, вам удастся найти сторонний компонент, обеспечивающий доступ к низкоуровневому интерфейсу, но я бы на это не рассчитывал (в прошлом я искал .NET и Java).

Для доступа к этому минимуму в стеке сетевых протоколов вам, вероятно, потребуется кодировать на C соответствующие системные вызовы ОС. Вы можете найти это проще всего в Python, и вы можете обнаружить, что эта функциональность уже реализована в библиотеках Python или сторонних. Например, я предлагаю взглянуть на сетевые библиотеки Twisted. Это было одной из причин, по которой я переключился на Python для большей части моей работы.

С наилучшими пожеланиями.

...