官网:http://www.tcpdump.org, 上面资料丰富。
转一简单介绍:
Who this is for: Allright peeps, this tutorial assumes at least a cursory knowledge in networks in general. For example, what a packet is, how packets are sent, physical vs datalink vs network layers etc. However, I am not assuming any previous knowledge in network programming, just a basic familiarity with c. If you already are a c/c++ master, then you might as well just man 3 pcap so you can skip my annoying writing style. You should have a working c compiler on your system and libpcap installed. We are only going to concern ourselves with Ethernet datalink layer.. so if you are using some funky network card like token ring... then you are on your own as to finding your way around the datalink headers. Finally, all source in this section was written and tested on linux, kernel 2.2.14, while it should be mostly portable (hehe) I can't guarantee that it will compile or run on other operating systems. You are going to want to run as root so be careful and be sure not to break your box in the meantime. Oh, and though I have tested and run all the code presented in this tutorial with no problems, I am NOT responsible if your shit breaks and has to be quarantined by the health department... aka play at your own risk.... (*eerie ghost sound*)
Intro: Well here it is, the beginning of my packet capture tutorial a la libpcap. Inevitably the questions will arise.. "what the hell is packet capture?!" or "Who is libpcap!?" ... so I guess I'll start off by answering these questions...
-
Packet Capture, simply means to "grab packets".
"Gee thanks Martin :-P"..you blurt.
No, really, all we are trying to do here is to get access to the underlying facility provided by the operating system so we can grab packets in their raw form. For example, assume your ethercard picks up a packet from the network. Once the packet is handed off to the OS, the OS must determine what type of packet it is, to do so it strips off the Ethernet header of the packet and looks at the next layer. Perhaps it is an ip packet... well the OS must now strip of the IP header and determine which type of IP packet it is. Finally, lets say it is determined that the packet is a UDP packet, the UDP header is stripped off and the packet payload is handed over to the application that the packet is sent for (notice this is an GROSSLY oversimplified version of what really goes on, but I trying to illustrate a point). Packet capture allows us to intercept any packet that is seen by the network device, and grab it in its entirety headers and all! Regardless of which port is being sent to, or even which HOST! for that matter!!! - libpcap "provides implementation-independent access to the underlying packet capture facility provided by the operating system" (Stevens, UNP page. 707). So pretty much, libpcap is the library we are going to use to grab packets from the network card directly. Let me quickly note that there are other ways of doing this, including BPF (Berkeley Packet Filter), DLPI (Data Link Provider Interface) and SOCKET_PACKET type sockets (Linux only).
Getting Started Well there is an awful lot to cover.. so lets just get familiar with libpcap.
Like I stated before, all the code in this section is assuming that you
are sitting on an Ethernet. If this is not the case, then the tutorial
basics are still pertinent, but the code presented later on involving
decoding the Ethernet header obviously isn't :-( *sorry*. Allright...
crack your knuckles *crunch* and lets get ready to code our FIRST LIBPCAP PROGRAM!!!!. Go ahead and copy the following program into your favorite editor (which should be vim if you have any sense :-) save, and compile with...
%>gcc ldev.c -lpcap
/* ldev.c
Martin Casado
To compile:
>gcc ldev.c -lpcap
Looks for an interface, and lists the network ip
and mask associated with that interface.
*/
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h> /* GIMME a libpcap plz! */
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char **argv)
{
char *dev; /* name of the device to use */
char *net; /* dot notation of the network address */
char *mask;/* dot notation of the network mask */
int ret; /* return code */
char errbuf[PCAP_ERRBUF_SIZE];
bpf_u_int32 netp; /* ip */
bpf_u_int32 maskp;/* subnet mask */
struct in_addr addr;
/* ask pcap to find a valid device for use to sniff on */
dev = pcap_lookupdev(errbuf);
/* error checking */
if(dev == NULL)
{
printf("%s\n",errbuf);
exit(1);
}
/* print out device name */
printf("DEV: %s\n",dev);
/* ask pcap for the network address and mask of the device */
ret = pcap_lookupnet(dev,&netp,&maskp,errbuf);
if(ret == -1)
{
printf("%s\n",errbuf);
exit(1);
}
/* get the network address in a human readable form */
addr.s_addr = netp;
net = inet_ntoa(addr);
if(net == NULL)/* thanks Scott :-P */
{
perror("inet_ntoa");
exit(1);
}
printf("NET: %s\n",net);
/* do the same as above for the device's mask */
addr.s_addr = maskp;
mask = inet_ntoa(addr);
if(mask == NULL)
{
perror("inet_ntoa");
exit(1);
}
printf("MASK: %s\n",mask);
return 0;
}
Did you run the program? If not, run it :-) Assuming it compiled, and ran correctly your output should be something like...
DEV: eth0
NET: 192.168.12.0
MASK: 255.255.255.0
Now
if your DEV is not eth0, or eth1 or eth followed by some number then we
are going to have problems because this document is geared toward
sniffing ethernet packets. Obviously the NET and MASK numbers will be
different than the ones I posted, however the actual values are not
important to this discussion.
"So what did we just do?", you ask. Well, we just asked libpcap to give us some specs on an interface to listen on.
"Whats an interface?"
Just
think of an interface as your computers hardware connection to whatever
network your computer is connected to. In Unix, eth0 denotes the first
ethernet card in your computer this is the network interface that I am
going to use to demonstrate libpcap. All you really have to be
concerned with right now is that we grabbed the device name "eth0",
since this is what we have to pass to libpcap to tell where to grab
packets from. The NET and MASK are simply the network number and mask
associated with the card which are for informative purposes only. There
are much better ways to enumerate and list the specifications of the
system interfaces than going through libpcap which I'll hopefully write
about someday :-).
Allright, by now you should know how to write, run and compile a libpcap program, grab the name of the interface card we are going to capture packets from, and have a basic understanding of what we are doing. Next, we'll grab our very first packet.. WohoO!!!