ip首部校验和算法
TCPIP协议详解卷1学习笔记-IP校验和与ICMP协议

TCP/IP协议详解卷1学习笔记-IP校验和与ICMP协议TCP/IP协议详解卷1学习笔记-IP校验和与ICMP协议IP数据报的检验和:为了计算一份数据报的I P检验和,首先把检验和字段置为0。
然后,对首部中每个16 bit 进行二进制反码求和(整个首部看成是由一串16 bit的字组成),结果存在检验和字段中。
当收到一份I P数据报后,同样对首部中每个16 bit进行二进制反码的求和。
由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该为全1。
这个是原文。
看一些网络程序的源码时,发现几乎都是用同一种程序来计算检验和的:USHORT checksum(USHORT *buffer, int size) {unsigned long cksum=0;while(size >1) {cksum+=*buffer++;size -=sizeof(USHORT);}if(size ) {cksum += *(UCHAR*)buffer;}cksum = (cksum >> 16) + (cksum & 0xffff);cksum += (cksum >>16);return (USHORT)(~cksum);}摘自 ping 源码。
大家都用的东西看来是不会错的了,不过还是要按协议说的方法用笨办法试试看。
今天看的是ICMP协议,基本格式:|-------- IP 数据报 ------------++--20 bytes --+----------------++ IP首部 + ICMP 报文 ++------------------------------+ICMP报文还是通过IP报文发送出去的。
ICMP的格式:+----8---+----8---+-------- --------++ 8位类型 + 8位代码 + 16位检验和 ++-----------------------------------++ 不同类型有不同的内容和长度 ++-----------------------------------+ICMP的报文类型有很多种,而每种类型里又有多种代码。
校验和算法

校验和算法IP/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的。
今儿以IP 数据包为例来讲解一下校验和算法。
在IP数据包发送端,首先将校验和字段置为0,然后将IP数据包头按16比特分成多个单元,如果包头长度不是16比特的倍数,则用0比特填充到16 比特的倍数,其次对各个单元采用反码加法运算(即高位溢出位会加到低位,通常的补码运算是直接丢掉溢出的高位),将得到的和的反码填入校验和字段,最后发送数据。
在IP数据包接收端, 首先将IP包头按16比特分成多个单元,如果包头长度不是16比特的倍数,则用0比特填充到16比特的倍数,其次对各个单元采用反码加法运算,检查得到的和是否符合全是1(有的实现可能对得到的和取反码,然后判断最终的值是否为0),如果符合全是1(取反码后是0),则进行数据包的下一步处理,如果不符合,则丢弃该数据包。
在这里大家要注意,反码和是采用高位溢出加到低位上。
接下来以一张从网上找的一张IP数据包头图片来加以说明以上的算法。
大家应该记得一个公式,即两数据的反码和等于两数据和的反码,把它推广到n个数据同样适用,公式:~[X]+~[Y]=~[X+Y]从这张图片可以看出它的校验和是0x618D,现在我们来用它来模拟我们的发送端和接收端。
发送端:步骤如下:首先,将checksum字段设为0,那么将得到IP数据包头的分段信息如下1. 0x45002. 0x00293. 0x44F14. 0x40005. 0x80066. 0x0000 ------->这个为Header Checksum的值,我们前面将其重置为0了7. 0xC0A88. 0x01AE9. 0x4A7D+10. 0x477D结果为:0x29E70注意要将溢出位加到低位,即0x29E70的溢出位为高位2,将它加到低位上,即0x9E70+0x2=0x9E720x9E72二进制为:1001 1110 0111 0010反码为:0110 0001 1000 11010110 0001 1000 1101的16进制为:0x618D(这就是我们的校验和) 接收端:当我们收到该数据包时,它的分段信息将是如下信息:1. 0x45002. 0x00293. 0x44F14. 0x40005. 0x80066. 0x618D ------->这个为Header Checksum的值7. 0xC0A88. 0x01AE9. 0x4A7D+10. 0x477D结果为:0x2FFFD该数值的溢出位为高位2,把它加到底位D上,即0xFFFD+0x2=0xFFFF 0xFFFF二进制为:1111 1111 1111 11111111 1111 1111 1111反码为:0。
TCP、UDP、IP校验和

