這篇文章緊接着《使用Python來分離或者直接抓取pcap抓包文件中的HTTP流》展開,那篇文章是昨天寫的,今天早上突然又想實現一個直接抓包的程序,於是天沒亮就又爬起來了...
本文的代碼以及前文的代碼在github的地址:https://github.com/marywangran/Python-Http-cap-demux/tree/master
Python的庫太過豐富,但是前提是你必須可以隨意安裝它,我比較推薦使用pip安裝,它就像apt-get,yum這樣,甚至語法都一樣:
apt-get/yum/pip install aaaaa
但是pip要真的用起來似乎還是要花點時間的。我首先下載了setuptool:
wget https://pypi.python.org/packages/source/s/setuptools/setuptools-3.0.tar.gz
然後解壓,進入其主目錄後執行:
python ./setup.py build
python ./setup.py install
然後在我瞭解到pip本身也是一個Python庫的時候,我執行了:
easy_install pip
隨後得到了令人遺憾的錯誤提示,說什麼”unknown url type: https“,然後我問了度娘,解決了該問題,很簡單,執行下面的步驟即可:
1.yum install openssl-devel
2.重新編譯Python並install
接下來就可以easy_install pip了,然後就可以:
pip install pypcap
pip install dpkt
最後,代碼就可以隨便寫了...
我主要還是想在直接抓包的時候就過濾好我想要的包,而不是先抓一個超級大的pcap文件,然後再慢慢解析分流。只要腦子裏面有清晰的邏輯,並且手邊有一個得心應手的編程語言,模擬任何事情都不是難事,把昨天的代碼一改,把分析pcap的邏輯改成pypcap/dpkt抓包解包的邏輯,一切似乎就是那麼簡單。代碼如下:
- #!/usr/local/bin/python
- import pcap
- import dpkt
- cap = pcap.pcap('eth3')
- cap.setfilter('tcp port 80')
- files4out = {}
- url = 'www.baidu.com'
- for ptime,pktdata in cap:
- pkt = dpkt.ethernet.Ethernet(pktdata)
- if pkt.data.data.__class__.__name__ <> 'TCP':
- continue
- ipsrc_tag = 0
- ipdst_tag = 0
- sport_tag = 0
- dport_tag = 0
- ipdata = pkt.data
- sip='%d.%d.%d.%d'%tuple(map(ord,list(ipdata.src)))
- dip='%d.%d.%d.%d'%tuple(map(ord,list(ipdata.dst)))
- tcpdata = pkt.data.data
- sport = tcpdata.sport
- dport = tcpdata.dport
- src_tag = sip
- dst_tag = dip
- sp_tag = str(sport)
- dp_tag = str(dport)
- if ord(list(ipdata.src)[0]) > ord(list(ipdata.dst)[0]):
- temp = dst_tag
- dst_tag = src_tag
- src_tag = temp
- if sport > dport:
- temp = sp_tag
- sp_tag = dp_tag
- dp_tag = temp
- content = url
- FLAG = 0
- appdata = tcpdata.data
- if appdata.find(content) <> -1:
- print 'find'
- FLAG = 1
- name = src_tag + '_' + dst_tag + '_' + sp_tag + '_' + dp_tag
- if (name) in files4out:
- item = files4out[name]
- fi = 0
- cnt = item[1]
- if cnt < 6 and item[3] <> 1:
- item[1] += 1
- item[2].append(pktdata)
- if FLAG == 1:
- item[3] = 1
- elif item[3] == 1:
- for index in range(cnt+1):
- pktdatai = item[2][index]
- pkti = dpkt.ethernet.Ethernet(pktdatai)
- ipdatai = pkti.data
- tcpdatai = pkti.data.data
- sipi='%d.%d.%d.%d'%tuple(map(ord,list(ipdatai.src)))
- dipi='%d.%d.%d.%d'%tuple(map(ord,list(ipdatai.dst)))
- sporti = tcpdatai.sport
- dporti = tcpdatai.dport
- print '[datai]' + sipi + ':' + str(sporti) + '-' + dipi + ':' + str(dporti)
- item[1] = -1
- print '[data]' + sip + ':' + str(sport) + '-' + dip + ':' + str(dport)
- else
- # 這裏優化空間巨大!
- # 爲了不讓隨意的五元組無情地侵佔字典空間,這裏有幾個策略:
- # 1.發現FIN的時候,再容許這個流在字典中存在固定的時間段或者在允許此流來回5個包,之後刪除字典的索引
- # 2.如果超過6個包都沒有等到GET /$url,那麼在timewait的時間內,此流不允許佔據字典空間
- del files4out[name]
- else:
- item = [0, 0, [], 0, 0]
- item[2].append(pktdata)
- files4out[name] = item