2009-05-11 16 views
6

मैं एक टीसीपी सर्वर लिख रहा हूं जिसे यह जानने की जरूरत है कि प्रत्येक कनेक्शन किस इंटरफेस से आया है। मैं इस इंटरफ़ेस का उपयोग करने के लिए पता/सबनेट का उपयोग नहीं कर सकता, क्योंकि उसी पते/सबनेट मानों के साथ इंटरफेस हो सकता है। यह लिनक्स आधारित है, और कोड पोर्टेबल होने की कोई आवश्यकता नहीं है।मैं एक टीसीपी सॉकेट से जुड़े इंटरफ़ेस नाम/अनुक्रमणिका कैसे प्राप्त कर सकता हूं?

मैं सभी इंटरफेस, या इंडेक्स द्वारा एक इंटरफ़ेस प्राप्त करने के लिए सभी कार्यों को ढूंढ सकता था। मुझे एक स्वीकृत टीसीपी सॉकेट से जुड़े इंटरफेस को पाने का कोई तरीका नहीं मिला।

कोई भी विचार? मुझे कुछ याद आया है?

संपादित करें: दोहराने के लिए, मेरे मामले में आईपी पते अद्वितीय नहीं हैं। न तो गंतव्य पते (सर्वर स्वयं) और न ही स्रोत पते (ग्राहक)। हां, यह एक बहुत चरम आईपी योजना है।

+0

यहां केवल सही उत्तर दिया गया है, यह देखते हुए कि आप अपने सर्वर में जोड़ने के लिए कोड ढूंढ रहे हैं, उपयोगकर्ता 1 में से एक है। मैंने इसका परीक्षण किया है, और यह काम करता है - आपको इसे स्वीकार करना चाहिए। Http: // stackoverflow भी देखें।कॉम/प्रश्न/43659634/खोज-द-इंटरफ़ेस-द्वारा-एक-कनेक्टेड-सॉकेट/43663713 # 43663713 – EML

उत्तर

0

गंतव्य पते पर देखें।

प्रत्येक इंटरफ़ेस आम तौर पर एक अद्वितीय पते से जुड़ा होता है। यदि एकाधिक इंटरफेस एक साथ बंधे होते हैं, तो इससे कोई फर्क नहीं पड़ता कि इसका उपयोग किसने किया था।

इसका एकमात्र अपवाद है, आईपीवी 6 एनाकास्ट का उपयोग करते समय, लेकिन फिर भी, आप एक ही आईपी के साथ एक ही होस्ट पर आमतौर पर एकाधिक इंटरफेस नहीं रखेंगे।

+0

इस मामले में, इंटरफेस अद्वितीय पते से बंधे नहीं हैं। वे या तो बंधे नहीं हैं। वे विभिन्न नेटवर्क से जुड़े हुए हैं, हालांकि उनके पास ओवरलैपिंग/समान आईपी हैं। –

+0

यदि आपके पास टीसीपी कनेक्शन है, तो आपके पास एक आईपी पता होना चाहिए। आपको किसी विशेष पते पर सॉकेट बांधना नहीं है, लेकिन आपके इंटरफ़ेस को – JimB

+0

की आवश्यकता है हां, कनेक्शन में आईपी पता है, लेकिन यह अद्वितीय नहीं है। यह उस इंटरफ़ेस के लिए अद्वितीय नहीं है, और यह उस नेटवर्क के लिए अद्वितीय नहीं है। मुझे सॉकेट से इंटरफ़ेस प्राप्त करने के लिए वास्तव में एक तरीका चाहिए। –

1

मुझे लगता है कि आने वाले कनेक्शन में स्वीकार करने के बाद getockname() का उपयोग करना हो सकता है जो आप बाद में हो सकते हैं। दो फ़ंक्शन getockname() और getpeername() क्रमशः स्थानीय और दूरस्थ पते प्राप्त करते हैं कि एक सॉकेट बाध्य है। दोनों को पूरी तरह से जुड़े टीसीपी सॉकेट के लिए मान्य होना चाहिए।

संपादित करें: हालांकि यह पृष्ठ पृष्ठ के अनुसार ओपनबीएसडी के लिए सच प्रतीत होता है, लिनक्स मैन पेज काफी अलग है और इसलिए लिनक्स पर स्वीकृति() स्वीकार करने के बाद हो जाता है() लगभग निश्चित रूप से अनुपयोगी है। सब कुछ जांचने की बजाय मेरी याददाश्त का उपयोग करने के लिए मुझे सिखाता है। श्वास

+0

असल में, मैंने कोशिश की और यह समाधान लिनक्स और विंडोज – thang

+0

गलत 'नाम' में काम करता है - यह * पता * देता है। ओपी इंटरफेस नाम चाहता है, यानी। eth0/आदि। चूंकि glibc दस्तावेज़ कहते हैं, "सॉकेट पते से निपटने के लिए कार्यों और प्रतीकों का नाम असंगत रूप से नामित किया गया था, कभी-कभी 'नाम' शब्द का उपयोग करते हुए, और कभी-कभी 'पता' का उपयोग करते हुए। – EML

