2010-11-02 88 views
2

有一個遠程系統通過UDP向我的服務器發送數據,我想「捕獲」這些數據,並將它發送到非特定的端口。我知道發件人(IP:端口),但他們發送給的端口是可變的。如何收聽通過UDP發送到IP的數據?

我不知道應該用哪種語言來完成,但我向任何人開放。服務器運行CentOS。最終目標是接收數據,然後通過PHP輸出處理。

(!我要澄清我選擇要發送的數據,它不是惡意的)

編輯:我要提的是,該端口是可變的,不是我的問題,我不知道如何捕獲任何數據通過UDP發送到任何端口,我仍然需要知道如何捕獲和處理數據,一旦我可以指示它。

+0

您是否需要捕獲已發送到服務器的信息?或者你需要編寫一個程序來監聽傳入的數據包(如UDP服務器)? – 2010-11-02 17:13:46

回答

2

您只需編寫一個iptables規則將所有流量從該IP:端口轉發到系統上的給定端口,然後在該端口上監聽該數據。 (您可能會發現CentOS IPTables manual有用)

如果您正在與服務器通話,則必須使用NAT表,以便在返回路徑上進行正確的重寫。即使不需要,也可以在任何情況下方便地執行此操作,因爲那樣您就不必做任何事情來讓聽衆不會驚訝它正在接收它未在監聽的端口的數據包數據。

一旦你有一個端口上的流量登陸,你可以寫一個簡單的UDP服務器實現,像在PHP手冊:

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

+0

你可以用iptables複製流量嗎?正如我所瞭解的問題,它需要原始數據保持不變 – 2010-11-02 17:04:13

+0

這似乎是一個好主意,我會看看!我仍然需要知道如何處理數據,但我更新了我的問題!謝謝。 – sam 2010-11-02 17:06:11

+0

人,我不明白這個問題。我不相信iptables中有任何「跨度」功能,但我從來沒有嘗試過,所以如果這是海報正在尋找的功能,可能會有一些功能。 – 2010-11-02 17:07:24

0

您需要使用libpcap。藉助該庫,您可以非常直接地完成您想要的任務。

您肯定可以使用C/C++。但我猜想其他語言也有約束力,因爲它是一個非常受歡迎的圖書館。

+0

對於可以通過一些防火牆規則解決的問題,這似乎過分了。 – 2010-11-02 17:03:54

+0

如果我理解正確,他/她需要「捕捉」正在發送到他/她的服務器的數據。不知道這樣做的更簡單的方法。如果他/她只需要編寫一個服務器軟件來處理UDP數據包,我同意:在任何語言上編寫一個小的UDP守護進程將綽綽有餘。 – 2010-11-02 17:11:05

+0

我讀「捕獲」僅僅意味着他們不知道它將登陸什麼港口。這兩種解釋似乎都是有效的,但如果它們也需要讓它着陸在原來的位置,那麼pcap可能是最簡單的方法(除非它們使用OpenFlow路由器,在這種情況下,它可以完成跨越爲你搗蛋) – 2010-11-02 17:17:16

0

我最近一直在做類似的事情,在蟒蛇結帳驗證碼:

#!/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的大部分信息。