TCP、UDP、IP校验和
TCP和UDP校验和
校验和所校验的内容包括:12字节伪⾸部、TCP的⾸部以及全部数据。
伪⾸部:包含了源地址、⽬的地址、协议和TCP长度等字段,这能够防⽌TCP出现错误的。
并⾮TCP数据报中实际的有效成分。
伪⾸部是⼀个虚拟的数据结构,其中的信息是从数据报所在IP分组头的分组头中提取的,既不向下传送也不向上递交,⽽仅仅是为计算校验和。
这样的校验和,既校验了TCP⽤户数据的源和⽬的端⼝号以及TCP⽤户数据报的数据部分,⼜检验了的源IP地址和⽬的地址。
(伪报头保证UDP和TCP到达正确的⽬的地址。
因此,伪报头中包含IP地址并且作为计算校验和需要考虑的⼀部分。
最终⽬的端根据伪报头和数据单元计算校验和以验证通信数据在传输过程中没有改变⽽且到达了正确的⽬的地址。
)
tcp报⽂中,在tcp的⾸部之前,多了⼀个12字节的伪⾸部,伪⾸部中4个字节保存源ip信息,4个字节⽬的ip信息,⼀个字节的保留位置,⼀个字节保存协议号(6代表tcp,17代表udp),2个字节保存tcp⾸部+数据的长度。
根据伪⾸部的信息通过位运算,得到了⼀个校验和数据,保存在tcp保温的checksum字段。
接收端接收到tcp报⽂后,也按照特定算法计算出⼀个校验和,与checksum保存的校验和⽐较,如果相同,则完成此报⽂的接收。
如果不相同,则丢弃此报⽂,让发送端重传。
tcp校验和与ip校验和的区别是:TCP和UDP检验和覆盖⾸部和数据,⽽IP⾸部中的检验和只覆盖IP的⾸部,不覆盖IP数据报中的任何数据。
tcp校验和和udp校验和的区别是:TCP的检验和是必需的,⽽UDP的检验和是可选的。
IPv4首部

IPv4⾸部《图解TCP/IP》 4.7 IPv4的⾸部版本:由4⽐特构成,表⽰标识IP⾸部的版本号。
IPv4的版本号即为4,因此在这个字段上的值也为“4”。
⾸部长度:由4⽐特构成,表明IP⾸部的⼤⼩,单位为4字节(32⽐特)。
对于没有可选项的IP包,⾸部长度则设置为“5”。
也就是说,当没有可选项时,IP⾸部的长度为20字节(4*5=20)。
区别服务:由8⽐特构成,⽤来表明服务质量。
每⼀个的具体含义如表所⽰。
这个值通⽤由应⽤指定。
⽽且现在也⿎励这种结合应⽤的特性设定TOS(Type of Service)的⽅法。
然⽽在⽬前,⼏乎所有的⽹络都⽆视这些字段。
这不仅是因为在符合质量的要求下按其要求发送本⾝的功能实现起来⼗分困难,还因为若不符合质量要求就可能会产⽣不公平现象。
因此,实现TOS控制变得极其复杂。
这也导致TOS整个互联⽹⼏乎就没有被投⼊使⽤。
不过已有⼈提出将TOS字段再划分为DSCP和ECN两个字段的建议。
DSCP(Differential Services Codepoint,差分服务代码点)是TOS(Type Of Services)的⼀部分。
现在统称为DiffSer,⽤来进⾏质量控制。
如果3-5位的值为0,0~2位则被称作类别选择代码点。
这样就可以向TOS的优先度那样提供8中类型的质量控级别。
对于每⼀种级别所采取的措施则由提供DiffServ的运营管理者制定。
为了与TOS保持⼀致,值越⼤优先度也越⾼。
如果第五位为1,表⽰实验或本地使⽤的意思。
ECN(Ecplicit Congestion Notification,显⽰拥塞通告)⽤来报告⽹络拥塞情况,由两个⽐特构成。
第6位的ECT ⽤以通告上传TCP层协议是否处理ECN。
当路由器在转发ECN为1的包的过程中,如果出现⽹络拥塞的情况,就将CE位设置为1。
总长度:表⽰IP⾸部与数据部分合起来的字节数。
该字段长16⽐特。
因此IP包的最⼤长度为65535=2^16字节。
scapy ipv4 checksum 校验和计算方法

