如何收听通过UDP发送到IP的数据?
有一个远程系统通过UDP向我的服务器发送数据,我想“捕获”这些数据,并将它发送到非特定的端口。我知道发件人(IP:端口),但他们发送给的端口是可变的。如何收听通过UDP发送到IP的数据?
我不知道应该用哪种语言来完成,但我向任何人开放。服务器运行CentOS。最终目标是接收数据,然后通过PHP输出处理。
(!我要澄清我选择要发送的数据,它不是恶意的)
编辑:我要提的是,该端口是可变的,不是我的问题,我不知道如何捕获任何数据通过UDP发送到任何端口,我仍然需要知道如何捕获和处理数据,一旦我可以指示它。
您只需编写一个iptables规则将所有流量从该IP:端口转发到系统上的给定端口,然后在该端口上监听该数据。 (您可能会发现CentOS IPTables manual有用)
如果您正在与服务器通话,则必须使用NAT表,以便在返回路径上进行正确的重写。即使不需要,也可以在任何情况下方便地执行此操作,因为那样您就不必做任何事情来让听众不会惊讶它正在接收它未在监听的端口的数据包数据。
一旦你有一个端口上的流量登陆,你可以写一个简单的UDP服务器实现,像在PHP手册:
http://us3.php.net/manual/en/function.stream-socket-server.php
你可以用iptables复制流量吗?正如我所了解的问题,它需要原始数据保持不变 – 2010-11-02 17:04:13
这似乎是一个好主意,我会看看!我仍然需要知道如何处理数据,但我更新了我的问题!谢谢。 – sam 2010-11-02 17:06:11
人,我不明白这个问题。我不相信iptables中有任何“跨度”功能,但我从来没有尝试过,所以如果这是海报正在寻找的功能,可能会有一些功能。 – 2010-11-02 17:07:24
您需要使用libpcap。借助该库,您可以非常直接地完成您想要的任务。
您肯定可以使用C/C++。但我猜想其他语言也有约束力,因为它是一个非常受欢迎的图书馆。
对于可以通过一些防火墙规则解决的问题,这似乎过分了。 – 2010-11-02 17:03:54
如果我理解正确,他/她需要“捕捉”正在发送到他/她的服务器的数据。不知道这样做的更简单的方法。如果他/她只需要编写一个服务器软件来处理UDP数据包,我同意:在任何语言上编写一个小的UDP守护进程将绰绰有余。 – 2010-11-02 17:11:05
我读“捕获”仅仅意味着他们不知道它将登陆什么港口。这两种解释似乎都是有效的,但如果它们也需要让它着陆在原来的位置,那么pcap可能是最简单的方法(除非它们使用OpenFlow路由器,在这种情况下,它可以完成跨越为你捣蛋) – 2010-11-02 17:17:16
我最近一直在做类似的事情,在蟒蛇结帐验证码:
#!/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的大部分信息。
您是否需要捕获已发送到服务器的信息?或者你需要编写一个程序来监听传入的数据包(如UDP服务器)? – 2010-11-02 17:13:46