我正在用python(平台是linux)编写一个工具,其中一项任务是捕获实时tcp流对每一行应用一个函数。目前我正在使用
import subprocess
proc = subprocess.Popen(['sudo','tcpflow', '-C', '-i', interface, '-p', 'src', 'host', ip],stdout=subprocess.PIPE)
for line in iter(proc.stdout.readline,''):
do_something(line)
这工作得很好(在/etc/sudoers中有适当的条目),但我希望避免调用外部程序。
到目前为止,我已经研究了以下可能性:
flowgrep:一个python工具,看起来就像我需要的,但是:它使用pynids内部,它已经7年了,似乎几乎被抛弃了。没有pynids包对于我的gentoo系统,它附带了libnids的修补版本如果不进一步调整,我就无法编译。
scapy:这是一个python的包操作程序/库,我不确定tcp流支持重新装配。
pypcap或pylibpcap作为libpcap的包装器。同样,libpcap用于数据包捕获,我需要重新组装流,根据对于这个问题。
在我深入研究这些图书馆之前,我想知道是否有人有一个工作代码片段(这似乎是一个相当常见的问题)。如果有人可以就正确的道路提供建议。
感谢
Jon Oberheide领导了维护pynids的工作,这是最新的:http://jon.oberheide.org/pynids/
因此,这可能允许您进一步探索flowgrep。Pynids本身处理流重构相当优雅。请参阅http://monkey.org/~jose/ppresentation/pysniff04.d/获取一些好的示例。
作为后续:我放弃了在tcp层上监视流的想法。相反,我用python编写了一个代理,并让我想要监控的连接(http会话)通过这个代理进行连接。结果更加稳定,并且不需要root权限即可运行。这个解决方案依赖于吡喹酮。
这将进入一个独立的程序,例如helper_proxy.py
from multiprocessing.connection import Listener
import StringIO
from httplib import HTTPResponse
import threading
import time
from miproxy.proxy import RequestInterceptorPlugin, ResponseInterceptorPlugin, AsyncMitmProxy
class FakeSocket(StringIO.StringIO):
def makefile(self, *args, **kw):
return self
class Interceptor(RequestInterceptorPlugin, ResponseInterceptorPlugin):
conn = None
def do_request(self, data):
# do whatever you need to sent data here, I'm only interested in responses
return data
def do_response(self, data):
if Interceptor.conn: # if the listener is connected, send the response to it
response = HTTPResponse(FakeSocket(data))
response.begin()
Interceptor.conn.send(response.read())
return data
def main():
proxy = AsyncMitmProxy()
proxy.register_interceptor(Interceptor)
ProxyThread = threading.Thread(target=proxy.serve_forever)
ProxyThread.daemon=True
ProxyThread.start()
print "Proxy started."
address = ('localhost', 6000) # family is deduced to be 'AF_INET'
listener = Listener(address, authkey='some_secret_password')
while True:
Interceptor.conn = listener.accept()
print "Accepted Connection from", listener.last_accepted
try:
Interceptor.conn.recv()
except: time.sleep(1)
finally:
Interceptor.conn.close()
if __name__ == '__main__':
main()
从python helper_proxy.py
开始。这将创建一个代理,侦听端口8080上的http连接,并侦听端口6000上的另一个python程序。一旦另一个python程序在该端口上连接,助手代理将向其发送所有http回复。这样,助手代理就可以继续运行,保持http连接,并且可以重新启动侦听器进行调试。
以下是侦听器的工作方式,例如listener.py
:
from multiprocessing.connection import Client
def main():
address = ('localhost', 6000)
conn = Client(address, authkey='some_secret_password')
while True:
print conn.recv()
if __name__ == '__main__':
main()
这只会打印所有回复。现在,将浏览器指向运行在8080端口上的代理,并建立要监视的http连接。