Sniffing all network traffic in C - c

I was looking the most straightforward tutorial on making a tiny network sniffer and found this one. I followed it, but the method advised to sniff packets is:
sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;;
while(1)
{
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , &saddr_size);
}
With the rational:
A raw socket when put in recvfrom loop receives all incoming packets.
This is because it is not bound to a particular address or port.
It seemed to me that this would only monitor network traffic coming in and out of my own computer, and not the whole LAN. A test-run confirmed my intuition.
Is it correct? Can this method only sniff packets coming in and out of my laptop?
Which approach should I take to sniff all network traffic (ie: netsniff-ng, Wireshark)?
I want to avoid using libpcap in this case.

That depends on your network, especially the types and configuration of the routers and switches that connect everything. In most installations, computers are not connected directly to each other. Instead, they talk to a switch. The switch will only send you the packets which are meant for your computer - the rationale is that it doesn't make sense for the switch to elaborately push electrons towards you which you'll only throw away.
But a computer can tell a switch to go into "promiscuous mode". That will configure your port of the switch to send you a copy of every packet that the switch sees. There are two catches:
The switch still can't see packets which other switches/routers don't send to it. Promiscuous mode doesn't propagate - otherwise, you'd quickly get a copy of every packet sent over the Internet anywhere. Not even Google or the NSA could handle this kind of traffic.
If your switch isn't the plug&play kind, your system admin will have disabled this feature.
[EDIT] Wireshark uses libpcap which is a low-level library which does everything from configuring your network device to fetching and filtering the packets that it can see. So you should try to find the source code of this library to understand better how it is done.
Related:
FedEx Bandwidth: When - if ever - will the bandwidth of the Internet surpass that of FedEx?

Related

Can a RAW socket be bound to an ip:port instead of an interface?

I need to write a proxy server in C language on Linux (Ubuntu 20.04). The purpose of this proxy server is as follows. There're illogical governmental barriers in accessing the free internet. Some are:
Name resolution: I ping telegram.org and many other sites which the government doesn't want me to access. I ask 8.8.8.8 to resolve the name, but they response of behalf of the server that the IP may be resolved to 10.10.34.35!
Let's concentrate on this one, because when this is solved many other problems will be solved too. For this, I need to setup such a configuration:
A server outside of my country is required. I prepared it. It's a VPS. Let's call it RS (Remote Server).
A local proxy server is required. Let's call it PS. PS runs on the local machine (client) and knows RS's IP. I need it to gather all requests going to be sent through the only NIC available on client, process them, scramble them, and send them to RS in a way to be hidden from the government.
The server-side program should be running on RS on a specific port to get the packet, unscramble it, and send it to the internet on behalf of the client. After receiving the response from the internet, it should send it back to the client via the PS.
PS will deliver the response to the client application which originates the request. Of course this happens after it will unscramble and will find the original response from the internet.
This is the design and some parts is remained gloomy for me. Since I'm not an expert in network programming context, I'm going to ask my questions in the parts I'm getting into trouble or are not clear for me.
Now, I'm in part 2. See whether I'm right. There're two types of sockets, a RAW socket and a stream socket. A RAW socket is opened this way:
socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
And a stream socket is opened this way:
socket(AF_INET, SOCK_STREAM, 0);
For RAW sockets, we use sockaddr_ll and for stream sockets we use sockaddr_in. May I use stream sockets between client applications and PS? I think not, because I need the whole RAW packet. I should know the protocol and maybe some other info of the packet, because the whole packet should be retrieved transparently in RS. For example, I should know whether it has been a ping packet (ICMP) or a web request (TCP). For this, I need to have packet header in PS. So I can't use a stream socket, because it doesn't contain the packet header. But until now, I've used RAW sockets for interfaces and have not written a proxy server to receive RAW packets. Is it possible? In another words, I've the following questions to go to next step:
Can a RAW socket be bound to localhost:port instead of an interface so that it may receive all low-level packets containing packet headers (RAW packets)?
I may define a proxy server for browser. But can I put the whole system behind the proxy server so that packets of other apps like PING may route automatically via it?
Do I really need RAW sockets in PS? Can't I change the design to suffice the data I got from the packets payload?
Maybe I'm wrong in some of the concepts and will appreciate your guidance.
Thank you
Can a RAW socket be bound to localhost:port instead of an interface so that it may receive all low-level packets containing packet headers (RAW packets)?
No, it doesn't make sense. Raw packets don't have port numbers so how would it know which socket to go to?
It looks like you are trying to write a VPN. You can do this on Linux by creating a fake network interface called a "tun interface". You create a tun interface, and whenever Linux tries to send a packet through the interface, instead of going to a network cable, it goes to your program! Then you can do whatever you like with the packet. Of course, it works both ways - you can send packets from your program back to Linux through the tun interface, and Linux will act like they just arrived on a network cable.
Then, you can set up your routing table so that all traffic goes to the tun interface, except for traffic to the VPN server ("RS"), which goes to your real ethernet/wifi interface. Otherwise you'd have an endless loop where your VPN program PS tried to send packets to RS but they just went back to PS.

Injecting an incoming packet to a network interface

I want to be able to simulate an incoming packet on a certain physical network interface.
Specifically, given an array of bytes and an interface name, I want to be able to make that interface think a packet containing those bytes arrived from another interface (most likely on another machine).
I've implemented the code that prepares the packet, but I'm unsure what the next step is.
I should point out that I actually need to feed the interface with my bytes, and not use a workaround that might produce a similar results in other machines (I've seen answers to other questions mentioning the loopback interface and external tools). This code is supposed to simulate traffic on a machine that's expecting to receive traffic from certain sources via specific interfaces. Anything else will be ignored by the machine.
I'm going to stick my neck out and say this is not possible without kernel modifications, and possibly driver modifications. Note that:
There are plenty of ways of generating egress packets through a particular interface, including libpcap. But you want to generate ingress packets.
There are plenty of ways of generating ingress packets that are not through a physical interface - this is what tap/tun devices are for.
If you modify the kernel to allow direct injection of packets into a device's receive queue, that may have unexpected effects, and is still not going to be an accurate simulation of the packets arriving in hardware (e.g. they will not be constrained to the same MTU etc). Perhaps you can build an iptables extension that fools the kernel into thinking the packet came from a different interface; I'm not sure that will do what you need though.
If all you need is simulation (and you are happy with a complete simulation), build a tap/tun driver, and rename the tap interface to eth0 or similar.
Depending on which network layer you're trying to simulate, there may be a work-around.
I have had success getting ip packets into the ingress queue with an ethernet 'hairpin'. That is, by setting the source and destination MAC address to the local interface, sending the packet results in it first appearing as an egress packet, then being 'hairpinned' and also appearing as an ingress packet.
This at least works under linux using pcapplusplus (libpcap under the hood), with my wireless interface. Your millage may vary.
This will obviously only suit your needs if you're OK with modifying the ethernet header, ie only simulating a higher layer.
Here is a snippet of c++ where I spoof a rst tcp packet for a local socket:
//always use the actual device source MAC, even if we're spoofing the remote rst
// this produces a 'hairpin' from the egress to the ingress on the interface so the tcp stack actually processes the packet
// required because the tcp stack doesn't process egress packets (at least on a linux wireless interface)
pcpp::EthLayer eth(localMAC,localMAC);
pcpp::IPv4Layer ip(remoteIP, localIP);
pcpp::TcpLayer tcp(remotePort, localPort);
pcpp::Packet pac(60);
ip.getIPv4Header()->timeToLive = 255;
tcp.getTcpHeader()->rstFlag = 1;
tcp.getTcpHeader()->ackFlag = 1;
tcp.getTcpHeader()->ackNumber = pcpp::hostToNet32(src.Ack);
tcp.getTcpHeader()->sequenceNumber = pcpp::hostToNet32(src.Seq);
pac.addLayer(&eth);
pac.addLayer(&ip);
pac.addLayer(&tcp);
pac.computeCalculateFields();
dev->sendPacket(&pac);
EDIT: the same code works on windows on an ethernet interface. It doesn't seem to do the same 'hairpin' judging from wireshark, but the tcp stack does process the packets.
Another solution is to create a new dummy network device driver, which will have the same functionality as the loopback interface (i.e. it will be dummy). After that you can wrap up a creation of simple tcp packet and specify in the source and destination addresses the addresses of the two network devices.
It sounds a little hard but it's worth trying - you'll learn a lot for the networking and tcp/ip stack in linux.

Udp transmit packet lost on linux embedded device (GigE Vision camera) in rare cases

Hardware:
derived from Sequoia-Platform (AMCC)
Using AMCC PowerPC 440EPx and
Marvell 88E1111 Ethernet PHY, 256 M DDR2 RAM
Linux version 2.6.24.2
I transmit data via udp socket ca. 60MB per second in a linux-application (C –Language). Sometimes my PC-Test program notice a lost packet because all packets are numbered (GigE Vision Stream Channel protocol) I Know that the UDP-protocol is unreliable. But because I have clean labor conditions and it always the same last packet which is lost, I think it must be a systematic error somewhere in my code.
So I try to find out the cause of the missing packet over a week but I can’t find it.
Following issues:
using Jumbo-Frames : packet size 8K Bytes
always the same last packet which is lost
error is rare (after some hours and thousands of transferred images)
error rate is higher after a connect or reconnect the device on NIC (after Auto negotiation)
I tried :
Use another NIC
Check my code : check the return values of functions, check the error handling of functions
Log the outgoing packages on my device
View packages with wireshark tool, and check with logged
packages from device
How I can solve the problem?
I know it is difficult because there are so many possibilities of cause of failure.
Questions:
Are there any know bugs on linux 2.6.24 ethernet driver stack(
especially after Auto negotiation) which were fixed in later
versions?
Should I set special options on my transfer socket ? (sock
= socket(AF_INET, SOCK_DGRAM, 0);
Should I renew the socket after Auto negotiation ?
Should I enable any linux diagnostic messages in linux kernel to find out what is going wrong ?
Are there other recommendations ?
I have seen similar problems on an application I once developed where one side of the connection was windows, and the other side was an embedded real time OS (not linux) and the only thing in between was cat5 ethernet cable. Indeed I found that a certain flury of UDP messages would almost always cause 1 of the messages to be lost, and it was always the same message. Very strange, and after a lot of time with wireshark and other network tools I finally decided that it could only be the fact that UDP was unreliable.
My advice is to switch to TCP and build a small message framer:
http://blog.chrisd.info/tcp-message-framing/
I find using TCP to be very reliable, and it can also be very fast if the traffic is "stream like" (meaning: mostly unidirectional) additionally building a message framer on top of TCP is much easier than building TCP on top of UDP.
It might be possible that it's the camera's fault - surprisingly even on the camera side, GigE vision can be more complicated and less deterministic than competing technologies like CameraLink. In particular I've seen my own strange problems and have been told from manufacturers that many of the cameras have some known buffering issues, in particular when running at their higher resolution/framerates.
Check your camera's firmware with the vendor and see if there's an update to address this.
Alternatively perhaps you have some delay between the last packet recvmsg and the previous recvmsg such as processing the frame data before receiving the end of the gvsp frame packet?
Additional recommendation: make sure no switch or other networking equipment is in the middle between the system and the camera - use a direct Cat-6e cable.

Maximizing performance on udp

im working on a project with two clients ,one for sending, and the other one for receiving udp datagrams, between 2 machines wired directly to each other.
each datagram is 1024byte in size, and it is sent using winsock(blocking).
they are both running on a very fast machines(separate). with 16gb ram and 8 cpu's, with raid 0 drives.
im looking for tips to maximize my throughput , tips should be at winsock level, but if u have some other tips, it would be great also.
currently im getting 250-400mbit transfer speed. im looking for more.
thanks.
Since I don't know what else besides sending and receiving that your applications do it's difficult to know what else might be limiting it, but here's a few things to try. I'm assuming that you're using IPv4, and I'm not a Windows programmer.
Maximize the packet size that you are sending when you are using a reliable connection. For 100 mbs Ethernet the maximum packet is 1518, Ethernet uses 18 of that, IPv4 uses 20-64 (usually 20, thought), and UDP uses 8 bytes. That means that typically you should be able to send 1472 bytes of UDP payload per packet.
If you are using gigabit Ethernet equiptment that supports it your packet size increases to 9000 bytes (jumbo frames), so sending something closer to that size should speed things up.
If you are sending any acknowledgments from your listener to your sender then try to make sure that they are sent rarely and can acknowledge more than just one packet at a time. Try to keep the listener from having to say much, and try to keep the sender from having to wait on the listener for permission to keep sending.
On the computer that the sender application lives on consider setting up a static ARP entry for the computer that the receiver lives on. Without this every few seconds there may be a pause while a new ARP request is made to make sure that the ARP cache is up to date. Some ARP implementations may do this request well before the ARP entry expires, which would decrease the impact, but some do not.
Turn off as many users of the network as possible. If you are using an Ethernet switch then you should concentrate on the things that will introduce traffic to/from the computers/network devices on which your applications are running reside/use (this includes broadcast messages, like many ARP requests). If it's a hub then you may want to quiet down the entire network. Windows tends to send out a constant stream of junk to networks which in many cases isn't useful.
There may be limits set on how much of the network bandwidth that one application or user can have. Or there may be limits on how much network bandwidth the OS will let it self use. These can probably be changed in the registry if they exist.
It is not uncommon for network interface chips to not actually support the maximum bandwidth of the network all the time. There are chips which may miss packets because they are busy handling a previous packet as well as some which just can't send packets as close together as Ethernet specifications would allow. Additionally the rest of the system might not be able to keep up even if it is.
Some things to look at:
Connected UDP sockets (some info) shortcut several operations in the kernel, so are faster (see Stevens UnP book for details).
Socket send and receive buffers - play with SO_SNDBUF and SO_RCVBUF socket options to balance out spikes and packet drop
See if you can bump up link MTU and use jumbo frames.
use 1Gbps network and upgrade your network hardware...
Test the packet limit of your hardware with an already proven piece of code such as iperf:
http://www.noc.ucf.edu/Tools/Iperf/
I'm linking a Windows build, it might be a good idea to boot off a Linux LiveCD and try a Linux build for comparison of IP stacks.
More likely your NIC isn't performing well, try an Intel Gigabit Server Adapter:
http://www.intel.com/network/connectivity/products/server_adapters.htm
For TCP connections it has been shown that using multiple parallel connections will better utilize the data connection. I'm not sure if that applies to UDP, but it might help with some of the latency issues of packet processing.
So you might want to try multiple threads of blocking calls.
As well as Nikolai's suggestion of send and recv buffers, if you can, switch to overlapped I/O and have many recvs pending, this also helps to minimise the number of datagrams that are dropped by the stack due to lack of buffer space.
If you're looking for reliable data transfer, consider UDT.

Can I make a "TCP packet modifier" using tun/tap and raw sockets?

I have a Linux application that talks TCP, and to help with analysis and statistics, I'd like to modify the data in some of the TCP packets that it sends out. I'd prefer to do this without hacking the Linux TCP stack.
The idea I have so far is to make a bridge which acts as a "TCP packet modifier". My idea is to connect to the application via a tun/tap device on one side of the bridge, and to the network card via raw sockets on the other side of the bridge.
My concern is that when you open a raw socket it still sends packets up to Linux's TCP stack, and so I couldn't modify them and send them on even if I wanted to. Is this correct?
A pseudo-C-code sketch of the bridge looks like:
tap_fd = open_tap_device("/dev/net/tun");
raw_fd = open_raw_socket();
for (;;) {
select(fds = [tap_fd, raw_fd]);
if (FD_ISSET(tap_fd, &fds)) {
read_packet(tap_fd);
modify_packet_if_needed();
write_packet(raw_fd);
}
if (FD_ISSET(raw_fd, &fds)) {
read_packet(raw_fd);
modify_packet_if_needed();
write_packet(tap_fd);
}
}
Does this look possible, or are there other better ways of achieving the same thing? (TCP packet bridging and modification.)
There were some apps I used years ago to do some TCP/IP packet manipulation for testing a firewall: fragoute and fragtest. Looks like they haven't been touched in years, but they might give you some ideas of what to do in your code.
You might want to consider using a LD_PRELOAD library to hook the functions that it uses to send the data out (send(), write() etc).
That wouldn't involve any kernel messing-around at all.
Another option is to NAT the outbound connections to a local proxy which can read the data, make whatever modifications, and send it all out to the real destination (with some options to prevent it being NAT'd again and going round in circles)
You can use the click modular router. It is a software router implemented entirely in C++. Click allows you to capture packets as they pass through elements in the router where you can modify or collect statistics as needed. As a kernel module, you completely override the linux routing mechanism and as a userland binary you simply get a duplicate (as you mention in your post) of each packet from the interface. Packets can be directed through the Click graph by way of pcap filters and a variety of other mechanisms.
If you are headed down the bridge route, I think this provides the most direct support for what you are looking to do as you can use tun/tap, to/from host or to/from device capture methods as you require.

Resources