libpcap落地包dump
#include <stdio.h>
#include <pcap.h> /*Libpcap头文件*/
void packet_callback(u_char *user,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
{
static int packet_number = 1; /*静态局部变量,用来存放捕获到的数据包的个数*/
printf("The %d packet is captured len%d.\n",packet_number,packet_header->len); /*输出捕获数据包的个数*/
pcap_dump(user, packet_header, packet_content); /*调用pcap_dump函数写入文件*/
packet_number++; /*每次调用此回调函数,个数+1*/
}
void main()
{
pcap_t* pcap_handle; /*Libpcap句柄*/
pcap_dumper_t *dumpfp; /*定义dump句柄*/
char error_content[PCAP_ERRBUF_SIZE]; /*用来存储错误信息*/
char *net_interface; /*用来存储网络接口*/
struct bpf_program bpf_filter; /*BPF过滤规则*/
char bpf_filter_string[] = "tcp port 80"; /*过滤规则字符串形式*/
bpf_u_int32 net_mask; /*网络掩码*/
bpf_u_int32 net_ip; /*网络地址*/
net_interface = pcap_lookupdev(error_content); /*获取网络接口*/
pcap_lookupnet(net_interface, &net_ip,&net_mask,error_content);
/*获取网络地址和掩码*/
pcap_handle = pcap_open_live(net_interface, BUFSIZ, 1, 0, error_content);
pcap_compile(pcap_handle, &bpf_filter, bpf_filter_string, 0, net_ip);
pcap_setfilter(pcap_handle, &bpf_filter);
dumpfp = pcap_dump_open(pcap_handle, "./traffic");
pcap_loop(pcap_handle, -1, packet_callback, (u_char *)dumpfp);
pcap_close(pcap_handle); /*关闭Libpcap操作*/
pcap_dump_close(dumpfp); /*关闭写入的文件*/
}
libpcap落地包转发
/*pcap_sendpacket 转发包*/
#include <pcap.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* default snap length (maximum bytes per packet to capture) */
#define SNAP_LEN 1518
/* ethernet headers are always exactly 14 bytes [1] */
#define SIZE_ETHERNET 14
/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN 6
int main(int argc, char **argv)
{
char *dev = NULL; /* capture device name */
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
pcap_t *handle; /* packet capture handle */
pcap_t *sendhandle; /* packet capture handle */
const u_char *packet;
struct pcap_pkthdr header;
char filter_exp[] = "tcp port 80"; /* filter expression [3] */
struct bpf_program fp; /* compiled filter program (expression) */
bpf_u_int32 mask; /* subnet mask */
bpf_u_int32 net; /* ip */
int num_packets = -1; /* number of packets to capture */
dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n",
errbuf);
exit(EXIT_FAILURE);
}
sendhandle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
exit(EXIT_FAILURE);
}
handle = pcap_open_offline("traffic", errbuf);
while(1){
packet = pcap_next(handle,&header);
pcap_sendpacket(sendhandle, packet, header.len) ;
}
/* cleanup */
pcap_freecode(&fp);
pcap_close(handle);
printf("\nCapture complete.\n");
return 0;
}
libpcap中转包程序
网关设置/etc/sysconfig/network-scripts/ifcfg-eth0
/*本机需要设置为SRCIP,DESTIP机器的网关
通过SRCIP机器,连接DEST地址,DEST必须和SRCIP不是一个网段,这样通过网关转到本机
本程序捕获后,将DEST转化到DESTIP,SRCIP转化到SRC(为了回消息的时候也通过网关给本机)
这样SRCIP访问DESTIP会通过本机中转,本机可以截获所有信息
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pcap.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
void handle_packet(u_char *user, const struct pcap_pkthdr* pkthdr,const u_char* packet);
unsigned short check_sum(unsigned short *addr,int len);
void print_payload(const u_char *payload, int len);
void print_hex_ascii_line(const u_char *payload, int len, int offset);
struct psd_header{
unsigned long saddr;
unsigned long daddr;
char mbz;
char ptcl;
unsigned short tcpl;
};
unsigned short port;
#define SRCIP "192.168.100.51"//源真实IP
#define DESTIP "192.168.100.190"//目标真实IP
#define DEST "192.168.0.190" //目标虚拟地址
#define SRC "192.168.0.207" //源虚拟地址(无所谓不用改,只要不在一个网段就行)
#define PORT 8443
//程序所在本机为网关
/* default snap length (maximum bytes per packet to capture) */
#define SNAP_LEN 1518
int main(int argc, char **argv)
{
char *dev = NULL;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *handle = NULL;
struct bpf_program filter;
char filter_app[] = "tcp port 8443 and ( host 192.168.100.190 or 192.168.100.51 )";//源真实IP+目标真实IP+端口
bpf_u_int32 mask;
bpf_u_int32 net;
struct pcap_pkthdr header;
const u_char *packet;
int on = 1;
int sockfd = socket(PF_INET,SOCK_RAW,IPPROTO_TCP);
if(sockfd < 0){
fprintf(stderr,"Socket error:\n");
exit(-4);
}
if(setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on)) < 0)
fprintf(stderr,"HDRINCL error\n");
/* create a socket */
if (argc == 2) {
dev = argv[1];
}
else if (argc > 2) {
fprintf(stderr, "error: unrecognized command-line options\n\n");
exit(EXIT_FAILURE);
}
else {
/* find a capture device if not specified on command-line */
dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n",
errbuf);
exit(EXIT_FAILURE);
}
}
/* get network number and mask associated with capture device */
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
dev, errbuf);
net = 0;
mask = 0;
}
/* print capture info */
printf("Device: %s\n", dev);
printf("Filter expression: %s\n", filter_app);
if(NULL == (handle = pcap_open_live(dev,SNAP_LEN,1,0,errbuf))){
fprintf(stderr,"pcap_open_live() error:%s\n",errbuf);
exit(-2);
}
if(-1 == pcap_compile(handle,&filter,filter_app,1,net)){
fprintf(stderr,"pcap_compile() error.\n");
exit(-3);
}
pcap_setfilter(handle,&filter);
// while(1){
// packet = pcap_next(handle,&header);
// printf("captured a packet with length of [%d]\n",header.len);
// handle_packet(&header,packet,sockfd);
// }
pcap_loop(handle, -1, handle_packet, (u_char *)&sockfd);
pcap_close(handle);
return 0;
}
void handle_packet(u_char *user, const struct pcap_pkthdr* pkthdr,const u_char* packet)
{
int sockfd = *user;
u_char buffer[SNAP_LEN];
int len = pkthdr->len;
struct iphdr* ip;
struct tcphdr* tcp;
char srcbuf[16];
char dstbuf[16];
u_char temp[SNAP_LEN];
struct sockaddr_in addr;
struct psd_header psdhdr;
int ip_len;
memset(buffer,0,SNAP_LEN);
memset(temp,0,SNAP_LEN);
memcpy(buffer,packet,len);
memset(srcbuf,0,16);
memset(dstbuf,0,16);
memset(&addr,0,sizeof(struct sockaddr_in));
memset(&psdhdr,0,sizeof(struct psd_header));
ip = (struct iphdr *)(buffer + sizeof(struct ethhdr));
tcp = (struct tcphdr *)(buffer + sizeof(struct ethhdr) + sizeof(struct iphdr));
//int iphl_size = ip->ihl *4 ; //ip头长度
// int tcphl_size =tcp->doff * 4;//tcp头长度
//u_char *payload = (u_char *)(buffer + sizeof(struct ethhdr) + iphl_size + tcphl_size );
/* compute tcp payload (segment) size */
//int size_payload = ntohs(ip->tot_len) - ( iphl_size + tcphl_size) ;
/*
* Print payload data; it might be binary, so don't just
* treat it as a string.
*/
// if (size_payload > 0) {
// printf(" Payload (%d bytes):\n", size_payload);
// print_payload(payload, size_payload);
// }
ip_len = ntohs(ip->tot_len);
strcpy(srcbuf,inet_ntoa(((struct ip *)(buffer + sizeof(struct ethhdr)))->ip_src));
strcpy(dstbuf,inet_ntoa(((struct ip *)(buffer + sizeof(struct ethhdr)))->ip_dst));
printf("source ip:%s\n",srcbuf);
printf("destination ip:%s\n",dstbuf);
printf("len:%d\n",ip_len);
printf("fin:%x,syn:%x,rst:%x,psh:%x,ack:%x,urg:%x\n", tcp->fin,tcp->syn,tcp->rst,tcp->psh,tcp->ack,tcp->urg );
if(strcmp(dstbuf,DEST) == 0)
{
if(strcmp(srcbuf,SRCIP) == 0)
{
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(DESTIP);
ip->daddr = addr.sin_addr.s_addr;
ip->saddr = inet_addr(SRC);
ip->check = 0;
ip->check = check_sum((unsigned short *)ip,sizeof(struct iphdr));
tcp->dest = addr.sin_port;
port = tcp->source;
tcp->source = htons(PORT);
tcp->check = 0;
psdhdr.saddr = ip->saddr;
psdhdr.daddr = ip->daddr;
psdhdr.mbz = 0;
psdhdr.ptcl = IPPROTO_TCP;
psdhdr.tcpl = htons(ip_len - sizeof(struct iphdr));
memcpy(temp,&psdhdr,sizeof(struct psd_header));
memcpy(temp + sizeof(struct psd_header),tcp,ip_len - sizeof(struct iphdr));
tcp->check = check_sum((unsigned short *)temp,sizeof(struct psd_header) + ip_len - sizeof(struct iphdr));
sendto(sockfd,buffer + sizeof(struct ethhdr),ip_len,0,(struct sockaddr *)(&addr),sizeof(struct sockaddr));
}
}
else if(strcmp(srcbuf,DESTIP) == 0)
{
if(strcmp(dstbuf,SRC) == 0)
{
addr.sin_family = AF_INET;
addr.sin_port = port;
addr.sin_addr.s_addr = inet_addr(SRCIP);
ip->daddr = addr.sin_addr.s_addr;
ip->saddr = inet_addr(DEST);
ip->check = 0;
ip->check = check_sum((unsigned short *)ip,sizeof(struct iphdr));
tcp->dest = addr.sin_port;
tcp->source = htons(PORT);
tcp->check = 0;
psdhdr.saddr = ip->saddr;
psdhdr.daddr = ip->daddr;
psdhdr.mbz = 0;
psdhdr.ptcl = IPPROTO_TCP;
psdhdr.tcpl = htons(ip_len - sizeof(struct iphdr));
memcpy(temp,&psdhdr,sizeof(struct psd_header));
memcpy(temp + sizeof(struct psd_header),tcp,ip_len - sizeof(struct iphdr));
tcp->check = check_sum((unsigned short *)temp,sizeof(struct psd_header) + ip_len - sizeof(struct iphdr));
sendto(sockfd,buffer + sizeof(struct ethhdr),ip_len,0,(struct sockaddr *)(&addr),sizeof(struct sockaddr));
}
}
}
unsigned short check_sum(unsigned short *addr,int len){
register int nleft = len;
register int sum = 0;
register u_short *w = addr;
u_short answer = 0;
while(nleft > 1){
sum += *w++;
nleft -= 2;
}
if(nleft == 1){
*(u_char *)(&answer) = *(u_char *)w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
/*
* print packet payload data (avoid printing binary data)
*/
void print_payload(const u_char *payload, int len)
{
int len_rem = len;
int line_width = 16; /* number of bytes per line */
int line_len;
int offset = 0; /* zero-based offset counter */
const u_char *ch = payload;
if (len <= 0)
return;
/* data fits on one line */
if (len <= line_width) {
print_hex_ascii_line(ch, len, offset);
return;
}
/* data spans multiple lines */
for ( ;; ) {
/* compute current line length */
line_len = line_width % len_rem;
/* print line */
print_hex_ascii_line(ch, line_len, offset);
/* compute total remaining */
len_rem = len_rem - line_len;
/* shift pointer to remaining bytes to print */
ch = ch + line_len;
/* add offset */
offset = offset + line_width;
/* check if we have line width chars or less */
if (len_rem <= line_width) {
/* print last line and get out */
print_hex_ascii_line(ch, len_rem, offset);
break;
}
}
return;
}
/*
* print data in rows of 16 bytes: offset hex ascii
*
* 00000 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a GET / HTTP/1.1..
*/
void print_hex_ascii_line(const u_char *payload, int len, int offset)
{
int i;
int gap;
const u_char *ch;
/* offset */
printf("%05d ", offset);
/* hex */
ch = payload;
for(i = 0; i < len; i++) {
printf("%02x ", *ch);
ch++;
/* print extra space after 8th byte for visual aid */
if (i == 7)
printf(" ");
}
/* print space to handle line less than 8 bytes */
if (len < 8)
printf(" ");
/* fill hex gap with spaces if not full line */
if (len < 16) {
gap = 16 - len;
for (i = 0; i < gap; i++) {
printf(" ");
}
}
printf(" ");
/* ascii (if printable) */
ch = payload;
for(i = 0; i < len; i++) {
if (isprint(*ch))
printf("%c", *ch);
else
printf(".");
ch++;
}
printf("\n");
return;
}