2009-02-18 19 views
16

इसे this earlier SO question की निरंतरता माना जा सकता है।लिनक्स: मैं एक विशिष्ट नेटवर्क इंटरफ़ेस का उपयोग करने के लिए कैसे मजबूर करूं?

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

  1. उपयोग करने के लिए इंटरफ़ेस का आईपी निर्धारित करें।
  2. रूट करने के लिए एक आईपी नीति नियम बनाएं सभी पैकेट इंटरफ़ेस से कि आईपी
  3. मार्ग के लिए एक और आईपी नीति नियम बनाने के लिए आने वाले सभी पैकेट कि आईपी से कि इंटरफेस
  4. प्रत्येक नियम के लिए एक डिफ़ॉल्ट अनुमार्गण तालिका सेट करें के लिए आ रहा

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

मेरे प्रश्न हैं:

  1. SO_BINDTODEVICE क्या मैं यहाँ करना चाहते हैं करता है? या यह कच्चे सॉकेट के लिए केवल प्रभावी है? किसी ने टिप्पणी की कि, "सॉकेट पर SO_BINDTODEVICE यह गारंटी नहीं देता है कि सॉकेट केवल उस भौतिक इंटरफ़ेस के तार/एंटीना पर आने वाले पैकेट प्राप्त करेगा।" यदि यह वास्तव में सच है, तो SO_BINDTODEVICE करता है?

  2. क्या ऐसा करने का कोई तरीका है कि स्थानीय आईपी को अद्वितीय नहीं होना चाहिए? यह इस तथ्य के अलावा कोई समस्या नहीं होगी कि एक इंटरफ़ेस पर DHCP सर्वर इसे एक आईपी आवंटित कर सकता है जो किसी अन्य इंटरफ़ेस द्वारा उपयोग में है, इस प्रकार रूटिंग तालिका को भ्रमित कर रहा है।

  3. मैं केवल एक विशिष्ट इंटरफ़ेस से प्रसारण कैसे प्राप्त करूं? एक विशिष्ट आईपी के लिए बाध्यकारी यह प्रसारण को अनदेखा करता है, जो समझ में आता है, लेकिन जो कुछ मैं ढूंढ रहा हूं वह काफी नहीं है।

मैं उबंटू 8.04 डब्ल्यू/लिनक्स कर्नेल 2.6.26 पर चल रहा हूं। दो अलग-अलग इंटरफेस के माध्यम से एक ही सबनेट को एक ही सबनेट तक पहुंचने में सक्षम होने के साथ-साथ एक गैर-विचारणीय आवश्यकता होती है, इस प्रकार इसे "अधिकतर नहीं" करने के लिए प्रतिरक्षा (ज्यादातर) प्रतिरक्षा होती है। :)

उत्तर

3

हार्ड-लड़े सप्ताहांत के बाद, मुझे एक ऐसा समाधान पेश करने में प्रसन्नता हो रही है जो मैंने पहले से ही लगभग शून्य परेशानी के साथ चर्चा की है।

एक sysctl net.ipv4.conf.all.rp_filter कि स्रोत सत्यापन निष्क्रिय करने के लिए 0 पर सेट किया जा सकता है कहा जाता है:

 
    rp_filter - INTEGER 
     2 - do source validation by reversed path, as specified in RFC1812 
      Recommended option for single homed hosts and stub network 
      routers. Could cause troubles for complicated (not loop free) 
      networks running a slow unreliable protocol (sort of RIP), 
      or using static routes. 

     1 - (DEFAULT) Weaker form of RP filtering: drop all the packets 
      that look as sourced at a directly connected interface, but 
      were input from another interface. 

     0 - No source validation. 

यह भी का उपयोग कर एक प्रति इंटरफ़ेस आधार पर सेट किया जा सकता/proc/sys/net/ipv4/conf/<interface>/rp_filter।

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

ब्रॉडकास्ट अभी भी उन कारणों से समस्याग्रस्त हैं जिन्हें मैं समझ नहीं पा रहा हूं, लेकिन मैं अंत में इस मुद्दे से संतुष्ट हूं और मुझे आशा है कि इससे दूसरों की मदद मिलेगी।

+0

