ワイヤレス トラフィックのリアルタイム分析ツールを作成したいと考えています。
Cで無差別(またはスニッフィング)デバイスから読み取る方法を知っている人はいますか?
それを行うにはルートアクセスが必要であることを知っています。これを行うために必要な機能を誰かが知っているかどうか疑問に思っていました。通常のソケットはここでは意味がないようです。
ワイヤレス トラフィックのリアルタイム分析ツールを作成したいと考えています。
Cで無差別(またはスニッフィング)デバイスから読み取る方法を知っている人はいますか?
それを行うにはルートアクセスが必要であることを知っています。これを行うために必要な機能を誰かが知っているかどうか疑問に思っていました。通常のソケットはここでは意味がないようです。
Linuxでは、PF_PACKETソケットを使用して、プロミスキャスモードで実行されているイーサネットインターフェイスなどのrawデバイスからデータを読み取ります。
s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
これにより、受信したすべてのパケットのコピーがソケットに送信されます。ただし、実際にはすべてのパケットが必要なわけではない可能性があります。カーネルは、BPFであるBerkeleyPacketFilterを使用して第1レベルのフィルタリングを実行できます。BPFは基本的にスタックベースの仮想マシンであり、次のような小さな命令セットを処理します。
ldh = load halfword (from packet)
jeq = jump if equal
ret = return with exit code
BPFの終了コードは、パケットをソケットにコピーするかどうかをカーネルに指示します。setsockopt(s、SOL_SOCKET、SO_ATTACH_FILTER、)を使用して、比較的小さなBPFプログラムを直接作成することができます。(警告:カーネルはstructbpf_programではなくstructsock_fprogを取ります。これらを混同しないでください。そうしないと、プログラムが一部のプラットフォームで動作しなくなります)。
かなり複雑なものについては、本当にlibpcapを使用したいと思います。BPFは、実行できること、特にパケットごとに実行できる命令の数に制限があります。libpcapは、複雑なフィルターを2つに分割し、カーネルが第1レベルのフィルター処理を実行し、より機能的なユーザースペースコードが実際には見たくないパケットをドロップします。
libpcapは、アプリケーションコードからカーネルインターフェイスも抽象化します。LinuxとBSDは同様のAPIを使用しますが、SolarisにはDLPIが必要であり、Windowsは別のものを使用します。
私はかつて、生のイーサネット フレームをリッスンする必要があり、最終的にこのためのラッパーを作成しました。デバイス名を指定して関数を呼び出すと、eth0
たとえば、プロミスキャス モードのソケットが返されました。あなたがする必要があるのは、生のソケットを作成し、それを無差別モードにすることです。これが私がやった方法です。
int raw_init (const char *device)
{
struct ifreq ifr;
int raw_socket;
memset (&ifr, 0, sizeof (struct ifreq));
/* Open A Raw Socket */
if ((raw_socket = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 1)
{
printf ("ERROR: Could not open socket, Got #?\n");
exit (1);
}
/* Set the device to use */
strcpy (ifr.ifr_name, device);
/* Get the current flags that the device might have */
if (ioctl (raw_socket, SIOCGIFFLAGS, &ifr) == -1)
{
perror ("Error: Could not retrive the flags from the device.\n");
exit (1);
}
/* Set the old flags plus the IFF_PROMISC flag */
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl (raw_socket, SIOCSIFFLAGS, &ifr) == -1)
{
perror ("Error: Could not set flag IFF_PROMISC");
exit (1);
}
printf ("Entering promiscuous mode\n");
/* Configure the device */
if (ioctl (raw_socket, SIOCGIFINDEX, &ifr) < 0)
{
perror ("Error: Error getting the device index.\n");
exit (1);
}
return raw_socket;
}
次に、ソケットを取得したら、 select を使用して、到着したパケットを処理できます。
tcpdump と Wireshark でも使用されている pcap ライブラリ ( http://www.tcpdump.org/pcap.htmを参照) を使用できます。
WireSharkのようなものを使用しないのはなぜですか?
これはオープン ソースであるため、単に使用したくない場合でも、少なくともいくつかのことを学ぶことができます。