3

libpcap を使用してトラフィックを盗聴しています。現在アクティブなネットワーク デバイス (IP アドレスが割り当てられているデバイスなど) で実行したいと考えています。これを行う最善の方法は何ですか?私は次のことをしなければならないと仮定しています:

pcap_findalldevs(&alldevs, errbuf)

すべてのネットワーク デバイスを取得するには、ループして現在アクティブなデバイスを確認します。


編集:次の機能

(pcap_lookupnet(dev, &net, &mask, errbuf) 

ネットワーク デバイスのネットワーク アドレスとサブネット マスクを返します。コンピューターでさまざまなイーサネット アダプターを使用していくつかのテストを実行しましたが、ネットワークに接続されていないアダプターで呼び出すと、-1 が返されます。これは、アクティブなインターフェイスを取得する防弾方法でしょうか? 見逃すエッジケースはありますか?

4

4 に答える 4

2

いくつかのユーザー定義のルールに準拠するインターフェイスを検索するために pcap が持っている API は些細なことです。実際、pcap_findalldevs() を使用して、使用に適したすべてのネットワーク デバイスをやり取りするか、pcap_lookupdev() を使用して、pcap で使用できる次のネットワーク デバイスを取得できます。スニファで使用するインターフェイスを定義することは、複数のネットワーク デバイスを備えたシステムでは (コード的に) 問題になる可能性があり、そのようなインターフェイスを選択するためのより明確なルールを定義する必要があります。このようなルールは通常、静的に定義されます (「デフォルト ルートがインストールされたアクティブなインターフェイス」など)。ただし、複数のデフォルト ルートがあり (負荷分散を考えてください)、それらすべてをスニッフィングしたり、(たとえば) ppp インターフェースのみをスニッフィングしたりする場合があります。

例えば:

「アクティブなインターフェース」によって、デフォルトルートがインストールされているインターフェースを理解している場合(ここではLinuxシステムを想定しています):

ip route show 0.0.0.0/0 | awk ' { print $5 ; } ' | xargs ./sniffer

スニファー コードからデフォルト ルートがインストールされているアクティブなインターフェイスを取得する場合は、pcap のデバイス ルックアップ API よりも netlink(7) または proc(5) (/proc/net/route) を使用しますが、複雑さは次のとおりです。高い。

結論として、インターフェイス ルックアップ ロジックは、任意のシステム上の一部のラッパー プログラムに簡単にスクリプト化でき、その結果はパラメーターとしてスニファーに渡されます。

于 2010-12-05T12:31:20.980 に答える
0

pcap_open_live (3) によると:

DESCRIPTION
pcap_open_live() is used to obtain a packet capture handle to
   look at packets on the network.   device  is  a  string  that
   specifies  the  network device to open; on Linux systems with
   2.2 or later kernels, a device argument of "any" or NULL  can
   be used to capture packets from all interfaces.

しかし、現在は推奨されていないようです。 pcap_create(3) を使用する必要があります

于 2010-12-08T10:28:32.827 に答える
0

「任意の」デバイス (すべてのインターフェイスでキャプチャする疑似デバイス) でキャプチャしないのはなぜですか?

とにかく、「アクティブな」インターフェイスを見つけるのに役立つ小さなスニペットを次に示します。

#include <stdio.h>
#include <pcap.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

static void
dump_addresses (pcap_addr_t *addresses)
{
 pcap_addr_t *addr = addresses;
 printf("(");
 while (addr) {
  struct sockaddr_in *ip = (struct sockaddr_in *)addr->addr;
  struct sockaddr_in *nm = (struct sockaddr_in *)addr->netmask;
  if (ip && nm)
   printf("%s/%s ",
     inet_ntoa(ip->sin_addr), inet_ntoa(nm->sin_addr));
  addr = addr->next;
 }
 printf(")");
}

static void
devs_dump (pcap_if_t *devs)
{
 pcap_if_t *dev = devs;
 while (dev) {
  printf("dev: %s - %s - ",
    dev->name, dev->description);
  dump_addresses(dev->addresses);
  printf("\n");
  dev = dev->next;
 }
}

int
main(int argc, char *argv[])
{
 int r;
 char errbuf[PCAP_ERRBUF_SIZE];
 pcap_if_t *devs;

 r = pcap_findalldevs (&devs, errbuf);
 if (r) {
  printf("Findalldevs: %d (%s)\n", r, errbuf);
  return -1;
 }
 devs_dump(devs);
 pcap_freealldevs (devs);

 return 0;
}
于 2010-12-05T12:53:31.883 に答える
0

私は以前に何度かこの道をたどりましたが、通常は-i、ユーザーがインターフェイスを正確に識別できるようにするために、スイッチを追加することに戻ります。

ジョブを簡素化し、エッジ条件を回避します。

于 2010-12-05T16:11:59.787 に答える