ping与ping6

最近在做一个ping的功能,用python实现,要分别实现ipv4和ipv6两种栈。虽然也是用开源的ping包,并且只有不到300行,但ipv6改的时候确实感觉无从下手;所以老大改完之后,就仔细研究了一下这个包,发现囊括的知识点确实不少。为了避免自己以后忘记,这里记录下来。

ICMP协议

实现ping主要通过ICMP协议,因为IP协议不是一个可靠的协议,不保证数据被成功送达。所以需要使用ICMP网络控制报文协议。因为它传递差错报文和其他重要信息,所以通常供IP层或TCP/UP层使用,被人为是IP层一个重要组成部分。

ICMPv4和ICMPv6消息的前4个字节(也就是前32位)是相同的。数据链路层所能发送的最大数据帧MTU为1500字节,ICMP协议在实际传输中数据包为20字节IP首部+8字节ICMP首部+1472字节(数据大小)。

ping原理

ping程序的目的是测试另一台主机是否可达。该程序发送一份ICMP回显请求报文给远程主机,并等待ICMP回显应答。如果源主机在一定时间内收到应答,则认为主机可达。ping的原理是用类型码为0的ICMP发请求,收到请求的主机则用类型码为8的ICMP回应。通过计算ICMP应答报文数量和接收与发送报文之间的时间差,判断当前网络状态。ping命令在发送报文的时候,将当前时间值存储在ICMP报文中发出,当应答报文返回时,使用当前值减去存放在ICMP报文数据中存放发送请求的时间值来计算往返时间。Unix系统在实现ping程序时是把ICMP报文中的标识符字段置成发送进程的 ID号。这样 即使在同一台主机上同时运行了多个 ping程序实例,ping程序也可以识别出返回的信息。


ping包分析

my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, 1)

//ipv6:my_socket = socket.socket(socket.AF_INET6, socket.SOCK_RAW, 58)

my_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, src_nic)

my_id = os.getpid() & 0xFFFF

send_one_ping(my_socket, dest_addr, my_id, psize)

delay = receive_one_ping(my_socket, my_id, timeout)

1. socket(family,type[,protocal]) 使用给定的地址族、套接字类型、协议编号(默认为0)来创建套接字。

socket类型

socket.AF_INET:服务器之间网络通信

socket.SOCK_RAW:原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文

1这里是协议编号,ICMP协议编号为1,ICMPv6的协议编号为58

这是winsock2.h里的定义。

define IPPROTO_ICMP    1

define IPPROTO_ICMPV6    58   /* ICMPv6 */

2. 默认的socket选项不够时,用setsocket来调整。socket.setsockopt(level, optname, value)

level:选项定义的层次--SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP、IPPROTO_IPV6

optname:需要设置的选项

value:选项值

SOL_SOCKET:正在使用socket选项

当level设定为SOL_SOCKET,会有一些常见选项。SO_BINDTODEVICE:可以使socket只在某个特殊的网络接口有效。这时,value就是设备名称,或者为空字符串返回默认值。

3.send_one_ping(my_socket, dest_addr, my_id, psize)

my_id:Unix系统在实现ping程序时是把ICMP报文中的标识符字段置成发送进程的 ID号。这里和0xFFFF做了&运算,表示取字符低16位

在send_one_ping中要完成构造包的工作。

这一步用到了struct模块。当我们需要用python处理二进制数据,如存储文件,socket操作时,可以使用struct模块,来处理C语言中的结构体。

pack(fmt,v1,v2,v3,...)//按照给定格式fmt,把数据封装成字符串(实际上是类似于C结构体字节流)

format          C type            python type        standard size        notes

b                signed char          integer                    1                    (3)

B            unsigned char          integer                    1                    (3)

h                    short                 integer                    1                    (3)

H             unsigned short        integer                    1                    (3)

对齐方式:!表示我们要使用网络字节顺序解析,因为数据是从网络中接收到的。(字节对齐,通常是以4个字节为单位的32位系统。故struct根据本地机器字节顺序转换,可以用格式中第一个字符来改变对齐方式。)

这里要提到signed char和unsigned char的区别,作为字符使用,都是存字符的ASCII码,作为整数使用,两种类型取值范围不通,unsigned char取0~255,signed char可取值为-128至127。在ipv4中ICMP_ECHO_REQUEST赋值为8,所以struct.pack时用b转换,在ipv6中,ICMP_ECHO_REQUEST赋值为128,所以用B来转换。

    # Remove header size from packet size

    psize = psize - 8

    # Header is type (8), code (8), checksum (16), id (16), sequence (16)

    my_checksum = 0

    # Make a dummy heder with a 0 checksum.

    header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, my_checksum, id, 1)

    //ipv6:header = struct.pack("!BbHHh", ICMP_ECHO_REQUEST, 0, my_checksum, id, 1)

    bytes = struct.calcsize("d")

    data = (psize - bytes) * "Q"

    data = struct.pack("d", time.time()) + data

    # Calculate the checksum on the data and the dummy header.

    my_checksum = checksum(header + data)

    # Now that we have the right checksum, we put that in. It's just easier

    # to make up a new header than to stuff it into the dummy.

    header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), id, 1)

   //ipv6:header = struct.pack( "!BbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), id, 1 )

    packet = header + data

    my_socket.sendto(packet, (dest_addr, 1))  # Don't know about the 1

    //发送UDP数据,将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。

    //ipv6:my_socket.sendto(packet, (dest_addr, 58, 0, 0))

4.校验和算法

IP包发送端,首先将校验和字段设置为0,然后将IP数据包头按16比特划分单元,若包头长度非16倍数,则用0补齐,然后对各个单元采用反码加法运算(即高位溢出加到低位),将得到的和的反码填入校验和字段发送。

比如:

一个数据包:45 00 00 29 44 F1 40 00 80 06 61 8D C0 A6 01 AE 4A 7D 47 7D



参考

https://www.cnblogs.com/JetpropelledSnake/p/9177770.html

https://www.xuebuyuan.com/3254723.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容

  • ping 命令 Ping是为了测试另一台主机是否可达,现在已经成为一种常用的网络状态检查工具。 常见的ping命令...
    iosmedia阅读 5,176评论 3 12
  • Ping的c语言实现 Ping和ICMP Ping简介: ping 命令是用来查看网络上另一个主机系统的网络连接是...
    delta1037阅读 676评论 0 0
  • 推荐 最近很多人都在关注支持 IPv6 的事情吧?我们公司也是。也有不少同行使用了我们的 YTKNetwork 网...
    笨笨的考拉_2阅读 2,440评论 2 9
  • 第一天 早 面包奶 午 铁板面 晚 盖饭 今天 开学第一课 无感 站的很累 肩膀疼 正常上课 思修还可以有点意思...
    日记嘛阅读 197评论 1 3
  • 上周,我记得今天,正是你走的日子,今天,刚刚满一周,记得之前你满怀期望的,上了火车,对部队生活满怀着憧憬。 今...
    红王后阅读 283评论 0 2