'net.ipv4.conf.all.rp_filter' sysctl चर के लिए कोई IPv6 equivlant नहीं है; हालांकि netfilter के लिए 'rpfilter' मॉड्यूल के रूप में संबंधित कार्यक्षमता मौजूद है। यह [iptables-एक्सटेंशन] (http://ipset.netfilter.org/iptables-extensions.man.html) मैन पेज में प्रलेखित है। [Netfilter में rp_filter को स्थानांतरित करना] (http://www.strlen.de/talks/rpfilter.pdf) नोट करता है कि यह संभव है कि 'rp_filter' को पूरी तरह से भविष्य के कर्नेल में रूटिंग कैश कोड से हटा दिया जाए। –

4

मेरी सामान्य प्रश्न के लिए के रूप में, यह करने के लिए कुछ तरीके प्रतीत:

  • जटिल तरीका है कि प्रत्येक प्रक्रिया से अनुमार्गण तालिका में परिवर्तन और सहयोग शामिल है। इस तरह मैंने ऊपर वर्णित किया है। इसका एक फायदा यह है कि यह उपयोगकर्ताओं के स्थान से काम करता है। मैंने इस पर कुछ अतिरिक्त नोट्स रखे हैं और नीचे दिए गए मेरे विशिष्ट प्रश्नों का उत्तर दिया है।

  • एक कस्टम कर्नेल मॉडल लिखें जो रूटिंग तालिका को पूरी तरह से अनदेखा करता है, अगर SO_BINDTODEVICE सेट है। हालांकि, ग्राहक प्रक्रिया को अभी भी setsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev) पर कॉल करने की आवश्यकता है। यह विकल्प निश्चित रूप से दिल की बेहोशी के लिए नहीं है।

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

विकल्प 1 और 2 प्रक्रियाओं को ऑप्ट-इन करने के लिए प्रक्रियाओं की आवश्यकता होती है जैसा हम चाहते हैं। इसे एक गतिशील लाइब्रेरी बनाकर आंशिक रूप से कम किया जा सकता है जो सॉकेट बनाने के लिए सॉकेट() कॉल को हाइजैक करता है और फिर इसे डिस्क्रिप्टर लौटने से पहले डिवाइस पर तुरंत बांध देता है। यह अधिक जानकारी here में वर्णित है।

कुछ शोध करने और गूगलिंग के बहुत सारे करने के बाद, मैं कुछ निष्कर्ष निकाल सकता हूं कि लिनक्स कर्नेल 2.6.26 कैसे व्यवहार करता है। ध्यान दें कि ये शायद सभी कार्यान्वयन-विशिष्ट व्यवहार हैं, और शायद यहां तक ​​कि कर्नेल-विशिष्ट भी हैं। डेटा के अपने एकल बिंदु के आधार पर सुविधाओं को लागू करने का निर्णय लेने से पहले अपने स्वयं के मंच का परीक्षण करें।

  1. SO_BINDTODEVICE वास्तव में कम से कम यूडीपी के लिए, यह क्या कहते हैं क्या करता है।

  2. प्रत्येक इंटरफ़ेस के लिए अद्वितीय आईपी आवश्यक होने लगते हैं, क्योंकि हम रूटिंग टेबल का उपयोग कर रहे हैं। एक कस्टम कर्नेल मॉड्यूल इस प्रतिबंध को बाईपास कर सकता है।

  3. किसी विशिष्ट इंटरफ़ेस पर प्रसारण प्राप्त करने के लिए, डिवाइस को पहले SO_BINDTODEVICE का उपयोग करके बाध्य करें, और फिर सामान्य बाइंड() कॉल के साथ प्रसारण पते से जुड़ें। उपकरण बाध्यकारी किसी और चीज से पहले किया जाना चाहिए। फिर, सॉकेट केवल उस इंटरफ़ेस पर पहुंचने वाले प्रसारण प्राप्त करेगा।

मैंने पहली बार सॉकेट बनाने के द्वारा इसका परीक्षण किया। फिर मैंने इसे setsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev) का उपयोग करके एक विशिष्ट इंटरफ़ेस में बाध्य किया। अंत में, मैंने इसे प्रसारण पते पर बांध दिया। किसी अन्य कंप्यूटर से, मैंने एक प्रसारण भेजा जो एक गैर-इंटरफ़ेस इंटरफ़ेस के माध्यम से प्राप्त किया जाएगा। डिवाइस-बाउंड सॉकेट को यह प्रसारण प्राप्त नहीं हुआ, जो समझ में आता है। setsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev) कॉल हटाएं और प्रसारण प्राप्त होगा।

