Raw Socket Promiscuous Mode Not Sniffing What I Write

Raw Socket promiscuous mode not sniffing what I write

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.

Packet socket in promiscuous mode only receiving local traffic

Along with Rob Jones' suggestion, try a tool like Wireshark to make sure that you're receiving the packets that you expect at the interface. At least that will confirm (or deny) that you have a problem with your code.

Also need to make sure that the interface itself is set to promiscuous mode.
If not then you can use the ioctl() to set it:

ifr.ifr_flags |= IFF_PROMISC;
if( ioctl(sock, SIOCSIFFLAGS, &ifr) != 0 )
{
// handle error here
}

While your application is running, make sure that ifconfig reports the PROMISC flag for that interface.

Note that this will need to be executed as a privileged user.


Tried out the code as presented. Works for me. Of course (due to the test on line 102) this will only print details for TCP traffic.

Is it possible to inject on a raw socket while sniffing in promiscous mode?

The short answer is yes. Below is the longer one...

I know that for normal promiscous mode operation of a wireless card, your not suppose to be able to interact with the network

I am not sure where you have got this knowledge from but the above statement is wrong. A promiscuous mode does not restrict what you can do and how you can interact with the network. By default, network interface cards are simply trying to reduce the amount of data they pass to the host for better efficiency. For example, NICs would not pass an Ethernet frame to the host if its destination MAC address does not match the address of the receiving media access controller. The only thing that promiscuous mode does is simply tells the device to pass everything it gets to the host, be that frame addressed for the host or not. In other words, whatever you were able to do with NIC in a normal operation mode, you can still do when it is in promiscuous mode. Plus, NIC does not filter anything for you anymore, so you can receive more (as long as the host can handle the load).

but is it possible to do it with raw sockets?

Yes, it is possible. As long as you have enough privileges, you can send and receive Ethernet frames from user-space using "raw" sockets API. Whether a devices is in promiscuous mode or not does not make any difference.

Also note that these days routers are very smart and they won't forward packets to your host even if you put your host's NIC into promiscuous mode. So in the right network your are not likely to receive anything that in fact is not intended for your host, and promiscuous mode won't make any difference.

If that helps, here is a simple example of exchanging custom packets with an FPGA board connected to the PC over Ethernet. It uses raw socket API and runs in user-space on Linux.

Reading from a promiscuous network device

On Linux you use a PF_PACKET socket to read data from a raw device, such as an ethernet interface running in promiscuous mode:

s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))

This will send copies of every packet received up to your socket. It is quite likely that you don't really want every packet, though. The kernel can perform a first level of filtering using BPF, the Berkeley Packet Filter. BPF is essentially a stack-based virtual machine: it handles a small set of instructions such as:

ldh = load halfword (from packet)  
jeq = jump if equal
ret = return with exit code

BPF's exit code tells the kernel whether to copy the packet to the socket or not. It is possible to write relatively small BPF programs directly, using setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, ). (WARNING: The kernel takes a struct sock_fprog, not a struct bpf_program, do not mix those up or your program will not work on some platforms).

For anything reasonably complex, you really want to use libpcap. BPF is limited in what it can do, in particular in the number of instructions it can execute per packet. libpcap will take care of splitting a complex filter up into two pieces, with the kernel performing a first level of filtering and the more-capable user-space code dropping the packets it didn't actually want to see.

libpcap also abstracts the kernel interface out of your application code. Linux and BSD use similar APIs, but Solaris requires DLPI and Windows uses something else.

Raw socket bound to device not receiving all packets

The reason of receiving packets directed only to IP of your device is that you are using PF_INET raw socket. When PF_INET raw socket is used - skb faces different sanity checks when goes across the stack (see below).

F.e. :

int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
/*...*/

/* When the interface is in promisc. mode, drop all the crap
* that it receives, do not try to analyse it.
*/
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;

So the call trace is something like: __netif_receive_skb_core()->ip_rcv()->...->ip_local_deliver()->...->raw_local_deliver()->raw_rcv()->...->tcp_rcv() (you can check trace through the trace-cmd).

But tcpdump/Wireshark obtains packets around __netif_receive_skb_core(), i.e. before some sanity checks. Hence is discrepancy that confused you.

Therefore if you want skb's to bypass a large part of Linux kernel network stack - you should use PF_PACKET raw sockets.

Useful link

How do I create a tcp socket in promiscuous mode?

You want to use libpcap to grab raw packets. Run man 3 pcap to get a list of all the relevant functions.



Related Topics



Leave a reply



Submit