设为首页 收藏本站
查看: 756|回复: 0

[经验分享] Python socket编程之构造IP首部和ICMP首部

[复制链接]

尚未签到

发表于 2015-11-29 15:34:29 | 显示全部楼层 |阅读模式
  这两天在做一个实验需要自己构造IP首部,遇到诸多问题,搞了一天终于搞定。
  关于socket的介绍网上一大堆,我只记录构造IP头时我遇到的问题。由于没玩过socket构造IP首部,网上找了段代码研究下,无奈代码跑不动,各种问题,网上搜集资料无果,从基础学起,加上自己的脑洞总算解决了。
  我想自己构造一个自定义IP头的ICMP回送请求,网上找了段代码,自己改了改,现在长这个样子:



1 import socket
2 import struct
3 def checksum(source_string):
4     sum = 0
5     countTo = (len(source_string)/2)*2
6     count = 0
7     while count<countTo:
8         thisVal = ord(source_string[count + 1])*256 + ord(source_string[count])
9         sum = sum + thisVal
10         sum = sum & 0xffffffff
11         count = count + 2
12     if countTo<len(source_string):
13         sum = sum + ord(source_string[len(source_string) - 1])
14         sum = sum & 0xffffffff
15     sum = (sum >> 16)  +  (sum & 0xffff)
16     sum = sum + (sum >> 16)
17     answer = ~sum
18     answer = answer & 0xffff
19     answer = answer >> 8 | (answer << 8 & 0xff00)
20     return answer
21 def ping(ip):
22     s=socket.socket(socket.AF_INET,socket.SOCK_RAW,255)
24     s.setsockopt(0, socket.IP_HDRINCL, 1)
25 # now start constructing the packet
26  
27     source_ip = '172.16.12.1'
28     dest_ip = ip
29  
30 # ip header fields
31     ihl = 5
32     version = 4
33     tos = 0
34     tot_len = 28
35     id = 0
36     frag_off = 0
37     ttl = 255
38     protocol = 1
39     check = 0  
40     saddr =socket.inet_aton ( source_ip )  #Spoof the source ip address if you want to
41     daddr = socket.inet_aton ( dest_ip )
44     ihl_version = (version << 4) + ihl
45     # the ! in the pack format string means network order
46     ip_header = struct.pack('!BBHHHBBH4s4s', ihl_version, tos, tot_len, id, frag_off, ttl, protocol, check, saddr, daddr)
47     packet = struct.pack(
48             "!BBHHH", 8, 0, 0, 0, 0
49     )
50     chksum=checksum(packet)
51     packet = struct.pack(
52             "!BBHHH", 8, 0, chksum, 0, 0
53     )
54     packet=ip_header+packet
55     s.sendto(packet,(ip,1))
56     print "done"
57     
58 if __name__=='__main__':
59     ping('172.31.0.1')
  步骤很简单,就是自己创建个套接字,然后把头构造好再发送就行了,但是一般的套接字是无法自己更改IP头的,只能从IP数据报的数据部分开始构造,想要构造IP首部就要用到原始套接字,用原始套接字可以从IP首部开始构造,但是如果用原始套接字需要root权限,开始我在OS X下用IDE,程序总是报错socket.error: [Errno 1] Operation not permitted,就是因为权限的问题,在终端里sudo运行就没有权限问题了(Ps:如果想用root权限打开IDE,又不想切换账户的话,终端里sudo ./IDE就行了)现在有了权限,开始报别的错了,提示socket.error: [Errno 22]Invalid argument。
  这是创建原始套接字的代码,第一行第三个值255是IPPROTO_RAW的值,如果要构造IP头,就要加上第二行代码设置IP_HDRINCL,第一个值0是IPPROTO_IP的值



s=socket.socket(socket.AF_INET,socket.SOCK_RAW,255)
s.setsockopt(0, socket.IP_HDRINCL, 1)
  如果这样设置在OS X下就会在调用sendto()的位置报Invalid argument错误,后来发现问题出在第一行的第三个参数255上,经测试发现
  在OS X下,这个参数置成0或255都会报错
  在WINDOWS下 ,这个参数置成0或255都不会报错
  在LINUX下,这个参数置成0会报错,置成255不会报错
  
  现在可以构造任意的源IP和目的IP的ICMP回送请求了,IP首部字段的ID,长度,校验和置成0就可以,内核协议栈会修正。
  在linux上抓包发现目的IP为同子网下不存在的主机IP时,是抓不到ICMP包的,这是因为主机先发送ARP包请求目的IP的MAC地址得不到回应,而不能进一步发送ICMP回送请求,也就是说PING命令中提示的Request timeout for icmp_seq是因为ARP请求得不到应答而产生的。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-145022-1-1.html 上篇帖子: 2015/8/31 Python基础(5):字符串 下篇帖子: 【原创】Python第二章——标识符命名规则
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表