标题：网络监听技术
简介
网络监听在网络中的任何一个位置模式下都可实施行。而黑客一般都是利用网络监听来截取用户口令。比如当有人占领了一台主机之后，那么他要再想进将战果扩大到这个主机所在的整个局域网话，监听往往是他们选择的捷径。很多时候我在各类安全论坛上看到一些初学的爱好者，在他们认为如果占领了某主机之后那么想进入它的内部网应该是很简单的。其实非也，进入了某主机再想转入它的内部网络里的其它机器也都不是一件容易的事情。因为你除了要拿到他们的口令之外还有就是他们共享的绝对路径，当然了，这个路径的尽头必须是有写的权限了。在这个时候，运行已经被控制的主机上的监听程序就会有大收效。不过却是一件费神的事情，而且还需要当事者有足够的耐心和应变能力。主要包括： 
数据帧的截获 
对数据帧的分析归类 
dos攻击的检测和预防 
IP冒用的检测和攻击 
在网络检测上的应用 
对垃圾邮件的初步过滤
研究的意义
1）我国的网络正在快速发展中，相应的问题也就显现出来，网络管理及相应应用自然将越发重要，而监听技术正是网络管理和应用的基础，其意义当然重要，放眼当前相关工具linux 有snort tcpdump ,snift 等，window 有nexray, sniffer等无一不是国外软件，随着中国网络的发展，监听系统必将大有用武之地，因此监听技术的研究已是时事的要求。 
2）为什么选择linux作为环境？中国入世，各种针对盗版的打击力度和对于正版软件的保护力度都将大大加强，windows的盗版软件随处可见的现象将会一去不返，面对这样的情况，大部分的公司只有两种选择：要么花大价钱向微软购买正版软件，要么是用自由操作系统linux，特别是重要部门，如国家机关，政府部门，难道要把自己的办公系统操纵在国外大公司手里？北京的政府办公系统已经转用红旗linux，而且linux的界面也在不但的改进，更加友好易操作，我们有理由相信.linux将在我国大有作为，这也是研究Linux下网络监听的原因。
Linux下要点
1）如何尽可能完整的截取网络上的数据帧，因为以太网上每时每刻都可能有信息传递，而且根据以太网的规模不同网络上的信息量也变化不大，所以截取数据帧不仅要保证数据帧的完整，而且还要考虑到如何才能减少漏截取数据帧。 
2）就是对截取的数据帧的过滤分析，所谓监听当然要“听”得懂才行，所以把截取的数据帧翻译成我们能用的数据，监听才算成功。
网络监听的原理
Ethernet协议的工作方式是将要发送的数据包发往连接在一起的所有主机。在包头中包括有应该接收数据包的主机的正确地址，因为只有与数据包中目标地址一致的那台主机才能接收到信息包，但是当主机工作在监听模式下的话不管数据包中的目标物理地址是什么，主机都将可以接收到。许多局域网内有十几台甚至上百台主机是通过一个电缆、一个集线器连接在一起的，在协议的高层或者用户来看，当同一网络中的两台主机通信的时候，源主机将写有目的的主机地址的数据包直接发向目的主机，或者当网络中的一台主机同外界的主机通信时，源主机将写有目的的主机IP地址的数据包发向网关。但这种数据包并不能在协议栈的高层直接发送出去，要发送的数据包必须从TCP/IP协议的IP层交给网络接口，也就是所说的数据链路层。网络接口不会识别IP地址的。在网络接口由IP层来的带有IP地址的数据包又增加了一部分以太祯的祯头的信息。在祯头中，有两个域分别为只有网络接口才能识别的源主机和目的主机的物理地址这是一个48位的地址，这个48位的地址是与IP地址相对应的，换句话说就是一个IP地址也会对应一个物理地址。对于作为网关的主机，由于它连接了多个网络，它也就同时具备有很多个IP地址，在每个网络中它都有一个。而发向网络外的祯中继携带的就是网关的物理地址。
Ethernet中填写了物理地址的祯从网络接口中，也就是从网卡中发送出去传送到物理的线路上。如果局域网是由一条粗网或细网连接成的，那么数字信号在电缆上传输信号就能够到达线路上的每一台主机。再当使用集线器的时候，发送出去的信号到达集线器，由集线器再发向连接在集线器上的每一条线路。这样在物理线路上传输的数字信号也就能到达连接在集线器上的每个主机了。当数字信号到达一台主机的网络接口时，正常状态下网络接口对读入数据祯进行检查，如果数据祯中携带的物理地址是自己的或者物理地址是广播地址，那么就会将数据祯交给IP层软件。对于每个到达网络接口的数据祯都要进行这个过程的。但是当主机工作在监听模式下的话，所有的数据祯都将被交给上层协议软件处理。 
当连接在同一条电缆或集线器上的主机被逻辑地分为几个子网的时候，那么要是有一台主机处于监听模式，它还将可以接收到发向与自己不在同一个子网（使用了不同的掩码、IP地址和网关）的主机的数据包，在同一个物理信道上传输的所有信息都可以被接收到。 
在UNIX系统上，当拥有超级权限的用户要想使自己所控制的主机进入监听模式，只需要向Interface（网络接口）发送I/O控制命令，就可以使主机设置成监听模式了。而在Windows9x的系统中则不论用户是否有权限都将可以通过直接运行监听工具就可以实现了。 
在网络监听时，常常要保存大量的信息（也包含很多的垃圾信息），并将对收集的信息进行大量的整理，这样就会使正在监听的机器对其它用户的请求响应变的很慢。同时监听程序在运行的时候需要消耗大量的处理器时间，如果在这个时候就详细的分析包中的内容，许多包就会来不及接收而被漏走。所以监听程序很多时候就会将监听得到的包存放在文件中等待以后分析。分析监听到的数据包是很头疼的事情。因为网络中的数据包都非常之复杂。两台主机之间连续发送和接收数据包，在监听到的结果中必然会加一些别的主机交互的数据包。监听程序将同一TCP会话的包整理到一起就相当不容易了，如果你还期望将用户详细信息整理出来就需要根据协议对包进行大量的分析。Internet上那么多的协议，运行进起的话这个监听程序将会十分的大哦。 
当前网络中所使用的协议都是较早前设计的，许多协议的实现都是基于一种非常友好的，通信的双方充分信任的基础。在通常的网络环境之下，用户的信息包括口令都是以明文的方式在网上传输的，因此进行网络监听从而获得用户信息并不是一件难点事情，只要掌握有初步的TCP/IP协议知识就可以轻松的监听到你想要的信息的。前些时间美籍华人China-babble曾提出将望路监听从局域网延伸到广域网中，但这个想法很快就被否定了。如果真是这样的话我想网络必将天下大乱了。而事实上在广域网里也可以监听和截获到一些用户信息。只是还不够明显而已。在整个Internet中就更显得微不足道了。监听的协议分析 
我们的研究从监听程序的编写开始，用Linux C语言设计实现。
以太网数据帧剖析
以太网上的数据帧主要涉及Tcp/ip协议，针对以下几个协议的分析：IP,ARP,RARP,IPX,其中重点在于ip和 arp协议，这两个协议是多数网络协议的基础，因此把他们研究彻底，就对大多数的协议的原理和特性比较清楚了。 由于各种协议的数据帧个不相同，所以涉及很多的数据帧头格式分析，接下来将一一描述。 
在linux 下监听网络，应先设置网卡状态，使其处于杂混模式以便监听网络上的所有数据帧。然后选择用Linux socket 来截取数据帧，通过设置socket() 函数参数值，可以使socket截取未处理的网络数据帧，关键是函数的参数设置，下面就是有关的程序部分： 
AF_INET=2 表示 internet ip protocol 
SOCK_PACKET=10 表示 截取数据帧的层次在物理层，既不作处理。 
Htons(0x0003)表示 截取的数据帧的类型为不确定，既接受所有的包。 
总的设定就是网卡上截取所有的数据帧。这样就可以截取底层数据帧，因为返回的将是一个指向数据的指针，为了分析方便，我设置了一个基本的数据帧头结构。 
Struct etherpacket
{struct ethhdr eth;
struct iphdr ip;
struct tcphdr tcp;
char buff[8192];
} ep;
将返回的指针赋值给指向数据帧头结构的指针，然后对其进行分析。以下是有关协议的报头：ethhdr 这是以太网数据帧的mac报头： 
|48bit 目的物理地址| 48bit 源物理地址 | 16bit协议地址| 
相应的数据结构如下
struct ethhdr
unsigned char h_dest[ETH_ALEN];
unsigned char h_source[ETH_ALEN];
unsigned short h_proto;
其中h_dest[6]是48位的目标地址的网卡物理地址，h_source [6] 是48位的源地址的物理网卡地址。H_proto是16位的以太网协议，其中主要有0x0800 ip，0x8035.X25,0x8137 ipx,0x8863-0x8864 pppoe(这是Linux的 ppp),0x0600 ether _loop_back ,0x0200-0x0201 pup等。Iphdr 这是ip协议的报头: 
由此可以定义其结构如下：
这是Linux 的ip协议报头，针对版本的不同它可以有不同的定义，我们国内一般用BIG的定义，其中version 是ip的版本，protocol是ip的协议分类主要有0x06 tcp.0x11 udp,0x01 icmp,0x02 igmp等，saddr是32位的源ip地址，daddr是32位的目标ip地址。相应的数据结构：
struct arphdr {unsigned short int ar_hrd;
unsigned short int ar_pro;
unsigned char ar_hln;unsigned char ar_pln;
unsigned short int ar_op;#if 0unsigned char _ar_sha[ETH_ALEN];unsigned char _ar_sip[4];unsigned char _ar_tha[ETH_ALEN];unsigned char _ar_tip[4];#end if};
这是linux 的arp 协议报头，其中ar_hrd 是硬件地址的格式，ar_pro协议地址的格式，ar_hln是硬件地址的长度，ar_pln时协议地址的长度，ar_op是arp协议的分类0x001是arp echo 0x0002 是 arp reply.接下来的分别是源地址的物理地址，源ip地址，目标地址的物理地址，目标ip地址。 
Tcphdr ip协议的tcp协议报头 
以下是相应数据结构：
struct tcphdr
{u_int16_t source;
u_int16_t dest;
u_int32_t seq;
u_int32_t ack_seq;
# if _BYTE_ORDER == _LITTLE _ENDIANu_int16_t resl:4;
u_int16_t doff:4;u_int16_t fin:1;u_int16_t syn:1;
u_int16_t rst:1;u_int16_t psh:1;u_int16_t ack:1;
u_int16_t urg:1;u_int16_t res2:2;
#elif _BYTE _ORDER == _BIG _ENDIANu_int16_t doff:4;
u_int16_t res1:4;u_int16_t res2:2;u_int16_t urg:1;
u_int16_t ack:1;u_int16_t psh:1;u_int16_t rst:1;
u_int16_t syn:1;u_int16_t fin:1;
#else#error "Adjust your defines"#endifu_int16_t window;
u_int16_t check;u_int16_t urg_ptr;};
这是Linux 下tcp协议的一部分与ip协议相同取BIG，其中source是源端口，dest 是目的端口，seq是s序，ack_seq　是a序号，其余的是tcp的连接标志其中包括6个标志：syn表示连接请求，urg 表示紧急信息，fin表示连接结束，ack表示连接应答，psh表示推栈标志，rst表示中断连接。window是表示接受数据窗口大小，check是校验码，urg ptr是紧急指针。
Udphdr 这是udp协议报头 
struct udphdr {u_int16_t source;
u_int16_t dest;u_int16_t len;u_int16_t check;}
这是Linux下ip协议中udp协议的一部分，结构很明显 source源端口，dest目的端口，len udp 长度，check 是校验码。 
Icmphdr 这是ip协议的icmp协议的报头 
struct icmphdr{u_int8_t type;u_int8_t code;u_int16_t checksum;union{struct {u_int16_t id;u_int16_t 　sequence;} echo;u_int32_t gateway;struct{u_int16_t_unused;u_int16_tmtu;} frag;} un;};
这是linux下的ip协议中的icmp的协议，这里面主要的是前两项参数，其中type是icmp协议的类型，而code 则是对type类型的再分析。如：type 0x03 是表示unsearchable,这时code的不同表示了不同的unsearchable :0x00表示网络不可寻，0x01表示主机不可寻，0x02表示协议不可寻，0x03表示端口不可寻，0x05表示源路由失败，0x06网络不可知，0x07主机不可知。
Igmphdr 这是ip协议的igmp协议报头
struct igmphdr{ _u8 type;_u8 code;_u16 csum;_u32 group;};
这是Linux下的ip协议中的igmp协议，协议中主要是前面两个属性，Type表示igmp 协议的信息类型，code表示routing code. 然后,将截取的数据帧的地址赋值给定义的结构.由此可根据不同的结构分析数据,得到我们需要的信息。