यह भी उल्लेख किया जाना चाहिए कि आप यहां setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) का भी उपयोग कर सकते हैं। ध्यान दें कि प्रसारण पते के साथ SO_REUSEADDR के अर्थशास्त्र बदलते हैं। विशेष रूप से, यह वैध है कि ब्रॉडकास्ट पते और उसी पोर्ट पर एक ही पोर्ट पर दो सॉकेट हों, यदि दोनों के पास SO_REUSEADDR सेट है।

अद्यतन: SO_BINDTODEVICE ब्रॉडकास्ट के साथ, विशेष रूप से, प्रसारण फ्रेम के स्वागत से भरा हुआ प्रतीत होता है। मैं एक इंटरफेस पर प्राप्त प्रसारण फ्रेम देख रहा था, लेकिन एक ही समय में दूसरे पर गायब हो रहा था। ऐसा लगता है कि वे स्थानीय रूटिंग तालिका से प्रभावित होते हैं, लेकिन आईपी नीति नियमों से प्रतिरक्षा हैं। हालांकि, मैं इस बारे में 100% निश्चित नहीं हूं और यदि आप इसे जारी रखना चाहते हैं तो केवल जांच के बिंदु के रूप में इसका उल्लेख कर रहा हूं। यह सब कहने के लिए: अपने जोखिम पर उपयोग करें। समय के हित में, मैंने इंटरफ़ेस पर एक कच्ची सॉकेट खोली और ईथरनेट और आईपी शीर्षकों को स्वयं पार्स किया।

+0

बहुत जानकारीपूर्ण प्रश्न और उत्तर, अच्छी नौकरी! –

2

आपके प्रश्न का सीधा जवाब नहीं है, लेकिन केवल एक एफवाईआई है। जैसा कि आपने ऊपर बताया है, यह समाधान आपको जो चाहिए/उसके लिए करना बहुत अधिक काम हो सकता है।

मुझे व्यक्तिगत रूप से नेटवर्क स्टैक हुक कर्नेल मॉड्यूल बनाने का विचार पसंद है जो मुझे ऐसा करने की अनुमति देगा। इस तरह से मल्टीकास्ट और यूनिटकास्ट फ्रेम पर उपयोगकर्ता नियंत्रण से आने और आने पर मेरा पूरा नियंत्रण है। आपको अपने ड्राइवर और उपयोगकर्ता स्पेस एप्लिकेशन से डेटा भेजने/प्राप्त करने के लिए netlink sockets जैसे कुछ उपयोग करना होगा, लेकिन यह बहुत अच्छी तरह से काम करता है और बहुत तेज़ है।

आपको इस तरह के ढेर के किसी भी स्तर में भी हुक करना होगा ... ईथरनेट, या आईपी। इस प्रकार आप जो भेजते हैं/प्राप्त करते हैं उस पर पूर्ण नियंत्रण रखते हैं।

यहां एक उदाहरण article है जो नेटफिल्टर स्टैक में हुकिंग के बारे में बात करता है।
नोट: यह आलेख आईपी स्टैक में हुक करता है, और यह भी पुराना है। मुझे पता है कि एपीआई बदल गए हैं, लेकिन इस लेख में से बहुत सारे व्यावहारिक और सैद्धांतिक रूप से लागू होते हैं। आप ब्रिजिंग परत में हुक करना चाहता था, तो आप एक ऐसी ही प्रणाली का उपयोग होगा, लेकिन निर्दिष्ट

BR_LOCAL_IN instead of NF_IP_LOCAL_IN 

नोट: यह बहुत इंटरफेस पर एक रॉ सॉकेट खोलने के समान है। आपको अपने फ्रेम स्वयं बनाना होगा।

2

आप एक नेटवर्क इंटरफेस को नेटवर्क इंटरफेस को सीमित करने का प्रयास कर सकते हैं। आपको CONFIG_NETNS (आधुनिक distros के अधिकांश कर्नल) और कुछ स्क्रिप्ट के लिए असाइनमेंट करने के लिए कर्नेल बिल्ड की आवश्यकता है। Sample configuration

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

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