Python socket編程之構造IP首部和ICMP首部

來源:互聯網
上載者:User

標籤:

這兩天在做一個實驗需要自己構造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 + thisVal10         sum = sum & 0xffffffff 11         count = count + 212     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 = ~sum18     answer = answer & 0xffff19     answer = answer >> 8 | (answer << 8 & 0xff00)20     return answer21 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 packet26  27     source_ip = ‘172.16.12.1‘28     dest_ip = ip29  30 # ip header fields31     ihl = 532     version = 433     tos = 034     tot_len = 2835     id = 036     frag_off = 037     ttl = 25538     protocol = 139     check = 0  40     saddr =socket.inet_aton ( source_ip )  #Spoof the source ip address if you want to41     daddr = socket.inet_aton ( dest_ip )44     ihl_version = (version << 4) + ihl45     # the ! in the pack format string means network order46     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, 049     )50     chksum=checksum(packet)51     packet = struct.pack(52             "!BBHHH", 8, 0, chksum, 0, 053     )54     packet=ip_header+packet55     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請求得不到應答而產生的。

Python socket編程之構造IP首部和ICMP首部

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.