2012-07-12 31 views
20

ठीक है, मेरे पास एक छोटा प्रमाणीकरण मुद्दा है। मेरी वेब सेवा उपयोगकर्ता नाम और पासवर्ड के साथ HTTP पर मेरे एपीआई से कनेक्ट करने की अनुमति देती है, लेकिन यह कनेक्शन किसी विशिष्ट आईपी पते पर भी सीमित हो सकता है।HTTP_X_FORWARDED_FOR का सही तरीके से उपयोग कैसे करें?

इसका मतलब है कि $_SERVER['REMOTE_ADDR'] गलत हो सकता है। मुझे पहले से ही पता है कि किसी भी आईपी सूचना पर कभी भरोसा नहीं किया जा सकता है - मेरे पास केवल सुरक्षा की एक और परत जोड़ने के प्रयास में प्रतिबंध है।

यह मेरी वेब सर्वर के लिए एक अनुरोध के सामान्य अवलोकन है:

clientSERVER => clientPROXY => myPROXY => mySERVER

तो इसका मतलब है कि MYSERVER बजाय ग्राहक की इस बात का MyProxy की REMOTE_ADDR से पता चलता है और ग्राहक के वास्तविक IP भेजता है HTTP_X_FORWARDED_FOR के रूप में।

इस पर काबू पाने के लिए, मेरी वेब सेवा में 'विश्वसनीय प्रॉक्सी' आईपी पते की एक सूची है और यदि REMOTE_ADDR उन विश्वसनीय आईपी पते में से एक है, तो यह मेरी वेब सेवा को बताता है कि वास्तविक आईपी पता HTTP_X_FORWARDED_FOR का मान है।

अब समस्या क्लाइंटप्रॉक्सी के साथ है। इसका मतलब है कि (अक्सर) mySERVER को HTTP_X_FORWARDED_FOR मान मिलता है जिसमें एकाधिक आईपी पते होते हैं। HTTP_X_FORWARDED_FOR दस्तावेज़ीकरण के अनुसार, मान आईपी पते की अल्पविराम से अलग सूची है जहां पहला आईपी वास्तविक सत्य ग्राहक का है और हर दूसरे आईपी पते प्रॉक्सी का है।

तो, यदि HTTP_X_FORWARDED_FOR में कई मान हैं और मेरी सेवा आईपी प्रतिबंधित है, तो क्या मुझे अपनी अनुमति आईपी सूची के विरुद्ध HTTP_X_FORWARDED_FOR का 'अंतिम' मान देखना होगा और केवल वास्तविक क्लाइंट आईपी को अनदेखा करना होगा?

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

और HTTP_CLIENT_IP का क्या?

+0

http : //stackoverflow.com/q/7445592/759866 – Benjamin

उत्तर

-4

HTTP_CLIENT_IP उपयोगकर्ता का आईपी पता प्राप्त करने का सबसे विश्वसनीय तरीका है। अगला HTTP_X_FORWARDED_FOR है, इसके बाद REMOTE_ADDR है। सभी तीनों को जांचें, उस क्रम में, यह मानते हुए कि सेट किया गया पहला (isset($_SERVER['HTTP_CLIENT_IP']) उस चर को सेट करने पर सत्य लौटाता है) सही है। आप स्वतंत्र रूप से जांच सकते हैं कि उपयोगकर्ता विभिन्न विधियों का उपयोग कर प्रॉक्सी का उपयोग कर रहा है या नहीं। this देखें।

public function getClientIP(){  
    if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)){ 
      return $_SERVER["HTTP_X_FORWARDED_FOR"]; 
    }else if (array_key_exists('REMOTE_ADDR', $_SERVER)) { 
      return $_SERVER["REMOTE_ADDR"]; 
    }else if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) { 
      return $_SERVER["HTTP_CLIENT_IP"]; 
    } 

    return ''; 
} 
+7

इनमें से कोई भी शीर्षलेख दूसरों की तुलना में "अधिक विश्वसनीय" नहीं है। वे सभी क्लाइंट द्वारा जाली जा सकते हैं, और आपके अनुप्रयोगों को यह जानने की जरूरत है कि क्या भरोसा है और क्या नहीं है: आप आमतौर पर अपने HTTP सर्वर (सर्वर) के सामने किसी भी प्रॉक्सी/लोड बैलेंसर के अपने बुनियादी ढांचे और आईपी पते को जानते हैं। – Benjamin

+1

सच है, लेकिन आम तौर पर, यदि अनुमानित विश्वसनीयता के आधार पर प्राथमिकता का क्रम स्थापित किया जाना है, तो यह है। मुझे एहसास है कि वे सभी का उपयोग किया जा सकता है, लेकिन अगर इनका इस्तेमाल किया जाना चाहिए, तो यह कैसे करना है। – TheEnvironmentalist

+5

इस विषय पर इतनी अधिक जानकारी क्यों है? '$ _SERVER ['REMOTE_ADDR']' * केवल * विश्वसनीय फ़ील्ड है जो दूरस्थ उपयोगकर्ता से प्रभावित नहीं है, अन्य सभी को हेडर से पार्स किया गया है। – transistor09

13

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

