हाल ही में, उन्होंने एक दिलचस्प बहस देखी कि वास्तव में PHP लिपियों से अंतिम उपयोगकर्ता के आईपी पते को निर्धारित करना कितना आवश्यक है।
दरअसल, विषय का प्रत्येक शब्द वास्तविक स्थिति को दर्शाता है। यह एक धार्मिक बहस थी, जो अद्भुत वसंत के मौसम से बढ़ी थी, जिसमें, मेरा मानना है कि कोई सही और गलत नहीं थे, लेकिन जिसने मुझे थोड़ा शोध के लिए प्रेरित किया और मेरी खुशी के लिए, इस उलझन की समझ को समाप्त कर दिया, लेकिन वास्तव में एक बहुत ही सरल प्रश्न है।
उन लोगों के लिए, जिन्होंने मुझ पर
शक किया , मुझे यकीन था कि मैंने इसे समझ लिया था, लेकिन बिल्ली के नीचे छोटी चीज़ों को समझने के लिए बहुत आलसी से
पूछने से डरता था।
प्रागितिहास
सैमसंग स्मार्टटीवी प्लेटफॉर्म के लिए एक वीओडी सेवा विकसित करते समय, हमें निश्चित रूप से उपयोगकर्ता के देश को जानने की आवश्यकता है ताकि हम गलती से खुश उपयोगकर्ता को एक फिल्म न दिखाए जहां कॉपीराइट धारक मना करता है ... लेकिन इस अनुबंध अवधि के उल्लंघन में हजारों डॉलर में बच्चे का जुर्माना शामिल नहीं है (इसके लिए क्या होता है) निरीक्षण)।
[प्रश्न, जैसा कि टिप्पणियों में उल्लेख किया गया है, कानूनी है, और धोखाधड़ी संभव है, लेकिन लेख इस तरह के धोखाधड़ी को रोकने के लिए कैसे करें, लेकिन कैसे php और nginx के साथ दोस्तों को सही तरीके से बनाने के बारे में नहीं है]सर्वर पर हमारे पास निम्नलिखित हैं: php-fpm + nginx
देश का निर्धारण कैसे करें? खैर, स्वाभाविक रूप से, उपयोगकर्ता के आईपी और GEO आईपी आधार
मैक्समाइंड के माध्यम से"पफ़्फ़ ...." -
हम सभी ने मेरे
लिए सोचा - लेकिन उतना ही सरल। और अपनी बाइक न लिखने के लिए, वह
स्टैकओवरफ्लो पर googled ,
यहां तक कि हर लाइन में
डीलडाउन किया, उस पर स्क्रू किया और उसे वहीं छोड़ दिया और कोड बढ़ता गया:
public function getUserHostAddress(){ if (!empty($_SERVER['HTTP_X_REAL_IP']))
और यह काम किया! लगभग एक साल ... जब तक कुछ अप्रत्याशित नहीं हुआ। स्वाभाविक रूप से इस कोड के लिए अप्रत्याशित ...
कैसे php या प्रॉक्सी श्रृंखला भ्रमित करने के लिए (अभी भी इतिहास का हिस्सा)
सब कुछ टूट गया है! और यह तब हुआ जब हमें भुगतान प्रणालियों में से एक को पेंच करना पड़ा और यह सब कोड क्रैश हो गया, क्योंकि एक पता HTTP_X_FORWARDED_FOR पर नहीं आया था, लेकिन अल्पविराम से अलग किए गए पते की एक सूची (जो कड़ाई से कानूनी, अनुमेय और
php गोदी में विनियमित नहीं है)
अगर HTTP_X_REAL_IP या HTTP_CLIENT_IP (जो डॉक द्वारा भी विनियमित नहीं हैं) वांछित आईपी में सम्मिलित नहीं है, पर किसी ने कुछ भी नहीं देखा होगा, लेकिन अफसोस कि वे खाली थे :(
"ठीक है," हमें लगा (अब मैं अकेला नहीं था), सब कुछ फिर से लिखो और उपयोगकर्ता से IP को REMOTE_ADDR चर में धकेलने के लिए कहो:
public function getUserHostAddress(){ $ip=$_SERVER['REMOTE_ADDR']; return $ip; }
और यह काम किया! लगभग एक महीना ... जब तक कुछ अप्रत्याशित नहीं हुआ। स्वाभाविक रूप से इस कोड के लिए अप्रत्याशित ...
कठिन पुरुषों के वसंत तर्क (यह विडंबना नहीं है - वे शांत हैं)
सब कुछ टूट गया है! और यह इसलिए हुआ क्योंकि हमें nginx को अपडेट करने की आवश्यकता थी। और हमने इस मामले में पेशेवरों की ओर रुख किया - अपने प्रवेशकों के लिए।
और उन लोगों ने, रेमोटे_एडीडीआर को फॉरवर्ड करने के लिए कॉन्फिगरेशन को अपडेट करने और हमारी "बैसाखी / बैसाखी से छुटकारा" (जब तक हम इस बात को समझ नहीं पाए) से छुटकारा पाने का फैसला किया।
REMOTE_ADDR ने अपरिवर्तित छोड़ दिया अर्थात अब कुछ ऐसा है जैसे "127.0.0.1" चमक गया
HTTP_X_FORWARDED_FOR में उपयोगकर्ता का IP स्कैम किया गया था (जो इस बीच, ब्राउज़र से हेडर `x-फॉरवर्डेड-फॉर: 999.999.999.999` भेजकर आसानी से ओवरराइड कर लिया गया था)
और फिर यह शुरू हुआ - पी = डेवलप, ए = एडमिन:
A: आपके लिए सब कुछ टूट गया, और चूंकि हमारे पास एक nginx प्रॉक्सी है, तो आपको जिस पते की आवश्यकता है वह HTTP_X_FORWARDED_FOR में है और REMOTE_ADDR में क्लाइंट के लिए php-fpm का वास्तविक IP पता स्थित होगा (अर्थात 127.0.0.1)
R: लेकिन हम HTTP_X_FORWARDED_FOR पर विश्वास नहीं कर सकते हैं, क्योंकि यह एक ऐसा चर है जिसे हेडर के माध्यम से सर्वर पर आसानी से पुनः परिभाषित किया जा सकता है, बल्कि एक दिलचस्प
लेख का हवाला देते हुए।
A: नहीं, हम इसे अंतिम उपयोगकर्ता का वास्तविक IP बना देंगे, और REMOTE_ADDR में php के लिए वास्तविक ग्राहक पता
आर: तो हम परदे के पीछे के अनुक्रम का पालन नहीं करेंगे, और फिर भी एक और सर्वर पर सार्वभौमिकरण के लिए (एक प्रॉक्सी के बिना कहें) ये कॉन्फ़िगरेशन REMOTE_ADDR में सब कुछ सच नहीं हो सकता है जो वैसे भी काम करेगा।
... यह संक्षिप्त और मैट के बिना है ...
नतीजतन, निश्चित रूप से, सब कुछ शुरू हुआ ... और पारदर्शी समीपता पर बसे जब php को लगता है कि ग्राहकों को किसी भी परदे के पीछे और सभी चर से सीधे जुड़े हुए हैं (अधिक सटीक रूप से हम जिस पर ध्यान देते हैं) हमें राज्य में चाहिए।
हालांकि, इस मामले में पर्याप्त फेंग शुई नहीं है और वास्तव में हमारे
पास प्रॉक्सी है और शायद एक भी नहीं है।
किसे दोष देना है, किसे सही है
यह हमारे लिए न्याय करने के लिए नहीं है, लेकिन कोई भी नहीं!
अगर हमारे पास वास्तव में php, या पारदर्शी समीपता के लिए सीधे ग्राहकों का एक समूह है, तो सब कुछ सरल है - स्वास्थ्य और आनंद के लिए REMOTE_ADDR का उपयोग करें।
लेकिन फैनिंग के बारे में क्या है और यह कहाँ होना चाहिए अगर हम सामान्य प्रॉक्सिंग का उपयोग करते हैं और चाहते हैं कि PHP इसके बारे में जाने?
नुस्खा ... लेकिन रामबाण नहीं:
- REMOTE_ADDR - हमारे पास 127.0.0.1 मामले में सीधे पहुंच वाले nginx का IP पता है
- HTTP_X_FORWARDED_FOR - इसमें प्रॉक्सी पतों की एक श्रृंखला होती है और अंतिम ग्राहक के प्रॉक्सी सर्वर तक पहुँचने का आईपी होता है। और यहाँ हम दो विशेष मामलों पर विचार करते हैं:
- समीपवर्ती समीप नहीं। HTTP_X_FORWARDED_FOR में, अंतिम या केवल IP पता (उपयोगकर्ता द्वारा भेजे गए / x-अग्रेषित-हेडर के लिए जो नहीं भेजा गया है, उसके आधार पर) वास्तविक, खोजा हुआ, समान उपयोगकर्ता पता होगा।
ऐसा लगता है कि समस्या इस चर को पार्स करने के लिए है और वहां से अंतिम तत्व प्राप्त करना है। लेकिन हमारे मामले में, सेटिंग्स पूरी तरह से सही नहीं थीं और पूरे HTTP_X_FORWARDED_FOR को एक्स-फॉरवर्ड किए गए ब्राउज़र से हेडर द्वारा बदल दिया गया था, और इसे सीधे उपयोगकर्ता के असली आईपी को छड़ी करना था।
उदाहरण के लिए, मैंने औद्योगिक vps होस्टिंग पर जाँच की:
इस तरह के डेटा पर भरोसा करना भी डरावना है, लेकिन अगर सेटिंग्स में सब कुछ सही ढंग से किया जाता है, तो अंतिम आईपी उपयोगकर्ता का पता होगा, चाहे जो भी हेडर में आए।
- कैस्केडिंग प्रॉक्सी। इस मामले में, वास्तव में HTTP_X_FORWARDED_FOR - इसमें प्रॉक्सी पतों की एक श्रृंखला है और अंतिम प्रत्यक्ष क्लाइंट का आईपी है जो प्रॉक्सी सर्वर में बदल गया है। लेकिन यह उपयोगकर्ता का वास्तविक आईपी नहीं है, बल्कि सूची में पिछले प्रॉक्सी का आईपी है।
ऐसा लगता है कि समस्या इस चर को पार्स करना है और वहां से पहला तत्व प्राप्त करना है। लेकिन जैसा कि ऊपर दिए गए आंकड़े में दिखाया गया है, यह निश्चित रूप से सही डेटा नहीं है और उपयोगकर्ता हमें एक्स-फॉरवर्ड किए गए पहले तत्व के लिए दो खातों में गुमराह कर सकता है, जो आईपी चाहता है
- HTTP_X_REAL_IP (या कोई अन्य वैरिएबल एडमिन और रेज़र सहमत हैं ) - इसमें php तक पहुंचने वाले उपयोगकर्ता का IP पता या सर्वर से पहला अविश्वासित प्रॉक्सी है (जो हमारे लिए क्लाइंट एड्रेस के बराबर है)
सुविधा के लिए, आप nginx के लिए एक विशेष मॉड्यूल का उपयोग कर सकते हैं जो कैस्केडिंग और गैर-कैस्केडिंग प्रॉक्सी को निर्धारित करने की समस्याओं को समाप्त करता है, लेकिन यह "nginx को सेंटो, डेबिट और फेडोरा की मानक असेंबली में डिफॉल्ट करता है, किसी कारण के लिए पैरामीटर के बिना - http -real_realip_module"। इसके साथ ही इसके लिए , HTTP_X_FORWARDED_FOR में श्रृंखला सही ढंग से बनाई जानी चाहिए और विश्वसनीय प्रॉक्सी सर्वर के पते जिनसे हम HTTP_X_FORWARDED_FOR से अंतिम तत्व ले सकते हैं, को कॉन्फ़िगर किया जाना चाहिए
हालाँकि, फिर से, HTTP_X_REAL_IP सामान्य रूप से वास्तविक एंड-यूज़र IP नहीं है , लेकिन कैस्केडिंग प्रॉक्सी के लिए प्रॉक्सी की सूची में केवल पहला IP है।
हालाँकि अगर समीपता कैस्केडिंग नहीं है, तो अंतिम-उपयोगकर्ता पता भी हो सकता है।
और अगर समीपता कैस्केडिंग है और http_realip मॉड्यूल सही तरीके से कॉन्फ़िगर किया गया है, तो या तो एंड-यूज़र IP या पहले अविश्वासित प्रॉक्सी का सही IP होना चाहिए, यदि आप php सर्वर से गणना करते हैं, जो हमारे लिए भी काम करेगा। - HTTP_CLIENT_IP (या किसी भी अन्य चर व्यवस्थापक और रेज़र पर सहमत) - में HTTP_X_FORWARDED_FOR के पहले IP को किसी भी प्रकार के सम्मिलित करने के लिए सम्मिलित है, और सम्पर्क की अनुपस्थिति में, http हेडर की सामग्री क्लाइंट-आई पी हैं जिसका उपयोग केवल संदर्भ के लिए किया जा सकता है। और किसी भी मामले में उपयोगकर्ता के वास्तविक आईपी का निर्धारण करने के लिए नहीं ।
निष्कर्ष में
Php + nginx के लिए कई प्रॉक्सी विकल्प हैं
- पारदर्शी - _SERVER (REMOTE_ADDR सहित) में चर की निरंतर सामग्री की विशेषता है, जैसे कि हम सीधे php के साथ काम कर रहे थे
- पारदर्शी नहीं कैस्केडिंग नहीं - यह विशेषता है कि व्यवस्थापक और रज़्रब को इस बात पर सहमत होने की आवश्यकता है कि उपयोगकर्ता का वास्तविक आईपी पता कहाँ संग्रहीत किया जाएगा :)
- गैर-पारदर्शी कैस्केडिंग - समान चीज़ नॉन-पारदर्शी नॉन-कैस्केडिंग + की विशेषता है, जो कि नेग्नेक्स के लिए सही तरीके से कॉन्फ़िगर किया गया है। कैस्केडिंग के आसन्न होने की संभावना को याद रखना भी आवश्यक है और यह कि उपयोगकर्ता दुर्भावनापूर्ण है और _SERVER ["HTTP_xxxx"] पर अपना असत्य डेटा भेज सकता है।
पुनश्चबाद में हम सेटिंग्स में फेंग शुई डालेंगे और पारदर्शी प्रॉक्सी से छुटकारा पाएंगे, साथ ही दोनों प्रॉक्सी मामलों के लिए आईपी का निर्धारण करने के लिए एक सार्वभौमिक फ़ंक्शन लिखेंगे।
पी पी एसमज़े के लिए, कौन परवाह करता है: अगर कोई टिप्पणी करता है तो यह फ़ंक्शन लिखता है और नग्नेक्स कॉन्फ़िगरेशन हमारे लिए है और हम इसका उपयोग करेंगे, फिर ईमानदारी से, उसे फोन पर 100 रूबल मिलेंगे।
लेकिन यह फ़ंक्शन और कॉन्फ़िगरेशन वास्तव में रूढ़िवादी होना चाहिए और सब कुछ पर विचार करना चाहिए :) सभी सुराग लेख में हैं।
मुख्य बात ज़ेन है: अपना समय ले लो - अचानक पहले वाले त्रुटियों के साथ लिखेंगे और आप उन्हें ध्यान में रखेंगे, जल्दी करो - अचानक पहला सही जवाब आपके ऊपर होगा।
आप सभी को धन्यवाद। एक अच्छा वसंत है! सहकर्मियों के साथ व्यवस्था करें और उन्हें प्यार करें! :)
यूडीपी:खुद का कार्यान्वयन:
public function getUserHostAddress( $ip_param_name = null, $allow_non_trusted = false, array $non_trusted_param_names = array('HTTP_X_REAL_IP','HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR','REMOTE_ADDR') ){ if(empty($ip_param_name) || !is_string($ip_param_name)){