Pythonを使用してネットワークパケットをスニッフィングする最良の方法は何ですか?
これに最適なモジュールはScapyと呼ばれるモジュールであるといくつかの場所から聞いていますが、残念ながら、システムでpython.exeがクラッシュします。他の多くの人がWindowsでは特にうまく機能しないと私に言ったことを除いて、それは私がそれをインストールする方法の問題にすぎないと思います。 (誰かが興味を持っているなら、私はWindows Vistaを実行していますが、これは物事に影響を与える可能性があります)。
誰かがより良い解決策を知っていますか?
UPD:
PyPcapをインストールするようにとの回答を読んだ後、少しいじってみたところ、使用しようとしたScapyが、PyPcapもインストールするように指示していることがわかりました。回答の例でもハングが発生したため、問題を引き起こしたのはこの変更されたPyPcapでした。
PyPcapの元のバージョン(Googleのサイトから)をインストールすると、Scapyは正常に動作し始めました(私は多くのことを試しませんでしたが、少なくともスニッフィングを開始するとすぐにクラッシュしませんでした)。私はScapy開発者に新しい欠陥チケットを送りました: http://trac.secdev.org/scapy/ticket/166 、彼らがそれで何かできることを願っています。
とにかく、私がみんなに知らせたいと思っただけです。
pypcap を使用する:
import dpkt, pcap
pc = pcap.pcap() # construct pcap object
pc.setfilter('icmp') # filter out unwanted packets
for timestamp, packet in pc:
print dpkt.ethernet.Ethernet(packet)
出力サンプル:
Ethernet(src='\x00\x03G\xb2M\xe4', dst='\x00\x03G\x06h\x18', data=IP(src='\n\x00\x01\x1c',
dst='\n\x00\x01\x10', sum=39799, len=60, p=1, ttl=128, id=35102, data=ICMP(sum=24667,
type=8, data=Echo(id=512, seq=60160, data='abcdefghijklmnopqrstuvwabcdefghi'))))
Ethernet(src='\x00\x03G\x06h\x18', dst='\x00\x03G\xb2M\xe4', data=IP(src='\n\x00\x01\x10',
dst='\n\x00\x01\x1c', sum=43697, len=60, p=1, ttl=255, id=64227, data=ICMP(sum=26715,
data=Echo(id=512, seq=60160, data='abcdefghijklmnopqrstuvwabcdefghi'))))
Rawソケットを使用して、すべてのIPパケットをスニッフィングできます。
rawソケットは、データをバイナリで送受信するソケットです。
バイナリin pythonは、次のような文字列で表されます\x00\xff
...すべての\x..
はバイトです。
IPパケットを読み取るには、受信したパケットをIPプロトコルに従ってバイナリで分析する必要があります。
これは、すべてのヘッダーのビット単位のサイズのIPプロトコルの形式のイメージです。
このチュートリアルは、生のパケットを理解してヘッダーに分割するプロセスを理解するのに役立つ場合があります。 http://www.binarytides.com/python-packet-sniffer-code-linux/
IPパケットを非常に簡単にスニッフィングする別の方法は、scapyモジュールを使用することです。
from scapy.all import *
sniff(filter="ip", prn=lambda x:x.sprintf("{IP:%IP.src% -> %IP.dst%\n}"))
このコードは、すべてのIPパケットの送信元IPと宛先IPを出力します。ここにあるドキュメントを読むことで、scapyでさらに多くのことができます: http://www.secdev.org/projects/scapy/doc/usage.html
達成しようとしている目標によって異なりますが、プロジェクトを構築する必要がある場合、その機能はIPパケットをスニッフィングすることであるため、より安定したスクリプトにはscapyを使用することをお勧めします。
python-libpcap を使用します。
import pcap
p = pcap.pcapObject()
dev = pcap.lookupdev()
p.open_live(dev, 1600, 0, 100)
#p.setnonblock(1)
try:
for pktlen, data, timestamp in p:
print "[%s] Got data: %s" % (time.strftime('%H:%M',
time.localtime(timestamp)),
data)
except KeyboardInterrupt:
print '%s' % sys.exc_type
print 'shutting down'
print ('%d packets received, %d packets dropped'
' %d packets dropped by interface') % p.stats()
インターフェイスのIPアドレス(管理者モード)でrawソケットを使用できます。
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_IP)
s.bind(("YOUR_INTERFACE_IP",0))
s.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1)
s.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)
while True:
data = s.recvfrom(10000)
print data
気が遠くなる場合は、次の方法を試してください。 (Windows 10で動作します)
# -*- coding: utf-8 -*-
# pip install scapy
"""
[{'name': 'Intel(R) 82574L Gigabit Network Connection',
'win_index': '4',
'description': 'Ethernet0',
'guid': '{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}',
'mac': '00:0C:29:5C:EE:6D',
'netid': 'Ethernet0'}]
"""
from pprint import pprint
from scapy.Arch.windows import get_windows_if_list
from scapy.all import *
# disable verbose mode
conf.verb = 0
def parse_packet(packet):
"""sniff callback function.
"""
if packet and packet.haslayer('UDP'):
udp = packet.getlayer('UDP')
udp.show()
def udp_sniffer():
"""start a sniffer.
"""
interfaces = get_windows_if_list()
pprint(interfaces)
print('\n[*] start udp sniffer')
sniff(
filter="udp port 53",
iface=r'Intel(R) 82574L Gigabit Network Connection', prn=parse_packet
)
if __name__ == '__main__':
udp_sniffer()