Domanda

Sto cercando di inviare un pacchetto WOL su tutte le interfacce per riattivare il gateway (che è il server DHCP, quindi la macchina non avrà ancora un IP).

E sembra che posso solo collegare socket a IP e coppie di porte ...

Quindi la domanda è: come può creare un socket (o qualcos'altro) associato a una scheda NIC che non ha IP? (Qualsiasi lingua è ok. C # è preferito)

@ctacke: So che WOL viene eseguito tramite l'indirizzo MAC ... Il mio problema è che Windows invia solo trasmissioni UDP sulla NIC quella che Windows considera la NIC primaria (che non è nemmeno la NIC con la route predefinita attiva la mia macchina Vista). E non riesco a trovare un modo per associare un socket a un'interfaccia che non ha un indirizzo IP. (come fanno i client DHCP)

@Arnout: Perché no? I client conoscono l'indirizzo MAC del gateway. Voglio solo inviare un pacchetto WOL come fa inizialmente un client DHCP ... (I pacchetti di rilevamento DHCP affermano di provenire da 0.0.0.0) Non mi dispiace se devo costruire l'intero pacchetto byte per byte ...

È stato utile?

Soluzione

Sembra di aver trovato una soluzione. Si può usare winpcap per iniettare pacchetti in qualsiasi interfaccia. E c'è un buon wrapper per .net: http://www.tamirgal.com /home/dev.aspx?Item=SharpPcap

(Avrei preferito una soluzione che non richiedesse l'installazione di librerie extra ...)

AGGIORNAMENTO: Ecco cosa mi è venuto in mente per l'invio di un pacchetto WOL su tutte le interfacce:

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

Altri suggerimenti

WOL viene eseguito dal MAC, non dall'IP. Ecco un esempio .

WOL è un protocollo molto flessibile che può essere implementato in diversi modi.

I più comuni sono:

  • Invio di un WOL come payload di un pacchetto Ethernet.
  • Invio di un WOL come payload di un pacchetto UDP (per il routing attraverso la rete).

Una volta atterrato sulla rete locale, passa a tutti gli host della rete utilizzando l'indirizzo MAC di trasmissione.

Per un pacchetto Ethernet la struttura è:

  • MAC di destinazione: FF: FF: FF: FF: FF: FF (Broadcast)
  • Un payload del pacchetto magico

Per un pacchetto UDP la struttura è:

  • MAC di destinazione: FF: FF: FF: FF: FF: FF (Broadcast)
  • Porta UDP: 9
  • Un payload del pacchetto magico

Il payload magico è costituito da:

  • Stream di sincronizzazione: FFFFFFFFFFFF (ovvero 6 coppie o 6 byte di FF)
  • 16 copie del MAC del computer che stai segnalando a WOL
  • Una passphrase opzionale di 0, 4 o 6 byte.

Per ricevere pacchetti WOL da Internet (tramite un firewall / router):

  • Configura la porta del router 9 per l'inoltro a IP 255.255.255.255 (IP broadcast)
  • Imposta l'IP di destinazione: l'IP esterno del router

Nota: questo può essere ottenuto solo usando l'esempio UDP perché i pacchetti Ethernet mancano del livello IP necessario per il routing del pacchetto attraverso Internet. IE, i pacchetti Ethernet sono l'opzione solo rete locale. Il problema con l'invio di pacchetti WOL su UDP è la sicurezza perché è necessario impostare il router per abilitare la trasmissione IP (255.255.255.255). L'abilitazione della trasmissione su IP è generalmente considerata una cattiva idea a causa del rischio aggiuntivo di attacchi interni alla rete (flooding del ping, spoofing della cache, ecc ...).

Per ulteriori informazioni sul protocollo, inclusa una cattura di esempio, vedere questo sito .

Se si desidera uno strumento da riga di comando rapido e sporco che generi pacchetti WOL (e si sta eseguendo un debian, un Linux Lint o Ubuntu) è possibile installare uno strumento che già lo fa.

Installa semplicemente usando la riga di comando con:

sudo apt-get install wakeonlan

Aggiornamento:

Ecco un esempio funzionante che genera un pacchetto WakeOnLan utilizzando la versione corrente di 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: si tratta di un'applicazione console di invio di pacchetti Wake-On-Lan completamente funzionante basata sull'Esempio09 che si trova nell'origine SharpPcap.

Le librerie utilizzate in questo esempio che non possono essere trovate nel framework .NET sono:

using PacketDotNet;

Questa libreria (.dll) è fornita con SharpPcap. È responsabile di tutta la costruzione e dell'analisi dei pacchetti all'interno di SharpPcap. Qui risiede la classe WakeOnLan.

Nota: il codice di costruzione / analisi dei pacchetti era originariamente raggruppato in SharpPcap.dll. È stato migrato nella propria libreria perché SharpPcap è pensato per essere un wrapper per winpcap. Molti dei suoi utenti si occupano di progettare protocolli e / o gestire pacchetti di rete grezzi.

using SharpPcap;

SharpPcap contiene tutto il codice wrapper winpcap (windows) / libpcap (* nix). È necessario selezionare l'interfaccia e inviare i pacchetti effettivi attraverso il filo.

.NET funziona come una macchina virtuale (CLR), quindi estrae gran parte della macchina reale sottostante. Ad esempio, fornisce solo interfacce per la rete TCP e UDP, che è molto più alta nello stack del protocollo di rete rispetto a ciò di cui stai discutendo. Potresti essere in grado di trovare un componente di terze parti che fornisce l'accesso a un'interfaccia di livello inferiore, ma non ci contare su di esso (ho cercato in passato .NET e Java).

Per accedere a un livello così basso nello stack del protocollo di rete, probabilmente sarà necessario codificare in C le chiamate di sistema del sistema operativo pertinenti. Puoi trovarlo più facilmente in Python e potresti trovare questa funzionalità già implementata nelle librerie di Python o di terze parti. Ad esempio, suggerisco di dare un'occhiata alle librerie di rete Twisted. Questo è stato uno dei motivi per cui sono passato a Python per gran parte del mio lavoro.

I migliori auguri.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top