2

कर्नेल रूटिंग तालिका तय करता है कि कौन सा इंटरफ़ेस एक पैकेट भेजने के लिए है, इसलिए बॉन्ड डिवाइस की क्षमता। "लिनक्स सॉकेट प्रोग्रामिंग, वॉरेन डब्ल्यू गे" के माध्यम से एक सरसरी नज़र से पता चलता है कि एक इंटरफ़ेस निर्दिष्ट करना बुरा है, और कर्नेल (फ़ायरवॉल, अग्रेषण) की गतिशीलता के कारण यह अधिक जटिल है।

मैं आपकी आईपी योजना को बदलने का सुझाव दूंगा कि आईपी सूचना आपको उसी तरह से देखकर अपने इंटरफ़ेस को बताती है, अन्यथा आप पैर डिजाइन के अनुसार स्वयं को शूटिंग कर रहे हैं।

1) टीसीपी सत्र से आई पी जानकारी 2) लुक जो इंटरफेस (रों) इस के लिए

मैं हालांकि कर्नेल एपीआई में देख रखेंगे मान्य हो सकता है प्राप्त करें। आपको यह जानने की आवश्यकता नहीं है, अच्छे कारणों के लिए अमूर्तता है।

अतिरिक्त सोचा इस पर विचार, ऐसा लगता है कि अगर दोनों इंटरफेस एक ही आईपी का उपयोग फिर वहाँ एक ग्राहक पता श्रेणी मार्ग अंतर (अन्यथा दोनों इंटरफेस का इस्तेमाल किया जाएगा) होना चाहिए। आपका सर्वर क्लाइंट आईपी

+0

क्लाइंट आईपी भी ओवरलैप कर सकते हैं। अंतर जो इन आईपी को ओवरलैप करने की अनुमति देता है वह वीएलएएन आईडी है। जहां तक ​​मुझे पता है, यह भी पहुंच योग्य नहीं है। –

+0

आपको एक ऐसी स्थिति मिल सकती है जहां आप इंटरफ़ेस निर्धारित करने के लिए परिस्थिति संबंधी साक्ष्य का उपयोग नहीं कर सकते हैं। मुझे नहीं लगता कि एक तरीका होगा, क्योंकि इंटरफ़ेस कर्नेल से अधिक अनुप्रयोगों से सार का प्रकार है। आप अपने कर्नेल को/proc/tcp_sessions_to_devs या कुछ के माध्यम से कुछ डेटा प्रदान करने के लिए संशोधित कर सकते हैं, लेकिन यह बहुत ही - erm-desperate है? –

+0

एक और विचार। वायरसहार्क का उपयोग करने वाले इंटरफ़ेस को इंटरफ़ेस में देखने की कोशिश कर रहा है (libpcap) और देखें कि iftop का स्रोत किसी डिवाइस पर सत्रों को कैसे समझाता है। दिलचस्प हो सकता है। –

4

के आधार पर रूटिंग तालिका की जांच कर सकता है सामान्य रूप से, आपको यह जानने की आवश्यकता नहीं है कि पैकेट को किस इंटरफ़ेस पर भेजा/प्राप्त किया जा रहा है; वह कर्नेल की रूटिंग टेबल की नौकरी है। सॉकेट के लिए इंटरफ़ेस को ढूंढना मुश्किल है क्योंकि वास्तव में कोई प्रत्यक्ष संबंध नहीं है। राउटिंग जानकारी के आधार पर पैकेट का मार्ग सॉकेट के जीवनकाल में बदल सकता है।

डेटाग्राम (यूडीपी) सॉकेट के लिए, आप getsockopt(s, IPPROTO_IP, IP_PKTINFO, ...) का उपयोग करने में सक्षम हो सकते हैं; getsockopt(2) और ip(7) देखें।

स्ट्रीम (टीसीपी) सॉकेट के लिए, एक विकल्प कई सुनवाई सॉकेट खोलने के लिए हो सकता है, सिस्टम पर प्रत्येक इंटरफ़ेस के लिए, और setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, ...) का उपयोग प्रत्येक इंटरफ़ेस को बाध्य करने के लिए करें; setsockopt(2) और socket(7) देखें।

+0

हां, प्रत्येक इंटरफ़ेस के लिए अलग सॉकेट सेट करना काम करेगा, लेकिन कई दर्जन इंटरफ़ेस देख रहे हैं और उन्हें लाया जाता है और गतिशील रूप से नीचे ले जाया जाता है, यह कुछ है जिसे मैं टालना चाहता हूं। –

0

जाहिर है कुछ नहीं मैं बहुत गहराई से देखा है, अकेले करने की कोशिश की है, इस टोकरी "तो यह सिर्फ काम कर सकते हैं पागल" के लिए एक हो सकता है ...

