2012-08-29 3 views
5

मैं प्रोस्कॉसिट मोड में रॉ सॉकेट के साथ एक प्रोग्राम लिख रहा हूं और मुझे कच्चे सॉकेट की आवश्यकता है जो मैं भेजता हूं। मुझे केवल ईथरनेट आरएक्स तार (टीएक्स तार नहीं) पर डेटा पढ़ने की जरूरत है। यह posible है?रॉ सॉकेट विचित्र मोड जो मैं लिखता हूं उसे स्नीफ नहीं करता

बहुत बहुत धन्यवाद।

+1

आप किस ओएस का उपयोग कर रहे हैं? – Eloff

+0

मैं लिनक्स का उपयोग कर रहा हूं। –

+0

क्या आप दोनों एक ही मशीन पर भेज रहे हैं और स्नीफिंग कर रहे हैं? ये एक समस्या है। इसके लिए आपको 2 मशीनों की आवश्यकता होगी। – Matt

उत्तर

6

समाधान पैकेट में देखने के लिए है यदि यह एक PACKET_OUTGOING है। इस विकल्प का उपयोग करके आप ईथरनेट टीएक्स तार और आपके द्वारा आरएक्स तार से पढ़े गए पैकेट में रखे पैकेट को अलग कर सकते हैं।

ओपन अनेक मोड में सॉकेट:

char* i = "eth0"; 
int fd; 
struct ifreq ifr; 
struct sockaddr_ll interfaceAddr; 
struct packet_mreq mreq; 

if ((fd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL))) < 0) 
    return -1; 

memset(&interfaceAddr,0,sizeof(interfaceAddr)); 
memset(&ifr,0,sizeof(ifr)); 
memset(&mreq,0,sizeof(mreq)); 

memcpy(&ifr.ifr_name,i,IFNAMSIZ); 
ioctl(fd,SIOCGIFINDEX,&ifr); 

interfaceAddr.sll_ifindex = ifr.ifr_ifindex; 
interfaceAddr.sll_family = AF_PACKET; 

if (bind(fd, (struct sockaddr *)&interfaceAddr,sizeof(interfaceAddr)) < 0) 
    return -2; 


mreq.mr_ifindex = ifr.ifr_ifindex; 
mreq.mr_type = PACKET_MR_PROMISC; 
mreq.mr_alen = 6; 

if (setsockopt(fd,SOL_PACKET,PACKET_ADD_MEMBERSHIP, 
    (void*)&mreq,(socklen_t)sizeof(mreq)) < 0) 
     return -3; 
//... 

और पढ़ें। अब, हम आरएक्स और टीएक्स ईथरनेट तार के बीच अंतर कर सकते हैं:

unsigned char buf[1500]; 
struct sockaddr_ll addr; 
socklen_t addr_len = sizeof(addr); 
n = recvfrom(fd, buf, 2000, 0, (struct sockaddr*)&addr, &addr_len); 
if (n <= 0) 
{ 
    //Error reading 
} 
else if (addr.sll_pkttype == PACKET_OUTGOING) 
{ 
    //The read data are not writing by me. 
    //Use only this data to copy in the other network. 
} 

और यह सब कुछ है। इसका उपयोग करके मैं जो डेटा लिखता हूं उसे पढ़ता नहीं हूं। जब मैं नेटवर्क 2 नेटवर्क के 1 फ्रेम और नेटवर्क 2 फ्रेम नकल दुर्भाग्य से नेटवर्क के 1.

0

आप आसानी से उन चीजों के लिए फ़िल्टर कर सकते हैं जो आपके आईपी पते से आए थे और उन्हें अपनी सूची से बाहर कर दें।

+0

हमारे पास दो नेटवर्क हैं और दो ईथरनेट डिवाइस (eth0 और eth1) वाला पीसी है। पहला नेटवर्क और दूसरे नेटवर्क के साथ दूसरा नेटवर्क कनेक्ट है। हम स्तर 2 पर एक सॉफ्टवेयर पुल बनाना चाहते हैं; विशिष्ट मोड में कच्चे सॉकेट का उपयोग करके हम नेटवर्क 1 के सभी ट्रैफिक को पढ़ते हैं और इसे नेटवर्क 2 और वाइसवर्सा में कॉपी करते हैं। यह सब एक अनंत लूप में खत्म होता है क्योंकि हम नेटवर्क 1 पर कॉपी किए गए फ्रेम नेटवर्क 2 पर प्रतिलिपि बनाते हैं और नेटवर्क 1 पर प्रतिलिपि बनाते हैं ... हमें उन फ्रेमों को स्नीफ करने की आवश्यकता नहीं होती है जिन्हें हम लिखते हैं और यह फ्रेम परत 2 (मैक के साथ) पर हैं और पूरी मशीन में किसी भी मशीन से हैं। –

+0

क्या आप बस मैक स्तर पर अपना फ़िल्टरिंग नहीं कर सकते हैं?मैक पते को देखने के लिए बहुत मुश्किल नहीं है और जिन्हें आप जानते हैं उन्हें छोड़ दें। मैं क्या खो रहा हूँ? – kmort

+0

