Sniffer(嗅探器)是一种基于被动侦听原理的网络分析方式。将网络接口设置在监听模式,便可以将网上传输的源源不断的信息截获。对于网络监听的基本原理我们不在赘述,我们也不开启网卡的混杂模式,因为现在的网络基本都使用了交换机,因此混杂模式也似乎变得无用武之地了。

Sniffer实现的底层支持有多种,如libpcap、套接字方式,libpcap是unix/linux平台下的网络数据包捕获函数包,对应windows下的是winpcap,大多数网络监控软件都以它为基础,比如大名鼎鼎的wireshark。libpcap目前支持源自Berkeley内核中的BPF、Solaris 2.X 和HP-UX中的DLPI、SunOS 4.1.x中的NIT、Linux的SOCK_PACKET套接字和PF_PACKET套接字。也就是说,linpcap在linux下的实现是基于以上两类套接字的,而我们主要讨论的就是直接通过套接字来获取链路层的数据。

Linux先后有两个从数据链路层获取分组的方法,较旧的方法是创建类型为SOCK_PACKET的套接字,这个方法的可用面较宽,但是缺乏灵活性,较新的方法是创建协议族为PF_PACKET的套接字,这个方法引入了更多的过滤和性能特性。举例来说,从数据链路层接受所有帧应如下创建套接字:

    fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));       /*较新的方法*/

fd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL)); /*较旧的方法*/

这里要说明的是,这两个函数的最后一个参数表明了接受链路层所有类型的以太网帧,若只想捕获IPv4帧,那就把最后一个参数改为htons(ETH_P_IP),其宏定义在linux/if_ether.h头文件中。另外,PF_PACKET协议簇支持两个不同的SOCKET类型,SOCK_DGRAM和SOCK_RAW,用SOCK_RAW创建的套接字,我们获得的是包含二层头的帧,而使用SOCK_DGRAM套接字类型,我们获取的数据不包含二层的头。

如果想设置网卡的混杂模式, 对于PF_PACKET套接字,通过设置PACKET_ADD_MEMBERSHIP套接字选项实现,在作为setsockopt第四个参数传递的packet_mreq结构中需指定网络接口和值为PACKET_MR_PROMISC。linux的数据链路层访问方法不提供内核缓冲,而且也只有较新的方法提供内核过滤(通过设置SO_ATTACH_FILTER套接字选项安装),在本程序中我们没有使用过滤功能。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<netinet/ip_icmp.h>
#include<netinet/tcp.h>
#include<netinet/udp.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<linux/if_ether.h>
#include<arpa/inet.h>
#include <unistd.h> #define BUFFSIZE 1024 int main(int argc, char *argv[]){ int rawsock;
unsigned char buff[BUFFSIZE];
int n;
int count = ;
char ch;
char proto[],
saddr[] = {},
daddr[] ={},
address[]= {};
int slen = ; rawsock = socket(PF_PACKET,SOCK_DGRAM, htons(ETH_P_IP));
if(rawsock < ){
printf("raw socket error!\n");
exit();
}
while((ch = getopt(argc, argv, "p:s:d:h")) != -){
switch (ch) {
case 'p':
slen = strlen(optarg);
if(slen > ){
fprintf(stdout, "The protocol is error!\n");
return -;
}
memcpy(proto, optarg, slen);
proto[slen] = '\0';
break;
case 's':
slen = strlen(optarg);
if(slen > || slen < ){
fprintf(stdout, "The IP address is error!\n");
return -;
}
memcpy(saddr, optarg, slen);
saddr[slen] = '\0';
break;
case 'd':
slen = strlen(optarg);
if(slen > || slen < ){
fprintf(stdout, "The IP address is error!\n");
return -;
}
memcpy(daddr, optarg, slen);
saddr[slen] = '\0';
break;
case 'h':
fprintf(stdout, "usage: snffer [-p protocol] [-s source_ip_address] [-d dest_ip_address]\n"
" -p protocol[TCP/UDP/ICMP]\n"
" -s souce ip address\n"
" -d dest ip address\n");
exit();
case '?':
fprintf(stdout, "unrecongized option: %c\n", ch);
exit(-);
}
}
while(){
n = recvfrom(rawsock,buff,BUFFSIZE,,NULL,NULL);
if(n<){
printf("receive error!\n");
exit();
} count++;
struct ip *ip = (struct ip*)(buff);
if(strlen(proto)){
if(!strcmp(proto, "TCP")){
if(ip->ip_p != IPPROTO_TCP)
continue;
else
goto addr;
}else if(!strcmp(proto, "UDP")){
if(ip->ip_p != IPPROTO_UDP)
continue;
else
goto addr;
}else if(!strcmp(proto, "ICMP")){
if(ip->ip_p != IPPROTO_ICMP)
continue;
else
goto addr;
}
} addr:
if(strlen(saddr)){
strcpy(address, inet_ntoa(ip->ip_src));
if(strcmp(address, saddr) != )
continue;
}
if(strlen(daddr)){
strcpy(address, inet_ntoa(ip->ip_dst));
if(strcmp(address, daddr) != )
continue;
} printf("%4d %15s",count,inet_ntoa(ip->ip_src));
printf("%15s %5d %5d\n",inet_ntoa(ip->ip_dst),ip->ip_p,ntohs(ip->ip_len)); int i=,j=;
for(i=;i<n;i++){
if(i!= && i%==){
printf(" ");
for(j=i-;j<i;j++){
if(buff[j]>=&&buff[j]<=)
printf("%c",buff[j]);
else printf(".");
}
printf("\n");
}
if(i% == ) printf("%04x ",i);
printf("%02x",buff[i]); if(i==n-){
for(j=;j<-i%;j++) printf(" ");
printf(" ");
for(j=i-i%;j<=i;j++){
if(buff[j]>=&&buff[j]<)
printf("%c",buff[j]);
else printf("."); } } } printf("\n\n"); }
}