scapy ipv4 checksum 校验和计算方法IPv4协议是Internet协议簇中用于网络包传送的一个主要协议。
在IPv4协议中,每个数据包都会有一个校验和字段,用于验证数据包在传输过程中是否发生了错误。
校验和是通过对包括源IP地址、目标IP地址、协议类型、数据长度等在内的数据包头部和数据部分进行计算而得出的一个值,接收方可以通过计算校验和来验证数据包的完整性。
在计算IPv4包的校验和时,首先需要将整个数据包按16位作为一个单位进行分组,对各个16位的单位进行求和,最后再加上进位的值。
最终得到的结果取反就是IPv4包校验和的值。
下面我们将详细介绍计算IPv4包校验和的方法。
首先,我们需要了解IPv4协议数据包的格式。
一个典型的IPv4数据包包括了如下的字段:版本号、头部长度、区分服务、总长度、标识、标记、生存时间、协议类型、校验和、源IP地址、目标IP地址、选项(可选)、数据(Payload)等。
其中,我们关注的是校验和字段,也就是在IP头部中的第十个字节和第十一个字节。
接下来,我们来了解一下IPv4包校验和的计算过程。
在计算校验和时,我们需要对数据包中的各个16位的单位进行求和。
具体的计算方法包括以下几个步骤:1.对所有的16位的值进行求和,得到一个累加和。
2.将累加和按16位进行截取,进行溢出位的处理。
3.取得到的结果的反码作为校验和的值。
具体的计算过程为:1.首先,将所有的16位的值进行求和。
这里需要注意的是,需要将校验和字段先置为0,然后再对所有的16位的数据进行求和。
2.接着,将得到的累加和值按16位进行截取,并将溢出位加回到累加和值中。
3.最后,对得到的结果取反,得到最终的校验和值。
举个例子来说明:假设我们有一个IPv4数据包,其前20个字节依次为0101010101010101、0110011001100110、1001100110011001、1011011101110111。
ip校验规则

ip校验规则
IP校验规则通常包括以下几点:
1. IP地址格式检查:确保输入的IP地址符合正确的格式,例如IPv4地址应分为四个十进制数,每个数字范围在0-255之间,用点号分隔。
IPv6地址则需要符合相应的格式。
2. IP地址范围检查:检查IP地址是否在一个有效的地址范围内。
例如,有些地址段可能被保留用于特定目的,如私有IP地址段(如10.0.0.0 - 10.255.255.255)或公共IP地址段(如192.168.0.0 - 224.0.0.0)。
3. 子网掩码检查:如果使用了子网掩码,需要确保输入的子网掩码符合正确的格式,并与其对应的IP地址匹配。
4. IP地址唯一性检查:确保同一个子网内没有重复的IP地址。
5. 排除特殊IP地址:根据需求,可以排除某些特殊IP地址,如回环地址(127.0.0.1)、默认网关地址等。
6. 负载均衡策略:如果需要实现负载均衡,可以针对不同的服务实例制定相应的策略,如根据权重、响应时间等指标来分配请求。
7. 动态转发规则:根据运行过程中的实际情况,可以动态调整转发地址。
例如,当某个服务实例出现故障时,可以及时将其从路由规则中移除,避免将请求转发到不可用的服务上。
在实际应用中,可以使用编程语言或相关库(如Java 中的``包)来实现IP校验规则的检查功能。
同时,还可以借助一些开源项目,如Spring Cloud Gateway,通过配置文件或代码实现IP校验和路由规则的制定。
解析IPv4和IPv6分组的校验和算法

解析IPv4和IPv6分组的校验和算法77 发表于 2005-10-26 10:02:00关于IP分组头的校验和(checksum)算法,简单的说就是16位累加的反码运算,但具体是如何实现的,许多资料不得其详。
TCP和UDP数据报头也使用相同法,的校验算但参与运算的数据与IP分组头不一样。
此外,IPv6对校验和的运算与IPv4又有些许不同。
因此有必要对IP分组的校验和算法作全面的解析。
IPv4分组头的结构如下所示:0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| IHL |Type of Service| Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification |Flags| Fragment Offset | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time to Live | Protocol | Header Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+其中的"Header Checksum"域即为头校验和部分。
TCPIP校验和

