IP アドレスのない NIC 経由で WOL パッケージ (またはその他) を送信するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/445411

質問

ゲートウェイ(DHCPサーバーであるため、マシンにはまだIPがありません)を起動するために、すべてのインターフェイスにWOLパッケージを送信しようとしています。

そして、ソケットをIPとポートのペアにのみバインドできるようです...

そこで質問は次のとおりです。IP のない NIC にバインドされたソケット (またはその他のもの) を作成するにはどうすればよいでしょうか?(どの言語でも大丈夫です。C# が推奨されます)

@cacke:WOLがMACアドレスで行われることは知っています...私の問題は、WindowsがプライマリNIC(私のVistaマシンではデフォルトルートを持つNICでさえない)と見なすNIC上でのみUDPブロードキャストを送信することです。そして、IPアドレスのないインターフェイスにソケットをバインドする方法が見つからないようです。(DHCP クライアントがこれを行うのと同様)

@アーナウト:なぜだめですか?クライアントはゲートウェイの MAC アドレスを知っています。DHCP クライアントが最初に行うように WOL パケットを送信したいだけです...(DHCP 検出パケットは 0.0.0.0 から来ると主張しています) パケット全体をバイトごとに構築する必要があるかどうかは気にしません...

役に立ちましたか?

解決

解決策を見つけたようです。 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();
    }
}

他のヒント

WOLはIPではなくMACによって実行されます。 例を示します

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 に送信しているコンピューターの MAC のコピー 16 個
  • 0、4、または 6 バイトのオプションのパスフレーズ。

インターネットから (ファイアウォール/ルーター経由で) WOL パケットを受信するには:

  • ルーターのポート 9 を IP 255.255.255.255 (ブロードキャスト IP) に転送するように設定します。
  • 宛先 IP を設定します。ルーターの外部IP

注記:これは、UDP の例を使用した場合にのみ実現できます。これは、イーサネット パケットには、インターネット経由でパケットをルーティングするために必要な IP 層が欠けているためです。つまり、イーサネット パケットはローカル ネットワーク専用のオプションです。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();
        }
    }
}

注記:これは、SharpPcap ソースにある Example09 に基づいて構築された、完全に機能する Wake-On-Lan パケット送信コンソール アプリケーションです。

この例で使用されている、.NET Framework では見つからないライブラリは次のとおりです。

using PacketDotNet;

このライブラリ (.dll) は、SharpPcap にパッケージ化されています。これは、SharpPcap 内のすべてのパケット構築と解析を担当します。ここに WakeOnLan クラスが存在します。

注記:パケット構築/解析コードは元々、SharpPcap.dll 内にバンドルされていました。SharpPcap は winpcap のラッパーとして意図されているため、独自のライブラリに移行されました。ユーザーの多くは、プロトコルの設計や生のネットワーク パケットの処理を担当しています。

using SharpPcap;

SharpPcap には、winpcap(windows)/libpcap(*nix) ラッパー コードがすべて含まれています。インターフェイスを選択し、実際のパケットをネットワーク経由で送信するために必要です。

.NETは仮想マシン(CLR)として動作するため、基になる実マシンの多くを抽象化します。たとえば、TCPおよびUDPネットワーキング用のインターフェイスのみを提供します。これは、議論しているものよりもネットワークプロトコルスタックではるかに高いものです。下位レベルのインターフェイスへのアクセスを提供するサードパーティのコンポーネントを見つけることができるかもしれませんが、私はそれを期待しません(過去に.NETとJavaを探していました)。

ネットワークプロトコルスタックの下位にアクセスするには、おそらく関連するOSシステムコールに合わせてCでコーディングする必要があります。これはPythonで最も簡単に見つけることができ、この機能は既にPythonまたはサードパーティのライブラリに実装されています。たとえば、Twistedネットワークライブラリをご覧になることをお勧めします。それが、私の仕事の多くでPythonに切り替えた理由の1つでした。

ご多幸を祈ります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top