Linux下一个简单sniffer的实现的更多相关文章

  1. Linux下一个简单的日志系统的设计及其C代码实现

    1.概述 在大型软件系统中,为了监测软件运行状况及排查软件故障,一般都会要求软件程序在运行的过程中产生日志文件.在日志文件中存放程序流程中的一些重要信息, 包括:变量名称及其值.消息结构定义.函数返回 ...

  2. Linux下一个简单守护进程的实现 (Daemon)

    在Linux/UNIX系统引导的时候会开启很多服务,这些服务称为守护进程(也叫Daemon进程).守护进程是脱离于控制终端并且在后台周期性地执行某种任务或等待处理某些事件的进程,脱离终端是为了避免进程 ...

  3. Linux 下一个很棒的命令行工具

    导读 Taskwarrior 是 Ubuntu/Linux 下一个简单而直接的基于命令行的 TODO 工具.这个开源软件是我曾用过的最简单的基于命令行的工具之一.Taskwarrior 可以帮助你更好 ...

  4. linux下一个oracle11G DG建立(一个):准备环境

    linux下一个oracle11G  DG建立(一个):准备环境 周围环境 名称 主库 备库 主机名 bjsrv shsrv 软件版本号 RedHat Enterprise5.5.Oracle 11g ...

  5. [转帖] Linux 创建一个简单的私有CA、发证、吊销证书

    原创帖子地址:   https://blog.csdn.net/mr_rsq/article/details/71001810 Linux 创建一个简单的私有CA.发证.吊销证书 2017年04月30 ...

  6. linux下一个有意思的问题(文件名以短划线或空格开头)

    linux下一个有意思的问题(文件名以短划线开头) 这本是无意中的一个发现. 在linux下,文件名中含有 - 是没有问题,但是如果文件名是以-作为第一个字符的,那么就比较麻烦了. 问题演示 看这里, ...

  7. Memcahce(MC)系列(两)Linux下一个Memcache安装

    Linux下一个memcache安装 memcache是高性能.分布式的内存对象缓存系统,用于在动态应用中降低数据库负载.提升訪问速度.眼下用memcache解决互联网上的大用户读取是很流行的一种使用 ...

  8. Linux 下一个 Mysql error 2002 错误解决

    Linux 下一个 Mysql error 2002 错误解决     首先查看 /etc/rc.d/init.d/mysqld status 查看mysql它已开始.     假设启动的的话,先将数 ...

  9. linux 下一个 osw先从操作系统和标准脚本主动发起

    linux 下一个 osw与操作系统的引导和启动标准的脚本.osw它指的是--os watcher,这是一个显示器os这些指标shell脚本.osw监测数据一般使用oracle技能评估os资源的使用, ...

随机推荐

  1. Mysql 函数, 存储过程, 任务调度

    官网链接:   https://dev.mysql.com/doc/refman/5.7/en/stored-programs-views.html

  2. c#之using关键字

    1.using可以引入命名空间: 2.在using语句里声明的变量,使用完后会自动调用Dispose方法(实现IDisposable接口). using 语句允许程序员指定使用资源的对象应当何时释放资 ...

  3. eclipse使用ctrl+shift+F格式化代码失效

    通常情况出现这种问题是组合快捷键和别的软件快捷键冲突了, 最常见的是和搜狗输入法冲突, 在设置中找到搜狗输入法然后把冲突的快捷键取消掉就可以了.

  4. 向数据库添加学生信息。存放在REQUEST对象里

    代码前几天已经发过了,但是程序一直还没运行出来,今天重新建立了一个数据库,才可以,下面补充上数据截图

  5. maven向本地库添加jar包

    mvn install:install-file -DgroupId=com.lowagie -DartifactId=itextasian -Dversion=1.0 -Dpackaging=jar ...

  6. Jmeter响应数据为乱码的处理

    jmeter新手,跟着教程,发现响应的数据为乱码,百度到两种方法: 方法一:在相应节点的下方,添加后置处理器-BeanShell PostProcessor 添加一句代码:prev.setDataEn ...

  7. 【校招面试 之 剑指offer】第18题 删除链表中的节点

    题目一:在O(1)时间内删除链表节点. 给定单项链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点. 思路:(1)如果要删除的节点不是链表的尾节点,则将被删除节点的内容复制到该节点,然 ...

  8. 33. Search in Rotated Sorted Array旋转数组二分法查询

    一句话思路:反正只是寻找一个最小区间,断开也能二分.根据m第一次的落点,来分情况讨论. 一刷报错: 结构上有根本性错误:应该是while里面包括if,不然会把代码重复写两遍,不好. //situati ...

  9. 二叉树中的最大路径和 · Binary Tree Maximum Path Sum

    [抄题]: 给出一棵二叉树,寻找一条路径使其路径和最大,路径可以在任一节点中开始和结束(路径和为两个节点之间所在路径上的节点权值之和) [思维问题]: 不会写分合法 [一句话思路]: 用两次分治:ro ...

  10. centos7 二进制安装包安装 mysql5.6

    centos7 二进制安装包安装 mysql5.6 一.下载mysql5.6二进制安装包 http://mirrors.sohu.com/mysql/MySQL-5.6/ 如:mysql-5.6.34 ...