यह सॉफ्टवेयर किसी रेडियो लिंक के माध्यम से नेटवर्क के बीच एक पुल करने के लिए उपयोग किया जाता है। नेटवर्क 1 में पढ़ा गया पैकेट अन्य कंप्यूटर (एक यूडीपी कनेक्शन में पैकेट) के लिए एक रेडियो लिंक के माध्यम से भेजता है, अनपॅकेट और नेटवर्क 2 (और वाइसवर्सा) में लिखता है। इसलिए, मैं लिनक्स ब्रिजिंग क्षमताओं का उपयोग नहीं कर सकता :-(मुझे विश्वास है ... –

3

आपको लगता है कि आने वाले पैकेट के अनुरूप BPF (BSD पैकेट फ़िल्टर) फ़िल्टर बनाना होगा:

/* To obtain the BPF filter corresponding to incoming traffic: 
* sudo tcpdump -dd -i eth0 dst host YOUR_IP_ADDRESS and not src host YOUR_IP_ADDRESS 
* The filter given below is what i get on my local machine (192.168.1.7): 
* sudo tcpdump -dd -i eth0 dst host 192.168.1.7 and not src host 192.168.1.7 
*/ 
struct sock_filter incoming_filter[] = {  
    { 0x28, 0, 0, 0x0000000c }, 
    { 0x15, 0, 4, 0x00000800 }, 
    { 0x20, 0, 0, 0x0000001e }, 
    { 0x15, 0, 9, 0xc0a80107 }, 
    { 0x20, 0, 0, 0x0000001a }, 
    { 0x15, 7, 6, 0xc0a80107 }, 
    { 0x15, 1, 0, 0x00000806 }, 
    { 0x15, 0, 5, 0x00008035 }, 
    { 0x20, 0, 0, 0x00000026 }, 
    { 0x15, 0, 3, 0xc0a80107 }, 
    { 0x20, 0, 0, 0x0000001c }, 
    { 0x15, 1, 0, 0xc0a80107 }, 
    { 0x6, 0, 0, 0x0000ffff }, 
    { 0x6, 0, 0, 0x00000000 }, 
}; 

int s; 
struct sockaddr_ll sock_address; 
struct sock_fprog prog; 

/* Init the program filter */ 
prog.len = 14; 
prog.filter = incoming_filter; 

और फिर अपने रॉ सॉकेट, और बाँध और ...:

/* Create the raw socket */ 
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 
if (s < 0) 
{ 
    /* Error handling */ 
} 

/* Build our socket */ 
sock_address.sll_family = AF_PACKET; 
sock_address.sll_protocol = htons(ETH_P_IP); 
sock_address.sll_ifindex = if_nametoindex(your_interface_name); 

/* Bind */ 
if (bind(s, (struct sockaddr*)&sock_address, sizeof(sock_address)) < 0) 
{ 
    /* Error handling */ 
} 

/* Apply the filter */ 
if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0) 
{ 
    /* Error handling */ 
} 

/* Infinite listen loop */ 
while (1) 
{ 

    /* Handle received packet */ 
} 

संपादित करें: यदि आप मैक पते द्वारा फ़िल्टर करना चाहते हैं, तो यह आसान है, इस तरह अपना फ़िल्टर उत्पन्न करें (मैं यहां अपना मैक पता उपयोग करता हूं):

sudo tcpdump -dd -i eth0 ether dst 00:0f:b0:68:0f:92 and not ether src 00:0f:b0:68:0f:92 
{ 0x20, 0, 0, 0x00000002 }, 
{ 0x15, 0, 7, 0xb0680f92 }, 
{ 0x28, 0, 0, 0x00000000 }, 
{ 0x15, 0, 5, 0x0000000f }, 
{ 0x20, 0, 0, 0x00000008 }, 
{ 0x15, 0, 2, 0xb0680f92 }, 
{ 0x28, 0, 0, 0x00000006 }, 
{ 0x15, 1, 0, 0x0000000f }, 
{ 0x6, 0, 0, 0x0000ffff }, 
{ 0x6, 0, 0, 0x00000000 }, 
+0

हम मैक पते के साथ लेयर 2 में काम कर रहे हैं। हमारे पास आईपी एड्रेस नहीं है। –

+0

@ जोसेमरिया बी: वैसे यह कुछ भी नहीं बदलेगा! बस अपने होस्ट मैक एड्रेस द्वारा फ़िल्टर करें। मेरा संपादन देखें – TOC

+0

बहुत धन्यवाद। मुझे लगता है इस मामले के लिए PACKET_OUTGOING समाधान का उपयोग करना आसान है (Merci beaucoup। Je pense que c'est plus facile à utiliser la solution PACKET_OUTGOING pour ce cas :-)) –

0

मैं पाश से बचने, लिनक्स एक रॉ सॉकेट के लिए बाहर जाने वाले पैकेट प्राप्त नहीं निर्दिष्ट करने के लिए किसी भी विकल्प प्रदान नहीं करता है।

यदि लिनक्स कर्नेल को पुनर्निर्माण की अनुमति है, तो मैं कर्नेल को केवल packet_socket_type.patch के साथ पैच करने का सुझाव दूंगा।

और उपयोगकर्ता प्रोग्राम पर, आप निर्दिष्ट करते हैं कि आप किस प्रकार का पैकेट प्राप्त करना चाहते हैं।

int mask=0; 
mask = PACKET_MASK_ANY & ~(1<<PACKET_OUTGOING) & ~(1 << PACKET_LOOPBACK); 
setsockopt(raw_sock, SOL_PACKET, PACKET_RECV_TYPE, &mask, sizeof(mask)); 

आईएमओ, यह वह समाधान है जो वास्तव में समस्या हल करता है।

संबंधित मुद्दे