【问题标题】:How to listen to data sent via UDP to IP?如何监听通过 UDP 发送到 IP 的数据?
【发布时间】:2013-08-13 07:04:37
【问题描述】:

有一个远程系统通过 UDP 向我的服务器发送数据,我想“捕获”这些数据,它被发送到非特定端口。我知道发件人(IP:端口),但他们发送到的端口是可变的。

我不知道应该使用哪种语言,但我愿意接受任何语言。服务器运行 CentOS。最终目标是接收数据,然后通过 PHP 处理输出。

(我应该澄清我选择发送的数据,它不是恶意的!)

编辑:我应该提到端口可变的事实不是我的问题,我不知道如何捕获通过 UDP 发送到 anyany 数据端口,我仍然需要知道如何在可以引导数据后捕获和处理数据。

【问题讨论】:

  • 您是否需要捕获已经发送到服务器的信息?或者您需要编写一个程序来监听传入的数据包(如 UDP 服务器)?

标签: udp


【解决方案1】:

您可以编写一个 iptables 规则,将来自该 IP:Port 的所有流量转发到系统上的给定端口,然后在该端口上侦听该数据。 (你可能会发现 CentOS IPTables manual 很有用)

如果您要与服务器对话,则必须使用 NAT 表,以便在返回路径上进行正确的重写。在任何情况下这样做也可能很方便,即使不是必需的,从那时起,您不必做任何事情来让您的侦听器不会对它正在接收它未侦听的端口的数据包数据感到惊讶。

一旦流量登陆单个端口,您就可以编写一个简单的 UDP 服务器实现,就像 PHP 手册中的那样:

http://us3.php.net/manual/en/function.stream-socket-server.php

【讨论】:

  • 你能用 iptables 复制流量吗?据我了解,它要求原始数据保持不变
  • 这主意不错,我去看看!我仍然需要知道如何处理数据,我更新了我的问题!谢谢。
  • Hrm,我不明白这个问题。我不相信 iptables 中有任何“跨度”功能,但我从未尝试过,所以如果发帖人正在寻找这样的功能,可能会有一些类似的功能。
  • @citricsquid:一旦流量被重定向,您只需要编写一个标准的 UDP 侦听器 - 我确定您选择的语言中有一个套接字教程,其中包含一个简单的 UDP 服务器实现(我已经在此处添加了一个 PHP 链接)。
  • 嘿,所以我在 IPTables 中找不到任何关于如何根据到达的 IP 进行转发的信息。有任何想法吗?感谢到目前为止尼克的帮助:-)
【解决方案2】:

您需要使用libpcap。使用该库可以非常简单地完成您想要完成的工作。

您肯定可以将 C/C++ 与该库一起使用。但我猜也有其他语言的绑定,因为它是一个非常流行的库。

【讨论】:

  • 对于您可以通过一些防火墙规则解决的问题来说,这似乎有些过分了。
  • 如果我理解正确,他/她需要“捕获”发送到他/她的服务器的数据。不知道这样做的更简单的方法。如果他/她只需要编写一个服务器软件来处理 UDP 数据包,我同意:在任何语言上编写一个小 UDP 守护程序就足够了。
  • 我读到“捕获”只是为了表示他们不知道它将登陆哪个端口。不过,这两种解释似乎都是有效的,如果他们还需要让它降落在最初打算的地方,那么 pcap 可能是最简单的方法(除非他们使用的是 OpenFlow 路由器,在这种情况下它可以完成繁重的跨越和为你弄脏)
【解决方案3】:

我最近一直在做类似的事情,在python中查看这段代码:

#!/usr/bin/python

import socket, sys, io
from struct import *
from time import localtime, strftime

#-------------------------------------------------------------------------------
class ETHHeader: # ethernet header
  def __init__(self, s):
    data = s.read(14)
    hdr = unpack("!6s6sH", data)
    self.destination_addr = data[0:6]  # mac address
    self.source_addr      = data[6:12] # mac address
    self.protocol         = socket.ntohs(hdr[2])

  def src_addr(self):
    return addr_to_str(self.srouce_addr)

  def dst_addr(self):
    return addr_to_str(self.destination_addr)

  def is_IP(self): return self.protocol == 8

  #Convert a string of 6 characters of ethernet address into a dash separated hex string
  def addr_to_str (a) :
      b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (ord(a[0]), ord(a[1]) , ord(a[2]), \
                                         ord(a[3]), ord(a[4]) , ord(a[5]))
      return b

#-------------------------------------------------------------------------------
class IPHeader:
  def __init__(self, s):
    iph = unpack('!BBHHHBBH4s4s', s.read(20))
    self.protocol = iph[6]
    self.src_addr = socket.inet_ntoa(iph[8]);
    self.dst_addr = socket.inet_ntoa(iph[9]);

  def __str__(self):
    return "(" + self.proto() + " " + self.src_addr + " -> " + self.dst_addr + ")"

  def proto(self):
    return { 6: "TCP", 1: "ICMP", 17: "UDP" }.get(self.protocol, "???")

#-------------------------------------------------------------------------------
class UDPHeader:
  def __init__(self, s):
    hdr = unpack("!HHHH", s.read(8))
    self.source_port      = hdr[0]
    self.destination_port = hdr[1]
    self.length           = hdr[2]
    self.checksum         = hdr[3]

#-------------------------------------------------------------------------------
try:
  #s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
  # Using this instead of the above we will get:
  #   Also incoming packets.
  #   Ethernet header as part of the received packet.
  #   TCP, UDP, ...
  s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))
except socket.error, msg:
  print "Socket could not be created. Error Code : " + str(msg[0]) + ' Message ' + msg[1]
  sys.exit()

#-------------------------------------------------------------------------------
def communication_between_ports(udp_header, ports):
  src = udp_header.source_port
  dst = udp_header.destination_port
  return src in ports and dst in ports

def communication_between_ips(ip_header, ips):
  src = ip_header.src_addr
  dst = ip_header.dst_addr
  return src in ips and dst in ips

#-------------------------------------------------------------------------------

while True:
  packet = s.recvfrom(65535) # buffer size

  data = io.BytesIO(packet[0])
  eth  = ETHHeader(data)

  if not eth.is_IP():
    continue

  iph  = IPHeader(data)
  udph = UDPHeader(data)

  if not communication_between_ips(iph, ["192.168.1.3", "192.168.1.102"]):
    continue

  if iph.proto() != "UDP":
    continue

  ## To filter by port:
  #if udph.source_port != <PORT-YOU-WANT>
  #  continue

  time = localtime()
  timestr = strftime("%H:%M:%S", time)

  a = iph.src_addr
  b = iph.dst_addr
  direction = " -> "

  if a > b:
    tmp = a
    a = b
    b = tmp
    direction = " <- "

  print timestr + ": " + a + str(direction) + b

我只从每一层(ETH、IP、...)中提取我需要的数据,但您应该能够轻松扩展它。

大部分信息来自this blog post

【讨论】:

    猜你喜欢
    • 2015-01-06
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    相关资源
    最近更新 更多