如何监听通过UDP发送到IP的数据?

如何监听通过UDP发送到IP的数据?,udp,Udp,有一个远程系统通过UDP向我的服务器发送数据,我想“捕获”这些数据,它被发送到非特定端口。我知道发件人(IP:Port),但他们发送到的端口是可变的 我不知道应该用哪种语言来做,但我愿意接受任何语言。服务器运行CentOS。最终目标是接收数据,然后通过PHP进行输出处理 (我应该澄清我选择发送的数据,这不是恶意的!) 编辑:我应该提到的是,端口是可变的这一事实不是我的问题,我不知道如何捕获通过UDP发送到任何端口的任何数据,我仍然需要知道如何捕获和处理数据,一旦我可以指示它 您可以编写一个ipt

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

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

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


编辑:我应该提到的是,端口是可变的这一事实不是我的问题,我不知道如何捕获通过UDP发送到任何端口的任何数据,我仍然需要知道如何捕获和处理数据,一旦我可以指示它

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

如果您正在与服务器顶嘴,则必须使用NAT表,以便在返回路径上进行正确的重写。在任何情况下,这样做也可能很方便,即使不是必需的,因为这样您就不必做任何事情来让您的侦听器不感到惊讶,因为它正在为一个它没有侦听的端口接收数据包

一旦流量到达单个端口,就可以编写一个简单的UDP服务器实现,如PHP手册中的实现:

您需要使用。有了这个库,就可以很容易地完成您想要完成的任务


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

我最近也做了类似的事情,用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
#/usr/bin/python
导入套接字、系统、io
从结构导入*
从时间导入本地时间,strftime
#-------------------------------------------------------------------------------
类ETHHeader:#以太网头
定义初始值(self,s):
数据=s.read(14)
hdr=解包(“!6s6sH”,数据)
self.destination_addr=数据[0:6]#mac地址
self.source_addr=数据[6:12]#mac地址
self.protocol=socket.ntohs(hdr[2])
def src_地址(自身):
将地址返回到地址str(self.srouce\u addr)
def dst_地址(自身):
将地址返回到地址str(self.destination\u addr)
def is_IP(self):返回self.protocol==8
#将以太网地址的6个字符字符串转换为破折号分隔的十六进制字符串
def地址至地址(a):
b=“%.2x:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x”%(作战需求文件(a[0])、作战需求文件(a[1])、作战需求文件(a[2])\
作战需求文件(a[3])、作战需求文件(a[4])、作战需求文件(a[5]))
返回b
#-------------------------------------------------------------------------------
IPHeader类:
定义初始值(self,s):
iph=拆包(“!BBHHBBH4S”,s.read(20))
self.protocol=iph[6]
self.src_addr=socket.inet_ntoa(iph[8]);
self.dst_addr=socket.inet_ntoa(iph[9]);
定义(自我):
返回“(“+self.proto()+”+self.src_addr+”->“+self.dst_addr+”)
def proto(自我):
返回{6:“TCP”,1:“ICMP”,17:“UDP”}.get(self.protocol,“?”)
#-------------------------------------------------------------------------------
UDPHeader类:
定义初始值(self,s):
hdr=拆包(“!hhh”,s.read(8))
self.source_port=hdr[0]
self.destination_port=hdr[1]
self.length=hdr[2]
self.checksum=hdr[3]
#-------------------------------------------------------------------------------
尝试:
#s=socket.socket(socket.AF_INET、socket.SOCK_RAW、socket.IPPROTO_UDP)
#使用此选项而不是上述选项,我们将得到:
#还有传入的数据包。
#作为接收数据包一部分的以太网报头。
#TCP,UDP。。。
s=socket.socket(socket.AF_数据包,socket.SOCK_原始,socket.ntohs(0x0003))
除socket.error外,消息:
打印“无法创建套接字。错误代码:”+str(消息[0])+“消息”+msg[1]
sys.exit()
#-------------------------------------------------------------------------------
def_端口之间的通信(udp_头,端口):
src=udp_头。源_端口
dst=udp_头。目的地_端口
在端口中返回src,在端口中返回dst
ip之间的def通信(ip头,ip):
src=ip_头.src_地址
dst=ip_头.dst_地址
返回ips中的src和ips中的dst
#-------------------------------------------------------------------------------
尽管如此:
数据包=s.recvfrom(65535)#缓冲区大小
数据=io.BytesIO(数据包[0])
eth=ETHHeader(数据)
如果不是eth.is_IP():
持续
iph=IPHeader(数据)
udph=UDPHeader(数据)
如果IP之间没有通信(iph,[“192.168.1.3”,“192.168.1.102”):
持续
如果iph.proto()!=“UDP”:
持续
##要按端口进行筛选,请执行以下操作:
#如果udph.source\u端口!=
#继续
time=localtime()
timestr=strftime(“%H:%M:%S”,时间)
a=iph.src\u addr
b=iph.dst\U地址
方向=“->”
如果a>b:
tmp=a
a=b
b=tmp

direction=“对于您可以使用一些防火墙规则解决的问题来说,这似乎太过分了。如果我理解正确,他/她需要“捕获”“正在发送到他/她的服务器的数据。我不知道更简单的方法。如果他/她只需要编写一个服务器软件来处理UDP数据包,我同意:在任何语言上编写一个小小的UDP守护程序就足够了。我读“capture”仅仅是为了表示他们不知道它将到达哪个端口。不过,这两种解释似乎都是有效的,如果他们也需要让它到达最初的目的地,那么pcap可能是最简单的方法(除非他们使用的是OpenFlow路由器,在这种情况下,它可以为您完成繁重的跨越和破坏任务),您能用iptables复制流量吗?我已经理解了这个问题,它要求原始数据保持不变。这似乎是个好主意,我来看看!我仍然需要知道如何处理数据,不过,我更新了我的问题!