यदि यह वास्तव में केवल कभी के लिए होने जा रहा लिनक्स, आप कस्टम netfilter मॉड्यूल लिख सकते हैं जो आने वाले कनेक्शन और नोट्स को ट्रैक करता है जो वे इंटरफ़ेस पर आते हैं, और आपके सर्वर एप्लिकेशन को पढ़ने के लिए कहीं भी जानकारी लिखते हैं।

0

नेटफिल्टर मॉड्यूल लिखने के लिए कियरन का सुझाव शायद प्रयास करने का एक तरीका है, लेकिन मैं इस समाधान के लिए अपना पहला कर्नेल मॉड्यूल लिखने से बचना चाहता हूं।

मैं स्रोत एनएटी का उपयोग करने और कनेक्शन स्रोत के साथ संबंध के कनेक्शन के स्रोत बंदरगाह का अनुवाद करने का एक और विकल्प लेकर आया हूं। मैं प्रत्येक नेटवर्क के लिए पोर्ट रेंज असाइन कर सकता हूं और इसे सर्वर में देख सकता हूं। एकमात्र समस्या यह है कि iptables में स्रोत एनएटी POSTROUTING श्रृंखला में किया जाता है, और मुझे यकीन नहीं है कि यह उस होस्ट द्वारा स्वीकार किए गए कनेक्शन के लिए उपयोग किया जाता है, इसलिए मुझे किसी अन्य सर्वर का उपयोग करने की आवश्यकता हो सकती है।

यहाँ कोई आसान समाधान, बहुत बुरा मैं इंटरफ़ेस नाम/सॉकेट से सूचकांक नहीं मिल सकता है ...

+0

एक और नेटफिल्टर विकल्प ट्रैफिक को अतिरिक्त स्थानीय इंटरफेस के लिए अग्रेषित करना है जो विशिष्ट आईपी एड्रेस के साथ स्थापित किए गए हैं। – Bell

0

मैं एक और उत्तर और Wireshark और iftop के स्रोत के माध्यम से देखने के बाद एक संभावित समाधान द्वारा जोड़ा जा रहा है जो प्रतीत होता है कि अप्रत्यक्ष रूप से समान कार्यक्षमता है।

मुझे लगता है कि आप इंटरफेस पर स्नीफ करने के लिए libpcap का उपयोग कर सकते हैं। मान लीजिए कि आप टीसीपी/आईपी सत्र के कुछ अनूठे हिस्से की पहचान कर सकते हैं, फिर आप फ़िल्टर और सत्र ट्रैकिंग का उपयोग करके इसे आसानी से इंटरफेस पर ट्रैक कर सकते हैं।

नहीं गिरी मॉड्यूल (और यह धागे के साथ अच्छा खेलता है) कुछ सरल स्रोत

http://www.ex-parrot.com/pdw/iftop/ libpcap के लिए www.tcpdump.org/ पर एक नज़र है करने के लिए

मुझे लगता है कि आप VLANs मिलान करने के लिए सक्षम हो जाएगा इसका भी उपयोग कर रहे हैं।

इसके अलावा wireshark डिबगिंग के लिए उपयोगी हो सकता है। उम्मीद है की यह मदद करेगा! यह मेरे दिमाग पर रहा है।

+0

हाँ, यह एक और विकल्प की तरह लगता है। आपके परिश्रम के लिए धन्यवाद! –

2

टीसीपी कनेक्शन के स्थानीय छोर के आईपी प्राप्त करने के लिए getsockname() का उपयोग करें। फिर getifaddrs() का उपयोग इसी इंटरफेस को खोजने के लिए:

struct sockaddr_in addr; 
struct ifaddrs* ifaddr; 
struct ifaddrs* ifa; 
socklen_t addr_len; 

addr_len = sizeof (addr); 
getsockname(sock_fd, (struct sockaddr*)&addr, &addr_len); 
getifaddrs(&ifaddr); 

// look which interface contains the wanted IP. 
// When found, ifa->ifa_name contains the name of the interface (eth0, eth1, ppp0...) 
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) 
{ 
    if (ifa->ifa_addr) 
    { 
     if (AF_INET == ifa->ifa_addr->sa_family) 
     { 
      struct sockaddr_in* inaddr = (struct sockaddr_in*)ifa->ifa_addr; 

      if (inaddr->sin_addr.s_addr == addr.sin_addr.s_addr) 
      { 
       if (ifa->ifa_name) 
       { 
        // Found it 
       } 
      } 
     } 
    } 
} 
freeifaddrs(ifaddr); 

से ऊपर सिर्फ एक गंदा उदाहरण है, कुछ संशोधनों की जरूरत है:

  1. लापता त्रुटि जाँच
  2. IPv6 का समर्थन जोड़े
+0

मैंने इसका परीक्षण किया है, और यह काम करता है - धन्यवाद – EML

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