TCPIP校验和1. IP 头IP数据包也叫IP报⽂分组,传输在ISO⽹络7层结构中的⽹络层,它由IP报⽂头和IP报⽂⽤户数据组成,IP报⽂头的长度⼀般在20到60个字节之间,⽽⼀个IP分组的最⼤长度则不能超过65535个字节。
下图为IP分组的报⽂头格式,报⽂头的前20个字节是固定的,后⾯的可变。
版本:占4位(bit)指IP协议的版本号。
⽬前的主要版本为IPV4,即第4版本号,也有⼀些教育⽹和科研机构在使⽤IPV6。
在进⾏通信时,通信双⽅的IP协议版本号必须⼀致,否则⽆法直接通信。
⾸部长度:占4位(bit)指IP报⽂头的长度。
最⼤的长度(即4个bit都为1时)为15个长度单位,每个长度单位为4字节(TCP/IP标准,DoubleWord),所以IP协议报⽂头的最⼤长度为60个字节,最短为上图所⽰的20个字节。
服务类型:占8位(bit)⽤来获得更好的服务。
其中的前3位表⽰报⽂的优先级,后⾯的⼏位分别表⽰要求更低时延、更⾼的吞吐量、更⾼的可靠性、更低的路由代价等。
对应位为1即有相应要求,为0则不要求。
总长度:16位(bit)指报⽂的总长度(包括报⽂头)。
注意这⾥的单位为字节,⽽不是4字节,所以⼀个IP报⽂的的最⼤长度为65535个字节。
标志(flag)该字段⽤于标记该报⽂是否为分⽚(有⼀些可能不需要分⽚,或不希望分⽚),后⾯是否还有分⽚(是否是最后⼀个分⽚)。
⽚偏移指当前分⽚在原数据报(分⽚前的数据报)中相对于⽤户数据字段的偏移量,即在原数据报中的相对位置。
⽣存时间:TTL(Time to Live)该字段表明当前报⽂还能⽣存多久。
每经过1ms或者⼀个⽹关,TTL的值⾃动减1,当⽣存时间为0时,报⽂将被认为⽬的主机不可到达⽽丢弃。
使⽤过Ping命令的⽤户应该有印象,在windows中输⼊ping命令,在返回的结果中即有TTL的数值。
协议该字段指出在上层(⽹络7层结构或TCP/IP的传输层)使⽤的协议,可能的协议有UDP、TCP、ICMP、IGMP、IGP等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告(3) ——首部检验和的编程实现 一、 实验人员 二、实验内容和要求 (一)实验内容 编写一个计算IP报文中首部校验和的程序,并且通过抓包随机选择一个数据报,提取出IP报文首部部分,根据程序计算出校验和的计算值,与报文中检验和对比,检验程序的正确性,计算结果为0保留数据报,否则丢弃。
(二)实验要求 1.掌握IP数据报的结构,通过wireshark抓包随机选择一个TCP数据报,提取IP报部分,并找到首部。
2.学习理解并运用IP首部校验和的计算算法,通过程序实现。 三、实验环境 Wireshark抓包工具 Microsoft visual studio 2010 C# 四、实验过程与结果分析 (一)实验过程 1.利用wireshark抓包分析包格式并提取IP首部 (1)IP数据报格式 如图1,IP数据报的首部为前20字节。因为首部校验和的计算只需要IP数据报的首部20个字节即可,数据部分不参加运算。所以只需要把IP数据包中的前20个16进制数提取出来作为运算的数据即可。
图 1 IP数据包格式 (2)抓包得到的数据报 图 2 TCP数据报 如图2,通过wireshark抓包,随机选择一个TCP数据报,根据TCP数据报的格式,我们分析数据报内容可以知道:首先开始6个字节为目的mac地址,后面6个字节为目的mac地址,后面2个字节为协议类型为0800,是IP协议包。所以再后面的20个字节就是IP数据报的首部部分。也就是实验所需要的数据。
IP首部为:450000280000400034060ab73baf84710a687191 并且,通过包的计算的校验和结果,此包被留下,校验和的值为0。也是座位后面对设计程序计算得到结果的一个验证。
2.设计计算首部校验和的的算法 (1)程序设计的函数模块关系 (2)算法流程 首先将IP首部即40位16进制的字符串转化为二进制字符串,然后以每16位为一个字段,分为10个二进制字段。存放在IP1~IP10字符串中;
然后求出每个字段的反码,根据IP数据报格式,可以知道IP6存放的就是校验和,将校验和IP6置位全0;
利用求反码和方法FanMa(),求出10个字段反码相加后的值string sum,然后对字符串sum取反,得到发送时所用的校验码。
假设接收端的IP首部与发送的是相同的,那么其10个字段的利用反码和算法求出的值应为0。
算法的流程与在发送端求出发送的校验码过程相同。
输入IP首部 string IP0 转化为二进制字符串并划分为10个字段IP1~IP10,函数Getziduan()
求字段反码,函数FanMa()
反码求和函数FanSum();FanSum0(); 求出由上一布得到的结果的反码,输出结果 (3)几个主要的方法 将16进制转化为二进制的字符串操作: public static string Change(char a) {
switch (a) { case '0': return "0000"; case '1': return "0001"; case '2': return "0010"; case '3': return "0011"; case '4': return "0100"; case '5': return "0101"; case '6': return "0110"; case '7': return "0111"; case '8': return "1000"; case '9': return "1001"; case 'a': return "1010"; case 'b': return "1011"; case 'c': return "1100"; case 'd': return "1101"; case 'e': return "1110"; case 'f': return "1111"; default: break; } return "xxxx"; } 求各字段的反码: public static string FanMa(string zd) { string buff0 = ""; char a; for (int i = 0; i < zd.Length; i++) { a = zd[i]; if (a == '0') { buff0 = buff0 + "1"; } else { buff0 = buff0 + "0"; } } return buff0; }
求各字段的和: public static string FanSum(string ip1, string ip2, string ip3, string ip4, string ip5, string ip6, string ip7, string ip8, string ip9, string ip10,int len) { string buff = ""; buff = FanSum0(ip1, ip2, len); buff = FanSum0(buff, ip3, len); buff = FanSum0(buff, ip4, len); buff = FanSum0(buff, ip5, len); buff = FanSum0(buff, ip6, len); buff = FanSum0(buff, ip7, len); buff = FanSum0(buff, ip8, len); buff = FanSum0(buff, ip9, len); buff = FanSum0(buff, ip10, len); return buff;
} public static string FanSum0(string ip1, string ip2,int len) { string sum = ""; char a; char b; string buff=""; string buff1=""; int k = 0; for (int i = len-1; i >=0; i--) { a = ip1[i]; b = ip2[i]; if (a == '0' && b == '1' && k == 0) { buff = buff + "1"; k = 0; continue; } if (a == '1' && b == '0' && k == 0) { buff = buff + "1"; k = 0; continue; } if (a == '1' && b == '1' && k == 0) { buff = buff + "0"; k = 1; continue; } if (a == '1' && b == '1' && k == 1) { buff = buff + "1"; k = 1; continue; } if (a == '1' && b == '0' && k == 1) { buff = buff + "0"; k = 1; continue; } if (a == '0' && b == '1' && k == 1) { buff = buff + "0"; k = 1; continue; } if (a == '0' && b == '0' && k == 1) { buff = buff + "1"; k = 0; continue; } if (a == '0' && b == '0' && k == 0) { buff = buff + "0"; k = 0; continue; }
} for (int j = len-1; j >= 0; j--) {
buff1 = buff1 + buff[j]; }
if (k == 1) sum = FanSum0(buff1, "0000000000000001", 16); else sum = buff1; return sum;
}
3.显示结果并与已知值对比 结果显示最后的校验和为0,这个数据包被留下,与实际情况相同,但此时还不能说明算法一定正确,因为我们还没有考虑数据包被丢弃的情况。 在数据包被丢弃的情况下,肯定是最终算的校验和不为0,也就是接受到的IP首部与发送的不同,因此我们只要将接收端用来计算校验和的字段IP1~IP10任意更改一位,使其与原来不同即可。我所做的更改为由原来IP1的反码:1011101011111111,在计算接收端的校验和时更改为:1011101011111110。 所得到的结果为:
所以算法是正确的。 (二)结果分析 通过数据包正确接收和被丢弃两种情况对设计的校验和计算算法的比较,计算的结果与实际情况校验和的值是一致的,因此在数据报在实际通信时,利用校验和的方式可以判定所接收的数据报是否发生了变化,保证了可靠性。同时校验和的方法又是比较简便快速的,减少了时间上的开销,因此是在实际情况下比较适用的方法。
五、小结
(一)实验中曾经出现的犯过的错误、遇到的问题及相应的解决方案。 1.在利用字符串计算字段相加求值时开始没有考虑到计算结果正好是实际值的倒叙,通过调试观察局部变量的方法发现了错误,将计算结果作了顺序的转换,