您好我在python 2.6中有以下代码:
command = "tcpflow -c -i any port 5559"
port_sniffer = subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1, shell=True)
while True:
line = port_sniffer.stdout.readline()
#do some stuff with line
此代码的目的是嗅探在端口5559上通信的两个进程(A和B)之间的流量。
现在让我描述一下我遇到的不同场景:
1)上面的代码没有运行:
A和B正在通信,我可以使用日志清楚地看到它,linux命令netstat -napl | grep 5559
显示进程正在所需端口上进行通信。
2)上面的代码没有运行,我通过直接从shell运行tcpflow -c -i any port 5559
来嗅探:
我可以清楚地看到控制台上的通信: - )。
3)上面的代码正在运行:Proccesses无法通信。 netstat -napl | grep 5559
不打印任何内容,日志会发出错误!!!
4)上面的代码在调试模式下运行:我似乎无法在行line = port_sniffer.stdout.readline()
我尝试使用迭代器而不是while循环(不是它应该重要,但我仍然指出它)。我还尝试了bufsize(none,1和8)的不同值。
请帮助!!
答案 0 :(得分:1)
所以在快速阅读the docs后,我发现了这两句话:
在Unix上,如果args是一个字符串,则该字符串被解释为名称或 要执行的程序的路径
和
shell参数(默认为False)指定是否使用 shell作为要执行的程序。如果shell为True,则为 建议将args作为字符串而不是序列传递。
基于此,我建议将命令重新创建为列表:
command = ["tcpflow -c", "-i any port 5559"] #I don't know linux, so double check this line!!
一般的想法是这个(也来自文档):
如果args是序列,则第一项指定命令字符串, 任何其他项目将被视为附加参数 壳本身。也就是说,Popen相当于:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
另外,似乎要从您的流程中读取,您应该使用communicate()
。所以
while True:
line = port_sniffer.stdout.readline()
会变成
while True:
line = port_sniffer.communicate()[0]
但请记住文档中的这条说明:
注意读取的数据缓冲在内存中,因此如果数据量很大或无限制,请不要使用此方法。
答案 1 :(得分:0)
如果我不得不猜测,我认为您遇到的问题是您没有以root用户身份运行程序。如果您希望能够嗅探其他人的流量(否则这将是一个严重的安全漏洞),TCPFlow需要作为privelaged用户运行。我编写了以下程序,它们适用于您的场景
server.py
#!/usr/bin/python
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.bind((host,port))
s.listen(5)
while True:
c, addr = s.accept()
print 'Connection from', addr
c.send('Test string 1234')
c.recv(1024)
while x != 'q':
print "Received " + x
c.send('Blah')
x = c.recv(1024)
print "Closing connection"
c.close()
client.py
#!/usr/bin/python
import socket, sys
from time import sleep
from datetime import datetime
s = socket.socket()
host = socket.gethostname()
port = 12345
s.connect((host,port))
c = sys.stdin.read(1) # Type a char to send to initate the sending loop
while True:
s.send(str(datetime.now()))
s.sleep(3)
msg = s.recv(1024)
flow.py
#!/usr/bin/python
import subprocess
command = 'tcpflow -c -i any port 12345'
sniffer = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
while True:
print sniffer.stdout.readline()