网络通信编程 原始套接字程序设计_第1页
网络通信编程 原始套接字程序设计_第2页
网络通信编程 原始套接字程序设计_第3页
网络通信编程 原始套接字程序设计_第4页
网络通信编程 原始套接字程序设计_第5页
已阅读5页,还剩90页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、.,1,第四章,原始套接字,.,2,内容提要,1.使用原始套接字 2.套接字选项 3.icmp编程 4.使用ip头包含选项 5.网络嗅探器实例,.,3,1.使用原始套接字,利用原始套接字(raw socket),可访问底层传输协议。,原始套接字(raw socket)与标准套接字区别,.,4,使用原始套接字可以做什么? 实现一些实用工具(ping,traceroute)。 可对ip头,tcp头,udp头,icmp头等进行操作。 原始套接字使用sock_raw套接字类型来创建的,目前只有winsock2提供了对它的支持。 无论microsoft windows ce 还是老版本的windows

2、95 (无winsock 2升级)均不能利用原始套接字。,.,5,创建原始套接字,原始套接字类型 在ip头中使用预定义的协议(如icmp) 在ip头中使用自定义的协议(使用ip头包含选项),.,6,创建原始套接字 使用socket()或wsasocket()创建原始套接字。 例:创建原始套接字 使用预定义协议: socket s; s=socket(af_inet,sock_ram,ipproto_icmp); /or s=wsasocket(af_inef,sock_ram,ipproto_icmp,null,0,wsa_flag_overlapped);,.,7,使用自定义协议 使用igm

3、p、udp、ip或者原始ip,只需分别设置ipproto_igmp、ipproto_udp、ipproto_ip或ipproto_raw即可。 注意:在windows nt 4、windows 98以及windows 95(安装winsock 2)操作系统中,创建原始套接字时,只能使用icmp。 协议标志ipproto_udp、ipproto_ip以及ipproto_raw均要求使用套接字选项ip_hdrincl,而该选项在上述平台下都是不支持的。 windows 2000提供了对ip_hdrincl选项的支持,所以能够处理ip头(ipproto_raw)、tcp头(ipproto_tcp)以

