【问题标题】:Can I sniff UDP packets addressed another Linux machine using Python?我可以嗅探使用 Python 寻址另一台 Linux 机器的 UDP 数据包吗?
【发布时间】:2011-06-02 14:36:25
【问题描述】:

我在一台 Linux 机器 server1 上有一个 Python 进程,它接收和处理原始 UDP 数据包。我想要另一台 Linux 机器 server2 能够监听 server1 正在接收的相同 UDP 数据包。

是否有任何 Python 解决方案能够嗅探发往另一台 (Linux) 机器的 UDP 数据包?

【问题讨论】:

  • 流量通过几个非托管交换机,因此我无法从网络方面做太多事情。在同一台服务器上添加一个 python 进程怎么样:server1?是否可以让多个 Python 进程在同一台机器上的同一端口号上侦听相同的 UDP 数据包?
  • No- 只有单个进程可以监听套接字。但是您可以让某些东西监听套接字并将数据发送到多个其他子进程。在同一台机器或其他机器上。它是什么样的数据?
  • 这是一个UDP数据包,里面有大约150个文本字符。
  • 如果您想要不同机器上的进程(您认为一台机器无法完成所有工作),我会让一台 Linux 机器接收数据,并使用 iptables 将其发送到其他多台机器。也许到同一台机器上的不同插座。这是可能的,因为它的UDP。如果你想在同一台机器上做这一切,我会有一个进程,它产生连接PIPEs的子进程,绑定UDP套接字并将数据复制到每个子进程的管道;也许在一些输入验证之后。
  • 虽然我没有读完,但这可能会有所帮助:bjou.de/blog/2008/05/… 我认为您正在寻找--tee 标志/目标。

标签: python linux networking ubuntu network-programming


【解决方案1】:

如果您希望多台机器处理相同的数据,最好使用多播(如果您可以控制发送者和基础设施)

否则,http://sourceforge.net/projects/pylibpcap/ 将通过 python 启用数据包捕获。您仍然必须配置基础架构以将数据包发送到您想要嗅探它们的机器。通过 iptables(如果是 Linux 机器)或交换机上的镜像端口等。

编辑:

如果您想要不同机器上的进程(您认为一台机器无法完成所有工作),我会让一台 Linux 机器接收数据,并使用 iptables 将其发送到其他多台机器。也许到同一台机器上的不同插座。这是可能的,因为它的UDP。如果你想在同一台机器上进行所有操作,我将有一个进程,它使用连接的 PIPE 生成子进程,绑定 UDP 套接字并将数据复制到每个子进程的管道;也许经过一些输入验证

【讨论】:

  • +1:我忘了他在使用 UDP。多播可能是一个不错的选择
【解决方案2】:

这不取决于 Python,而是取决于您的网络架构。如果 server1 和 server2 通过交换机连接(可能是),那么您不能这样做,因为通过路由器的数据包将仅发送到请求的 IP。

首先,请告诉我们您的网络架构是如何组成的。 server1 和 server2 在哪里?怎么联系的?

您的问题解决方案既不依赖于您的操作系统,也不依赖于所使用的语言。 无论如何,您将您的问题标记为“linux”,所以我认为您熟悉该操作系统。 如果是这种情况,并且 server1 和 server2 通过同一个路由器访问 LAN,您可以评估在您的路由器上安装 linux 的可能性(查看openwrt),并从路由器本身执行嗅探和任何操作。

【讨论】:

  • +1 因为任何解决方案实际上都是关于网络架构,而不是编程......
  • 虽然 ARP 欺骗可以用来嗅探交换机。
  • 如果是管理型交换机,大部分都有镜像端口选项。您设置了一个镜像端口,并且可以从配置的镜像端口嗅探所有流量。
  • @Douglas Leeder。是的,它可以,但这不是一个合适的解决方案,而只是一个黑客。这样,两台服务器中的一台将像路由器本身一样运行..so..
【解决方案3】:

我也遇到过类似的问题,写了一个小python脚本来转发传入的udp数据包到多个主机。当然,这里的一个缺点是您丢失了原始 udp 数据包的源 IP。

import socket
import sys, time, string

def sendUDP(remotehost,remoteport,UDPSock,data):
    UDPSock.sendto( data, (remotehost,remoteport))

def serverLoop(listenport,remotes):
    # Set up socket
    UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    UDPSock.bind( ("0.0.0.0",listenport) )
    while 1:
        data, addr = UDPSock.recvfrom(1024)
        if not data: pass
        else:
            sys.stdout.write(".") ; sys.stdout.flush()
            # Send udp packet to remotes...
            for remote in remotes:
                if remote[0] == addr: pass
                else: sendUDP(remote[0],remote[1],UDPSock,data)
        time.sleep(0.001)

if __name__ == "__main__":
    if len(sys.argv) < 3:
        print "%s listenport remotehost1:port1 remotehostN:portN ..." % sys.argv[0]
        sys.exit(-1)
    listenport = int(sys.argv[1])
    print "Local foward port %d" % listenport
    remotes = []
    for pair in sys.argv[2:]:
        host,port = string.split(pair,":")
        remotes.append( (host,int(port)) )
        print "Adding remote forward %s:%s" % (host,port)
    print "Starting serverloop"
    serverLoop(listenport,remotes)

【讨论】:

  • 我写了类似的东西,但我确实失去了你所说的原始 IP。在我的情况下,我需要原始 IP,因为我需要返回通信。任何想法如何解决 IP 问题?
  • 刚刚注意到这段代码中的一个漏洞。您必须检查原始 ip 是否是遥控器中的地址之一:端口,否则您可能会有一个反馈循环,这会耗尽您的资源
  • @itgorilla,您将原始 IP 地址放入数据中; data = struct.pack("!LH",ip2long(addr),port) + data,然后在接收端解包。另一种方法是欺骗源地址,但需要超级用户权限。
  • 我认为我也应该这样做。谢谢!
  • 看看sk89q.com/2008/10/spoofing-a-udp-packet-in-python 请注意,您在使用 ip-spoofing 过滤路由器/防火墙时可能会遇到一些问题。
猜你喜欢
  • 2021-04-04
  • 2017-08-29
  • 1970-01-01
  • 2011-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多