$IParray=array_values(array_filter(explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']))); 
return end($IParray); 

array_filter खाली प्रविष्टियां हटाने के लिए वहाँ में है।

+3

यह उत्तर प्रश्न में वर्णित विशिष्ट स्थिति को संबोधित नहीं करता है, जहां ** सभी अनुरोध प्रॉक्सी ** के माध्यम से पारित नहीं किए जाते हैं। नतीजतन, ग्राहकों से सीधे प्राप्त अनुरोधों में हेडर में गलत आईपी पते हो सकते हैं। – duskwuff

+0

अच्छा जवाब, आप Prestashop के टूल्स क्लास से भी सटीक पा सकते हैं :)। GetRemoteAddr() फ़ंक्शन –

13

मैं ऋषिकेश के जवाब है, जो मैं केवल यह जोड़ने के लिए करने के लिए ... क्योंकि हम अल्प विराम द्वारा सीमांकित स्ट्रिंग जब कई भर में आ देखा की तरह:

+2

नोट करें कि ऐसा लगता है कि सूची में अंतिम मान का उपयोग करना संभवतः प्रॉक्सी के आईपी का उपयोग कर रहा है। नीचे दिए गए लिंक के मुताबिक, मूल ग्राहक पहला आईपी है। http://en.wikipedia.org/wiki/X-forwarded- –

+2

के लिए यह भी ध्यान दें कि एक ही स्रोत कहता है कि यह बनाना आसान है, इसलिए अंतिम एक अधिक विश्वसनीय है। इसलिए प्रत्येक उपयोग केस अलग-अलग विकल्प बना सकता है। यदि आईपी प्राप्त करने के लिए उपयोग केस धोखाधड़ी या स्पैम का मुकाबला कर रहा है, तो पहला आईपी अर्थहीन और सबसे विश्वसनीय पता हो सकता है - अंतिम - सबसे उपयोगी है। यदि आईपी प्राप्त करने के लिए उपयोग मामला कम घृणास्पद गतिविधियों है, तो पहला सबसे उपयोगी होगा। –

0

आप एक डेटाबेस में इसका इस्तेमाल करते हैं, तो यह एक अच्छा तरीका है:

varchar (250) के लिए डेटाबेस में आईपी क्षेत्र सेट करें, और फिर इस का उपयोग करें:

$theip = $_SERVER["REMOTE_ADDR"]; 

if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) { 
    $theip .= '('.$_SERVER["HTTP_X_FORWARDED_FOR"].')'; 
} 

if (!empty($_SERVER["HTTP_CLIENT_IP"])) { 
    $theip .= '('.$_SERVER["HTTP_CLIENT_IP"].')'; 
} 

$realip = substr($theip, 0, 250); 

तो फिर तुम सिर्फ जाँच डेटाबेस आईपी फ़ील्ड के खिलाफ $ realip

6

नवीनतम httpoxy भेद्यता के प्रकाश में, वास्तव में एक पूर्ण उदाहरण की आवश्यकता है, HTTP_X_FORWARDED_FOR का उपयोग कैसे करें।

तो PHP में लिखा गया एक उदाहरण है, क्लाइंट आईपी पता कैसे पता लगाया जाए, अगर आपको पता है कि क्लाइंट प्रॉक्सी के पीछे हो सकता है और आपको पता है कि यह प्रॉक्सी भरोसा किया जा सकता है। आप किसी भी भरोसा प्रॉक्सी ज्ञात नहीं है, तो बस का उपयोग REMOTE_ADDR

<?php 

function get_client_ip() 
{ 
    // Nothing to do without any reliable information 
    if (!isset ($_SERVER['REMOTE_ADDR'])) { 
     return NULL; 
    } 

    // Header that is used by the trusted proxy to refer to 
    // the original IP 
    $proxy_header = "HTTP_X_FORWARDED_FOR"; 

    // List of all the proxies that are known to handle 'proxy_header' 
    // in known, safe manner 
    $trusted_proxies = array ("2001:db8::1", "192.168.50.1"); 

    if (in_array ($_SERVER['REMOTE_ADDR'], $trusted_proxies)) { 

     // Get the IP address of the client behind trusted proxy 
     if (array_key_exists ($proxy_header, $_SERVER)) { 

      // Header can contain multiple IP-s of proxies that are passed through. 
      // Only the IP added by the last proxy (last IP in the list) can be trusted. 
      $proxy_list = explode (",", $_SERVER[$proxy_header]); 
      $client_ip = trim (end ($proxy_list)); 

      // Validate just in case 
      if (filter_var ($client_ip, FILTER_VALIDATE_IP)) { 
       return $client_ip; 
      } else { 
       // Validation failed - beat the guy who configured the proxy or 
       // the guy who created the trusted proxy list? 
       // TODO: some error handling to notify about the need of punishment 
      } 
     } 
    } 

    // In all other cases, REMOTE_ADDR is the ONLY IP we can trust. 
    return $_SERVER['REMOTE_ADDR']; 
} 

print get_client_ip(); 

?> 
+0

यह एक उत्कृष्ट उत्तर है, लेकिन एक मामूली समस्या है। यदि सख्त त्रुटि रिपोर्टिंग चालू है, तो एक पंक्ति पर 'ट्रिम करें (अंत (विस्फोट())' की कोशिश कर रहे हैं '' संदर्भ में केवल चर पारित किया जाना चाहिए। " इसके आस-पास पहुंचने के लिए, विस्फोटित प्रॉक्सी हेडर को पहले एक चर पर सेट करें, फिर 'trim (end())' इसके बजाए। –

+0

@ बेनडियर धन्यवाद, इसे ठीक किया गया। –

1

तुम भी एक conf.d फ़ाइल में निम्न, mod_remoteip का उपयोग कर अपाचे विन्यास के माध्यम से इस समस्या को हल कर सकते हैं जोड़ने के द्वारा:

RemoteIPHeader X-Forwarded-For 
RemoteIPInternalProxy 172.16.0.0/12 
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined