Pregunta

Estoy tratando de enviar un paquete WOL en todas las interfaces para activar la puerta de enlace (que es el servidor DHCP, por lo que la máquina aún no tiene una IP).

Y parece que solo puedo vincular sockets a IP y pares de puertos ...

Entonces, la pregunta es: ¿cómo puede crear un socket (u otra cosa) que esté vinculado a una NIC que no tiene IP? (Cualquier idioma está bien. Se prefiere C #)

@ctacke: Sé que WOL se realiza mediante la dirección MAC ... Mi problema es que Windows solo envía transmisiones UDP en la NIC lo que Windows considera la NIC primaria (que ni siquiera es la NIC con la ruta predeterminada en mi máquina Vista) Y parece que no puedo encontrar una manera de vincular un socket a una interfaz que no tiene dirección IP. (como los clientes DHCP hacen esto)

@Arnout: ¿Por qué no? Los clientes conocen la dirección MAC de la puerta de enlace. Solo quiero enviar un paquete WOL como lo hace inicialmente un cliente DHCP ... (DHCP descubre que los paquetes dicen que provienen de 0.0.0.0) No me importa si tengo que construir el paquete completo byte a byte ...

¿Fue útil?

Solución

Parece que he encontrado una solución. Se puede usar winpcap para inyectar paquetes a cualquier interfaz. Y hay un buen contenedor para .net: http://www.tamirgal.com /home/dev.aspx?Item=SharpPcap

(Hubiera preferido una solución que no requiere la instalación de bibliotecas adicionales ...)

ACTUALIZACIÓN: Esto es lo que se me ocurrió para enviar un paquete WOL en todas las interfaces:

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

Otros consejos

WOL se realiza por MAC, no por IP. Aquí hay un ejemplo .

WOL es un protocolo muy flexible que se puede implementar de varias maneras diferentes.

Los más comunes son:

  • Enviar un WOL como la carga útil de un paquete de ethernet.
  • Enviar un WOL como la carga útil de un paquete UDP (para enrutar a través de la red).

Una vez que aterriza en la red local, pasa a todos los hosts de la red utilizando la dirección MAC de transmisión.

Para un paquete Ethernet, la estructura es:

  • MAC de destino: FF: FF: FF: FF: FF: FF (Broadcast)
  • Una carga útil de paquete mágico

Para un paquete UDP, la estructura es:

  • MAC de destino: FF: FF: FF: FF: FF: FF (Broadcast)
  • Puerto UDP: 9
  • Una carga útil de paquete mágico

La carga mágica consiste en:

  • La secuencia de sincronización: FFFFFFFFFFFF (son 6 pares o 6 bytes de FF)
  • 16 copias del MAC de la computadora que está enviando a WOL
  • Una frase de contraseña opcional de 0, 4 o 6 bytes.

Para recibir paquetes WOL de Internet (a través de un firewall / enrutador):

  • Configure el puerto 9 del enrutador para reenviarlo a IP 255.255.255.255 (Broadcast IP)
  • Establecer la IP de destino: la IP externa del enrutador

Nota: Esto solo se puede lograr usando el ejemplo UDP porque los paquetes Ethernet carecen de la capa IP necesaria para que el paquete se enrute a través de Internet. Es decir, los paquetes de Ethernet son la opción de red local solamente. El problema con el envío de paquetes WOL a través de UDP es la seguridad porque debe configurar el enrutador para habilitar la transmisión IP (255.255.255.255). Habilitar la transmisión a través de IP generalmente se considera una mala idea debido al riesgo adicional de ataque interno dentro de la red (inundación de Ping, falsificación de caché, etc.).

Para obtener más información sobre el protocolo, incluida una captura de muestra, consulte este sitio .

Si desea una herramienta de línea de comando rápida y sucia que genere paquetes WOL (y está ejecutando en Debian, Linux mint o Ubuntu), puede instalar una herramienta que ya lo haga.

Simplemente instale usando la línea de comando con:

sudo apt-get install wakeonlan

Update:

Aquí hay un ejemplo de trabajo que genera un paquete WakeOnLan usando la versión actual de 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();
        }
    }
}

Nota: Esta es una aplicación de consola de envío de paquetes Wake-On-Lan completamente funcional construida en el Example09 que se puede encontrar en la fuente SharpPcap.

Las bibliotecas utilizadas en este ejemplo que no se pueden encontrar en .NET Framework son:

using PacketDotNet;

Esta biblioteca (.dll) viene empaquetada con SharpPcap. Es responsable de toda la construcción y análisis de paquetes dentro de SharpPcap. Aquí es donde reside la clase WakeOnLan.

Nota: El código de construcción / análisis de paquetes se incluyó originalmente en SharpPcap.dll. Se migró a su propia biblioteca porque SharpPcap está destinado a ser un contenedor para winpcap. Muchos de sus usuarios se encargan de diseñar protocolos y / o manejar paquetes de red sin procesar.

using SharpPcap;

SharpPcap contiene todo el código de derivación winpcap (windows) / libpcap (* nix). Es necesario seleccionar la interfaz y enviar los paquetes reales a través del cable.

.NET funciona como una máquina virtual (CLR), por lo que abstrae gran parte de la máquina real subyacente. Por ejemplo, solo proporciona interfaces para redes TCP y UDP, que es mucho más alto en la pila de protocolos de red que lo que está discutiendo. Es posible que pueda encontrar un componente de terceros que brinde acceso a una interfaz de nivel inferior, pero no contaría con él (he buscado .NET y Java en el pasado).

Para acceder a ese nivel bajo en la pila de protocolos de red, probablemente necesitará codificar en C las llamadas relevantes del sistema operativo. Puede encontrar esto más fácil en Python, y puede encontrar esta funcionalidad ya implementada en las bibliotecas de Python o de terceros. Por ejemplo, sugiero echar un vistazo a las bibliotecas de redes Twisted. Esa fue una de las razones por las que cambié a Python por gran parte de mi trabajo.

Mis mejores deseos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top