我在服务器端口777上收到了日志消息,我想在它们进入时解析它们,而不是将它们保存到磁盘然后解析它们。做这个的最好方式是什么?我查看了套接字模块文档,其中的示例并不适用于我的情况。
tcpdump有办法查看消息
tcpdump -Ai eth0 'port 777'
这基本上做了我想要的,它在我的日志所在的端口777上读取数据包为ASCII,但我想使用Python(2.7.6)而不是tcpdump。
答案 0 :(得分:0)
# pip install pcap dpkt
import pcap
import dpkt
import time
import binascii
DEBUG = False
def print_hex_string_nicely(hex_string):
index = 0
result = ''
while hex_string:
result += '{:08x}: '.format(index)
index += 16
line, hex_string = hex_string[:32], hex_string[32:]
while line:
two_bytes, line = line[:4], line[4:]
if two_bytes:
result += two_bytes + ' '
result = result[:-1] + '\n'
print result
def hex_dump_packet(packet_data):
print_hex_string_nicely(binascii.hexlify(packet_data))
packet_function = None
def get_tcp_from_ethernet(data):
packet = dpkt.ethernet.Ethernet(data)
if isinstance(packet.data, dpkt.ip.IP):
return packet.data.data.data
return None
def get_tcp_from_loopback(data):
packet = dpkt.loopback.Loopback(data)
if isinstance(packet.data, dpkt.ip.IP):
return packet.data.data.data
return None
def get_tcp_from_ip(data):
packet = dpkt.ip.IP(data)
if isinstance(packet, dpkt.ip.IP):
return packet.data.data
return None
def determine_packet_function(packet_data):
type_functions = [get_tcp_from_ethernet, get_tcp_from_loopback, get_tcp_from_ip]
for fn in type_functions:
if fn(packet_data) is not None:
if DEBUG: print 'Packet type:', fn.__name__.split('_')[-1]
return fn
return None
def tcp_data_from_packet_data(packet_data):
global packet_function
if not packet_function:
packet_function = determine_packet_function(packet_data)
if not packet_function:
return None
return packet_function(packet_data)
def tcp_data_from_filter(filter="", interface=None):
# interface notes:
# iptap and pktap alone act like ",any" is appended
# 'any' is a synonym for 'pktap,any'
# pktap and iptap do not work with permiscuous mode
# iptap seems to take no more than 23 characters
# pktap only takes 8 interfaces
# pcap.findalldevs() will return a list of interfaces
# Using iptap makes coding easier since pcap will only
# return the IP portion of the packet
if not interface:
interface="iptap"
if DEBUG: print 'Capturing on interface(s):',interface
# You must set timeout_ms. Not sure why the default doesn't work.
pc = pcap.pcap(name=interface, # default: None
snaplen=256 * 1024, # default: 64k, but tcpdump uses 256k
timeout_ms=500) # defailt: 500, but tcpdump uses 1000
pc.setfilter(filter)
for capture in pc:
if not capture:
continue
timestamp, packet_data = capture
if DEBUG: hex_dump_packet(packet_data)
tcp_data = tcp_data_from_packet_data(packet_data)
if tcp_data is not None:
yield timestamp, tcp_data
def timestring(timestamp):
# 00:14:21.836925
t = time.localtime(timestamp)
s = '{:0.6f}'.format(timestamp - int(timestamp))[1:]
return '{:02}:{:02}:{:02}{}'.format(t.tm_hour, t.tm_min, t.tm_sec, s)
def print_tcp_data_from_filter(**kwargs):
for timestamp, data in tcp_data_from_filter(**kwargs):
print "{} {}".format(timestring(timestamp), data)
# Only show packets containing actual data, i.e. no protocol-only
# packets, coming to my server on port 777.
filter = 'tcp dst port 777 and (tcp[tcpflags] & tcp-push != 0)'
print_tcp_data_from_filter(filter=filter)