Raw Socket promiscuous mode not sniffing what I write
Asked Answered
C

4

8

I am writing a program with a Raw Socket in promiscuous mode and I need the raw socket not sniff the packet I send. I need to read only the data over the ethernet rx wire (not the tx wire). It's posible?

Thanks a lot.

Cragsman answered 29/8, 2012 at 12:15 Comment(2)
Are you both sending and sniffing on the same machine? that's a problem. You'll need 2 machines for this.Isometry
Really, I sniff in one machine and send the data packet in a UDP connection via a radio link. In other machine, I unpacket and write in the other network. I join to networks via a radio link.Kautz
C
10

The solution is to look in the read packet if it is a PACKET_OUTGOING. Using this option you can diference the packet you put in the ethernet tx wire and the packet you read from the rx wire.

Open the Socket in promiscuous mode:

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;
//...

And read. Now, We can differentiate between the Rx and Tx ethernet wire:

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.
}

And it's all. Using it I don't read the data I write. I avoid the loop when I copy the network 1 frames to network 2 and the network 2 frames to network 1.

Cragsman answered 31/8, 2012 at 6:58 Comment(0)
B
3

You need to create the BPF (BSD Packet Filter) filter that correspond to incoming packets :

/* 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;

And then your RAW socket, and bind and ... :

/* 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 */
}

EDIT : If you want to filter by Mac Address, it's simple, generate your filter like this (I use my Mac address here):

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 },
Baggywrinkle answered 29/8, 2012 at 21:3 Comment(3)
We are working in layer 2, with MAC address. We don't have IP address.Kautz
@JoséMaríaB : Well this does not change anything! just filter by your host Mac Address. See my editBaggywrinkle
Thanks a lot. I think is easier to use the PACKET_OUTGOING solution for this case ( Merci beaucoup. Je pense que c'est plus facile à utiliser la solution PACKET_OUTGOING pour ce cas :-) )Kautz
G
1

Sadly, Linux doesn't offer any options to specify not receiving outgoing packets for a raw socket.

If rebuilding the Linux kernel is allowed, I would suggest just patching the kernel with packet_socket_type.patch.

and at the user program, you specify what kind of packet you'd like to receive like this.

int mask=0;
mask = PACKET_MASK_ANY & ~(1<<PACKET_OUTGOING) & ~(1 << PACKET_LOOPBACK);
setsockopt( raw_sock, SOL_PACKET, PACKET_RECV_TYPE, &mask, sizeof(mask));

IMO, this is the solution that really solves the problem.

Gailey answered 16/7, 2016 at 11:24 Comment(0)
L
0

You can easily filter for things that came from you IP address and just exclude them from your list.

Languedoc answered 29/8, 2012 at 12:18 Comment(4)
We have two networks and a PC with two ethernet devices (eth0 and eth1). The first is connecto to the first network and the second with the second network. We like to build a software bridge at level 2; using a raw socket in promiscuous mode we read all the traffic of the network 1 and copy it in the network 2 and viceversa. All it finish in a infinite loop because the frames we copy to network 1 are copy to network 2 and are copy to network 1... We need not to sniff the frames we writes and this frames are at layer 2 (with mac) and are from any machine in a full nerwork.Kautz
Can't you simply do your filtering at the MAC level then? It's not too hard to just look at the MAC address and skip the ones you know you sent. What am I missing?Languedoc
This software is use to do a bridge between to network via a radio link. The packet I read in the network 1 are send via a radio link to other computer (packet in a UDP connection), unpacket and write in the network 2 (and viceversa). Therefore, I can't use the linux bridging capabilities :-( I believe...Kautz
Store the MACs for know what we don't must write seems a good idea! Has "pcaplib" some functionality about it? I will check it.Kautz

© 2022 - 2024 — McMap. All rights reserved.