簡體   English   中英

如何使用python在端口上嗅探日志消息?

[英]How do I sniff on a port for log messages using python?

我在服務器端口777上收到了日志消息,我想在它們進入時解析它們,而不是將它們保存到磁盤然后解析它們。 做這個的最好方式是什么? 我查看了socket模塊文檔,那里的例子並不適用於我的情況。

tcpdump有辦法查看消息

tcpdump -Ai eth0 'port 777'

這基本上做我想要的,它在我的日志所在的端口777上讀取數據包為ASCII,但我想使用Python(2.7.6)而不是tcpdump。

博客文章 | GitHub | LGPLv2.1

# 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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM