8

プロミスキャス モードで raw ソケットを使用してプログラムを作成していますが、送信するパケットを盗聴しない raw ソケットが必要です。イーサネット rx ワイヤ (tx ワイヤではなく) を介してデータのみを読み取る必要があります。可能ですか?

どうもありがとう。

4

4 に答える 4

8

解決策は、それが PACKET_OUTGOING である場合、読み取りパケットを調べることです。このオプションを使用すると、イーサネット tx ワイヤに入れたパケットと rx ワイヤから読み取ったパケットを区別できます。

プロミスキャス モードでソケットを開きます。

char* i = "eth0";
int fd;
struct ifreq ifr;
struct sockaddr_ll interfaceAddr;
struct packet_mreq mreq;

if ((fd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL))) < 0)
    return -1;

memset(&interfaceAddr,0,sizeof(interfaceAddr));
memset(&ifr,0,sizeof(ifr));
memset(&mreq,0,sizeof(mreq));

memcpy(&ifr.ifr_name,i,IFNAMSIZ);
ioctl(fd,SIOCGIFINDEX,&ifr);

interfaceAddr.sll_ifindex = ifr.ifr_ifindex;
interfaceAddr.sll_family = AF_PACKET;

if (bind(fd, (struct sockaddr *)&interfaceAddr,sizeof(interfaceAddr)) < 0)
    return -2;


mreq.mr_ifindex = ifr.ifr_ifindex;
mreq.mr_type = PACKET_MR_PROMISC;
mreq.mr_alen = 6;

if (setsockopt(fd,SOL_PACKET,PACKET_ADD_MEMBERSHIP,
     (void*)&mreq,(socklen_t)sizeof(mreq)) < 0)
        return -3;
//...

そして読む。これで、Rx と Tx のイーサネット ワイヤを区別できます。

unsigned char buf[1500];
struct sockaddr_ll addr;
socklen_t addr_len = sizeof(addr);
n = recvfrom(fd, buf, 2000, 0, (struct sockaddr*)&addr, &addr_len);
if (n <= 0)
{
    //Error reading
}
else if (addr.sll_pkttype == PACKET_OUTGOING)
{
    //The read data are not writing by me.
    //Use only this data to copy in the other network.
}

そしてそれはすべてです。それを使用して、私が書いたデータを読みません。ネットワーク 1 のフレームをネットワーク 2 にコピーし、ネットワーク 2 のフレームをネットワーク 1 にコピーすると、ループを回避できます。

于 2012-08-31T06:58:27.273 に答える
3

BPF着信パケットに対応する (BSD パケット フィルター) フィルターを作成する必要があります。

/* To obtain the BPF filter corresponding to incoming traffic:
 * sudo tcpdump -dd -i eth0 dst host YOUR_IP_ADDRESS and not src host YOUR_IP_ADDRESS 
 * The filter given below is what i get on my local machine (192.168.1.7):
 * sudo tcpdump -dd -i eth0 dst host 192.168.1.7 and not src host 192.168.1.7
 */
struct sock_filter incoming_filter[] = {       
    { 0x28, 0, 0, 0x0000000c },
    { 0x15, 0, 4, 0x00000800 },
    { 0x20, 0, 0, 0x0000001e },
    { 0x15, 0, 9, 0xc0a80107 },
    { 0x20, 0, 0, 0x0000001a },
    { 0x15, 7, 6, 0xc0a80107 },
    { 0x15, 1, 0, 0x00000806 },
    { 0x15, 0, 5, 0x00008035 },
    { 0x20, 0, 0, 0x00000026 },
    { 0x15, 0, 3, 0xc0a80107 },
    { 0x20, 0, 0, 0x0000001c },
    { 0x15, 1, 0, 0xc0a80107 },
    { 0x6, 0, 0, 0x0000ffff },
    { 0x6, 0, 0, 0x00000000 },
};

int s;
struct sockaddr_ll sock_address;
struct sock_fprog prog;

/* Init the program filter */
prog.len = 14;
prog.filter = incoming_filter;

そして、あなたの RAW ソケットとバインドと ...:

/* Create the raw socket */
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s < 0) 
{
    /* Error handling */
}

/* Build our socket */
sock_address.sll_family = AF_PACKET;
sock_address.sll_protocol = htons(ETH_P_IP);
sock_address.sll_ifindex = if_nametoindex(your_interface_name);

/* Bind */
if (bind(s, (struct sockaddr*)&sock_address, sizeof(sock_address)) < 0)
{
    /* Error handling */
}

/* Apply the filter */
if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0)
{
    /* Error handling */
}

/* Infinite listen loop */
while (1)
{

    /* Handle received packet */
}

編集:Macアドレスでフィルタリングしたい場合は、簡単です。次のようにフィルタを生成します(ここではMacアドレスを使用します):

sudo tcpdump -dd -i eth0 ether dst 00:0f:b0:68:0f:92 and not ether src 00:0f:b0:68:0f:92
{ 0x20, 0, 0, 0x00000002 },
{ 0x15, 0, 7, 0xb0680f92 },
{ 0x28, 0, 0, 0x00000000 },
{ 0x15, 0, 5, 0x0000000f },
{ 0x20, 0, 0, 0x00000008 },
{ 0x15, 0, 2, 0xb0680f92 },
{ 0x28, 0, 0, 0x00000006 },
{ 0x15, 1, 0, 0x0000000f },
{ 0x6, 0, 0, 0x0000ffff },
{ 0x6, 0, 0, 0x00000000 },
于 2012-08-29T21:03:48.863 に答える
0

IPアドレスからのものを簡単にフィルタリングして、リストから除外することができます。

于 2012-08-29T12:18:44.137 に答える