4、及udp头(ipproto_udp)。 无论是否设置ip_hdrincl选项,原始套接字上接收到的数据都会包含ip头。,.,8,使用原始套接字可以对底层传输机制加以控制,所以有些人将其用于不法用途,,.,9,套接字选项操作函数 getsocketopt()获取套接字选项信息。 int getsocketopt( socket s, /套接字描述符 int level, /选项级别 int optname, /选项名称 char *optval, /选项值 int *optlen/选项长度 ); setsocketopt( ) 设置套接字选项。 int setsocketopt(socket s

5、, int level, int optname, const char *optval, int optlen);,2.套接字选项,.,10,选项级别: 协议的层次对应选项级别 应用层:sol_socket 传输层:ipproto_tcp、ipproto_udp 网络层:ipproto_ip 不同级别属性不同,同一级别的不同协议的属性不同,因此必须指定level参数 例:int ntime=2*1000 setsockopt(s,sol_socket,so_rcvtimeo,(char*) ipproto_icmp指定使用icmp,.,ping 程序执行步骤,1、创建协议类型为ipproto

6、_icmp的原始套接字,设置套接字的属性。 2、创建并初始化icmp封包。 3、调用sendto函数向远程主机发送icmp请求。 4、调用recvfrom函数接收icmp响应。,.,/ ping.h / 声明ip头数据结构 typedef struct _ipheader / 20字节的ip头 uchar iphverlen; / 版本号和头长度(各占4位) uchar iptos; / 服务类型 ushort iplength; / 封包总长度,即整个ip报的长度 ushort ipid; / 封包标识,惟一标识发送的每一个数据报 ushort ipflags; / 标志和片偏移 uchar

7、 ipttl; / 生存时间,就是ttl uchar ipprotocol; / 协议,可能是tcp、udp、icmp等 ushort ipchecksum; / 校验和 ulong ipsource; / 源ip地址 ulong ipdestination; / 目标ip地址 ipheader, *pipheader;,ping 程序代码,.,/icmp头数据结构 typedef struct icmp_hdr unsigned char icmp_type;/ 消息类型 unsigned char icmp_code;/ 代码 unsigned short icmp_checksum;/

8、校验和 unsigned short icmp_id; / 用来惟一标识此请求的id号,通常设置为进程id unsigned short icmp_sequence;/ 序号 unsigned long icmp_timestamp; / 数据传输时间 icmp_hdr, *picmp_hdr; /icmp回送请求的数据结构 typedef struct _echorequest icmp_hdr icmphdr; char cdata32; echorequest,*pechorequest;,.,/icmp回送应答的数据结构 #define req_datasize 32 typedef

9、struct _echoreply ipheader iphdr; echorequest echorequest; echoreplay,*pechoreplay; / 校验和的计算 / 以16位的字为单位将缓冲区的内容相加,如果缓冲区长度为奇数, / 则再加上一个字节。它们的和存入一个32位的双字中 ushort checksum(ushort* buff, int size);,/ ping.cpp #include #include #pragma comment(lib, ws2_32)/ 链接到ws2_32.lib #include #include ping.h,.,ushort

10、 checksum(ushort* buff, int size) u_long cksum = 0; while(size1) / 将数据以字为单位累加到cksum 中 cksum=cksum+ *buff; buff= buff +1; size= size- sizeof(ushort); /等价于size=size-2; if(size=1) / 共有奇数个字节将最后一个字节扩展为字,再累加 ushort u=0; u=(ushort)(*(uchar*)buff); cksum = cksum +u; / 校验位计算 /高16位和低16位相加 cksum = (cksum 16) +

11、 (cksum , 位右移运算符 右边的值依次被移出了,左边的位置依次放0,校验位计算 (1) 将32位的chsum高16位和低16位相加 (2) 自加当前数的高16位 (3) 取反并转换为16位,.,int main() wsadata wsadata; word version = makeword(2, 2); int ret = wsastartup(version, ,.,/ 创建icmp封包(回送请求) echorequest echoreq; / 填写icmp封包数据 echoreq.icmphdr.icmp_type = 8;/ 请求一个icmp回显 echoreq.icmph

12、dr.icmp_code = 0; echoreq.icmphdr.icmp_id = (ushort)getcurrentprocessid(); echoreq.icmphdr.icmp_checksum = 0; echoreq.icmphdr.icmp_sequence = 0; / 填充数据部分,可以为任意 memset(/sets buffers to a specified character.,.,/ 开始发送和接收icmp封包 ushort nseq = 0; sockaddr_in from; int nlen = sizeof(from); while(true) sta

13、tic int ncount = 0; int nret; if(ncount+ = 4) break; echoreq.icmphdr.icmp_checksum = 0; / gettickcount() 系统开始后,已经经过的毫秒数 echoreq.icmphdr.icmp_timestamp = gettickcount(); echoreq.icmphdr.icmp_sequence = nseq+; echoreq.icmphdr.icmp_checksum = checksum(ushort*) ,.,/接收回送应答包 echoreplay echoreply; nret = r

14、ecvfrom(sraw, (char*) ,.,/ 下面开始解析接收到的封包 if(nret sizeof(echoreplay) printf( too few bytes from %s n, inet_ntoa(from.sin_addr); / 接收到的数据中包含ip头,ip头大小为20个字节 if(echoreply.echorequest.icmphdr.icmp_type != 0) / 回显 printf( nonecho type %d recvd n, echoreply.echorequest.icmphdr.icmp_type); return -1; if(echo

15、reply.echorequest.icmphdr.icmp_id != getcurrentprocessid() printf( someone elses packet! n); return -1; ,.,printf( %d bytes reply from %s:, nret, inet_ntoa(from.sin_addr); printf( icmp_seq = %d. , echoreply.echorequest.icmphdr.icmp_sequence); int ntick = gettickcount(); printf( time: %d ms, ntick -

16、echoreply.echorequest.icmphdr.icmp_timestamp); printf( ttl= %d , echoreply.iphdr.ipttl); printf( n); sleep(1000); wsacleanup();/释放winsock库 return 0; ,.,64 bytes reply from 192.168.0.2: icmp_seq = 0. time: 0 ms ttl= 64 64 bytes reply from 192.168.0.2 : icmp_seq = 1. time: 0 ms ttl= 64 64 bytes reply

17、from 192.168.0.2 : icmp_seq = 2. time: 0 ms ttl= 64 64 bytes reply from 192.168.0.2 : icmp_seq = 3. time: 0 ms ttl= 64,ping 程序运行结果,.,51,traceroute(追踪路由) 利用traceroute可侦测出到达网络内特定主机,中途需经过哪些路由器(ip地址)。 利用ping,使用ip选项头内的记录路由选项,侦测中途经过的路由器ip地址,但ping最多只支持9跳。,traceroute程序分析,.,52,.,53,若网络较大,穿过的路由器不止9个,应换用tracer

18、oute。 实现traceroute程序的方法 基本思想:多次发送数据包,ttl递增,ttl 为0时返回一条 icmp报文。 例:路由跟踪程序(采用发送udp数据包) 创建两个套接字: sraw 用于接收icmp数据包 ssend用于发送ttl不断增加的udp数据报,.,traceroute程序主要代码,typedef struct icmp_hdr unsigned char icmp_type;/ 消息类型 unsigned char icmp_code;/ 代码 unsigned short icmp_checksum;/ 校验和 / 下面是回显头 unsigned short icmp

19、_id;/ 用来惟一标识此请求的id号,通常设置为进程id unsigned short icmp_sequence;/ 序列号 unsigned long icmp_timestamp; / 时间戳 icmp_hdr, *picmp_hdr;,.,bool setttl(socket s, int nvalue) int ret = setsockopt(s, ipproto_ip, ip_ttl, (char*) ,.,void main() char *szdestip = “202.199.25.20”; /目的地址 char recvbuf1024 = 0 ; / 创建用于接收icm

20、p封包的原始套节字,绑定到本地端口 socket sraw = socket(af_inet, sock_raw, ipproto_icmp); sockaddr_in in; in.sin_family = af_inet; in.sin_port = 0; in.sin_addr.s_un.s_addr = inaddr_any; if(bind(sraw, (sockaddr*),.,/ 创建用于发送udp封包的套节字 socket ssend = socket(af_inet, sock_dgram, 0); sockaddr_in destaddr; destaddr.sin_fam

21、ily = af_inet; destaddr.sin_port = htons(22); destaddr.sin_addr.s_un.s_addr = inet_addr(szdestip); int nttl = 1; int nret; icmp_hdr *picmphdr; int ntick; sockaddr_in recvaddr; do / 设置udp封包的ttl值 setttl(ssend, nttl); ntick = gettickcount(); / 发送这个udp封包 nret = sendto(ssend, hello, 5, 0, (sockaddr*),.,i

22、f(nret = socket_error) printf( sendto() failed n); break; / 等待接收路由器返回的icmp报文 int nlen = sizeof(recvaddr); nret = recvfrom(sraw, recvbuf, 1024, 0, (sockaddr*) ,.,/ 解析接收到的icmp数据 picmphdr = (icmp_hdr*) ,.,60,4. 使用ip头包含选项,创建原始套接字后使用ip_hdrincl套接字选项可对ip头进行操作,同时也能操作tcp或udp头(或封装在ip内的其他任何协议)。 使用ip_hdrincl选项时

23、,必须针对每一次发送调用,向ip头内自行填充内容。同时还需填写封装在其中的其他协议头。 相关协议报文格式,.,固 定 部 分,可变 部分,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,数 据 部 分,首 部,传送,ip 数据报,发送在前,ip 数据报格式,.,可变 部分,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,

24、填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,数 据 部 分,首 部,传送,ip 数据报,.,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,数 据 部 分,首 部,传送,ip 数据报,固 定 部 分,.,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长

25、度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,固 定 部 分,可变 部分,.,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,固 定 部 分,可变 部分,.,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部

26、检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,固 定 部 分,可变 部分,.,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,固 定 部 分,可变 部分,.,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的

27、地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,固 定 部 分,可变 部分,.,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,固 定 部 分,可变 部分,标志(flag)占 3 位,目前只有前两位有意义。 标志字段的最低位是 mf (more fragment)。 mf 1 表示后面“还有分片”。mf 0 表示最后一个分片。 标志字段中间的一位是 df (dont

28、fragment) 。 只有当 df 0 时才允许分片。,.,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,固 定 部 分,可变 部分,.,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,固

29、 定 部 分,可变 部分,生存时间(8 位)记为 ttl (time to live),这是为了 限制数据报在网络中的生存时间,用“跳数”作为 ttl 的单位。数据报每经过一个路由器,其 ttl 值就减 1。,.,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,固 定 部 分,可变 部分,.,运输层,网络层,首部,tcp,udp,icmp,igmp,ospf,数 据 部 分,ip 数据报,.,

30、首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,固 定 部 分,可变 部分,.,首 部,0,4,8,16,19,24,31,版 本,标志,生 存 时 间,协 议,标 识,区 分 服 务,总 长 度,片 偏 移,填 充,首 部 检 验 和,源 地 址,目 的 地 址,可 选 字 段 (长 度 可 变),位,首部长度,数 据 部 分,固 定 部 分,可变 部分,.,ip 数据报首部的可变部分,ip

31、 首部的可变部分就是一个选项字段,用来支持排错、测量以及安全等措施,内容很丰富。 选项字段的长度可变,从 1 个字节到 40 个字节不等,取决于所选择的项目。 增加首部的可变部分是为了增加 ip 数据报的功能,但这同时也使得 ip 数据报的首部长度成为可变的。这就增加了每一个路由器处理数据报的开销。,.,77,typedef struct _ipheader / 20字节的ip头 uchar iphverlen; / 版本号和头长度(各占4位) uchar iptos; / 服务类型 ushort iplength; / 整个ip报文长度 ushort ipid; / 封包标识 ushort

32、ipflags;/ 标志、片偏移量 uchar ipttl;/ 生存时间ttl uchar ipprotocol; / 协议(tcp、udp、icmp等) ushort ipchecksum; / 校验和 ulong ipsource; / 源ip地址 ulong ipdestination; / 目标ip地址 ipheader, *pipheader;,网络编程中ip头对应结构体声明,.,78,udp头简单。长度仅为8个字节,而且只包含了四个字段,格式如图所示。,由于udp是一种不能保证数据可靠传输的协议,所以校验和的计算是可选的。 udp校验和除覆盖了udp头之外,还同时覆盖了实际的数据,

33、此外还包括ip头的一部分。,.,79,typedef struct _udpheader ushortsourceport;/ 源端口号ushortdestinationport; / 目的端口号ushortlen;/ 封包长度 ushortchecksum;/ 校验和 udpheader, *pudpheader;,.,80,计算udp校验和的附加字段叫作“伪首部”。 udp校验和基于如下几个域: 32位源ip地址(ip头) 32位目标ip地址(ip头) 8位字段(全零) 8位协议 16位udp长度 16位源端口号 16位目标端口号 16位udp长度 16位udp校验和 udp数据,.,81

34、,发送原始udp封包的步骤 首先以ippoto_udp为协议类型创建一个原始套接字,打开原始套接字上的ip_hdrincl选项; 然后构建udp封包(先设置ip头,再设置udp头,最后设置数据); 初始化完整的udp封包之后,调用sendto函数即可将它发送。 例:发送原始udp封包,.,发送原始udp封包,int main() / 输入参数信息 char szdestip = 10.16.115.88; / = 填写目的ip地址 char szsourceip = 127.0.0.1; / = 填写您自己的ip地址 ushort ndestport = 4567; ushort nsourc

35、eport = 8888; char szmsg = this is a test rn; int nmsglen = strlen(szmsg); / 创建原始套节字 socket sraw = socket(af_inet, sock_raw, ipproto_udp); / 有效ip头包含选项 bool bincl = true; setsockopt(sraw, ipproto_ip, ip_hdrincl, (char *),.,/ ip头 ipheader *piphdr = (ipheader *)buff; piphdr-iphverlen = (4iplength = hto

36、ns(sizeof(ipheader) + sizeof(udpheader) + nmsglen); piphdr-ipttl = 128; piphdr-ipprotocol = ipproto_udp; piphdr-ipsource = inet_addr(szsourceip); piphdr-ipdestination = inet_addr(szdestip); piphdr-ipchecksum = checksum(ushort*)piphdr, sizeof(ipheader); / udp头 udpheader *pudphdr = (udpheader *),.,com

37、puteudppseudoheaderchecksum(piphdr, pudphdr, pdata, nmsglen); / 设置目的地址 sockaddr_in destaddr = 0 ; destaddr.sin_family = af_inet; destaddr.sin_port = htons(ndestport); destaddr.sin_addr.s_un.s_addr = inet_addr(szdestip); / 发送原始udp封包 int nret; for(int i=0; i5; i+) nret = sendto(sraw, buff, sizeof(iphe

38、ader) + sizeof(udpheader) + nmsglen, 0, (sockaddr*) ,.,85,5. 网络嗅探器实例,嗅探器设计原理 网卡正常工作模式:套接字程序只接收与自己硬件地址相匹配的或是以广播形式发出的数据帧,对于其他形式的数据帧丢弃。 网络嗅探器的目的:从网卡接收所有经过它的数据包,这些数据包既可以是发给它的也可以是发往别处的。 达到上述目的就不能让网卡按通常的正常模式工作,而必须将其设置为混杂模式。 设置混杂模式只能在原始套接字进行,不能在流套接字和数据报套接字进行。,.,tcp 首部,20 字节的 固定首部,目 的 端 口,数据 偏移,检 验 和,选 项 (长

39、 度 可 变),源 端 口,序 号,紧 急 指 针,窗 口,确 认 号,保 留,f i n,32 位,s y n,r s t,p s h,a c k,u r g,位 0 8 16 24 31,填 充,tcp 数据部分,tcp 首部,tcp 报文段,ip 数据部分,ip 首部,发送在前,.,typedef struct _tcpheader/ 20字节的tcp头 ushortsourceport; / 16位源端口号 ushortdestinationport; / 16位目的端口号 ulongsequencenumber; / 32位序列号 ulongacknowledgenumber; / 32位确认号 uchardataoffset; / 高4位首部长度/6位保留字 ucharflags; / 6位标志位 ushortwindows;/ 16位窗口大小 ushortchecksum;/ 16位校验和 ushorturgentpointer;/ 16位紧急数据偏移量 tcphea

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论