पर्यावरण वेरिएबल्स HTTP_PROXY, HTTPS_PROXY और NO_PROXY बेहद सरल लगते हैं: वेरिएबल सेट किया — सारा ट्रैफिक प्रॉक्सी के माध्यम से चला गया। प्रैक्टिकल में, इसी जगह डेवलपर्स डिबगिंग में घंटों बर्बाद करते हैं: प्रॉक्सी टर्मिनल में काम करता है, लेकिन Docker कंटेनर में नहीं; curl प्रॉक्सी के माध्यम से जाता है, लेकिन Python एप्लिकेशन नहीं; CI-रनर अचानक आंतरिक रजिस्ट्री को ब्लॉक कर देता है, क्योंकि NO_PROXY गलत सिंटैक्स में निर्दिष्ट है। हम 7 वास्तविक जालों का विश्लेषण करेंगे और दिखाएंगे कि उन्हें कैसे обходना है।
कैसे एप्लिकेशन प्रॉक्सी वेरिएबल्स पढ़ते हैं
यह समझना महत्वपूर्ण है: HTTP_PROXY, HTTPS_PROXY और NO_PROXY HTTP प्रोटोकॉल का मानक नहीं हैं, बल्कि एक सम्मेलन है जिसे प्रत्येक लाइब्रेरी अपने तरीके से लागू करती है। Linux का कोर इन वेरिएबल्स के बारे में कुछ नहीं जानता — इन्हें एक विशेष एप्लिकेशन या लाइब्रेरी नेटवर्क क्लाइंट के प्रारंभिककरण के चरण में पढ़ती है।
उदाहरण के लिए, curl और libcurl आधारित उपयोगिताएँ हर प्रक्रिया के प्रारंभ में वेरिएबल्स को पढ़ती हैं। Python लाइब्रेरी requests इन्हें urllib.request.getproxies() मॉड्यूल के माध्यम से पढ़ती है, जो सत्र बनाने के समय प्रक्रिया के वातावरण को स्कैन करता है। जबकि Node.js में встроенный fetch() संस्करण 18 से पहले इन वेरिएबल्स को बिना अतिरिक्त पैकेज के ध्यान में नहीं रखता।
यहाँ से पहला नियम निकलता है: प्रॉक्सी वेरिएबल केवल वहीं काम करती है जहाँ इसे विशेष रूप से समर्थन किया गया है। curl के माध्यम से जांच करने से यह सुनिश्चित नहीं होता कि आपका एप्लिकेशन Go, Java या Node.js में भी ऐसा ही व्यवहार करेगा।
export HTTP_PROXY="http://user:[email protected]:8080"
export HTTPS_PROXY="http://user:[email protected]:8080"
export NO_PROXY="localhost,127.0.0.1,.internal.corp"
curl -v https://api.example.com/ping
# curl verbose-log में दिखाएगा: "Trying proxy.example.com..."
जाल 1: वेरिएबल्स का केस और httpoxy
अधिकांश Linux कंसोल उपयोगिताएँ वेरिएबल्स को लोअर केस में पढ़ती हैं: http_proxy, https_proxy, no_proxy। कई आधुनिक SDK अपरकेस में काम करते हैं। यह अंतर मामूली लगता है, लेकिन इसी कारण "स्थानीय रूप से काम करता है, सर्वर पर नहीं" जैसी आधी बग्स पहले ही दिन सेटअप में हो जाती हैं।
एक अलग कहानी है httpoxy भेद्यता (CVE-2016-5385 और संबंधित)। इसका सार यह है कि CGI वातावरण (PHP, Python WSGI, कुछ Ruby फ्रेमवर्क) स्वचालित रूप से इनकमिंग अनुरोध से HTTP हेडर Proxy को पर्यावरण वेरिएबल HTTP_PROXY में बदल देता है। एक हमलावर Proxy: http://attacker.com हेडर भेजता है, और आपका सर्वर एप्लिकेशन बाहरी प्रॉक्सी सर्वर के माध्यम से आउटगोइंग अनुरोध भेजने लगता है, जिससे MITM हमले और डेटा लीक का रास्ता खुलता है।
समाधान — हमेशा दोनों केस में वेरिएबल्स सेट करें और HTTP_PROXY को वेब सर्वर स्तर पर इनकमिंग अनुरोधों के लिए स्पष्ट रूप से शून्य करें:
# संगतता के लिए दोनों केस में सेट करें
export http_proxy="http://proxy.example.com:8080"
export HTTP_PROXY="http://proxy.example.com:8080"
export https_proxy="http://proxy.example.com:8080"
export HTTPS_PROXY="http://proxy.example.com:8080"
# nginx में — क्लाइंट से Proxy हेडर को ब्लॉक करें
proxy_set_header Proxy "";
जाल 2: NO_PROXY का सिंटैक्स उपकरणों के बीच भिन्न होता है
NO_PROXY एक अपवादों की सूची है, लेकिन इसमें डोमेन और मास्क के रिकॉर्ड का प्रारूप मानकीकृत नहीं है। कुछ उपकरण .example.com को "कोई भी सबडोमेन" के रूप में समझते हैं, जबकि अन्य *.example.com की आवश्यकता होती है, और तीसरे केवल बिना वाइल्डकार्ड के सटीक मेल को समझते हैं।
उदाहरण के लिए, Go लाइब्रेरी net/http NO_PROXY में CIDR नोटेशन का समर्थन करती है (10.0.0.0/8), जबकि क्लासिक curl कुछ संस्करणों तक नहीं करता। यह स्थिति तब उत्पन्न होती है जब एक ही NO_PROXY एक CI चरण के लिए आंतरिक रजिस्ट्री को सही ढंग से बाहर करता है और दूसरे के लिए, जो एक अन्य भाषा में लिखा गया है, उसे बाहर नहीं करता।
| उपकरण | सबडोमेन का वाइल्डकार्ड | CIDR मास्क |
|---|---|---|
| curl / libcurl | के माध्यम से .example.com | नहीं |
| Go net/http | के माध्यम से .example.com | हाँ |
| Python requests | के माध्यम से .example.com | नहीं |
| npm / Node.js | आवश्यक *.example.com | नहीं |
व्यावहारिक सलाह: NO_PROXY में डोमेन और वाइल्डकार्ड दोनों रूपों को एक साथ सूचीबद्ध करें, ताकि विभिन्न पार्सर्स को कवर किया जा सके:
export NO_PROXY="localhost,127.0.0.1,.internal.corp,*.internal.corp,10.0.0.0/8"
जाल 3: Docker build बनाम Docker run — विभिन्न पर्यावरण वेरिएबल्स
यह शायद Docker में सबसे सामान्य जाल है। वेरिएबल्स जो docker run -e HTTP_PROXY=... के माध्यम से सेट किए जाते हैं, केवल कंटेनर के चलने के दौरान कार्य करते हैं। ये स्वचालित रूप से इमेज बनाने के चरण में नहीं जाते। यदि आपका Dockerfile apt-get install या pip install को कॉल करता है, और निर्माण कॉर्पोरेट प्रॉक्सी के पीछे हो रहा है, तो निर्माण बस टाइमआउट पर अटक जाएगा।
निर्माण के लिए, आपको build-args पास करने की आवश्यकता है, जिन्हें Docker संस्करण 1.9+ से "बॉक्स से बाहर" समझता है बिना Dockerfile में घोषित किए:
docker build \
--build-arg HTTP_PROXY=http://proxy.example.com:8080 \
--build-arg HTTPS_PROXY=http://proxy.example.com:8080 \
--build-arg NO_PROXY=localhost,127.0.0.1 \
-t my-app:latest .
यदि आप चाहते हैं कि वेरिएबल कंटेनर के अंदर भी उपलब्ध रहे, तो इसे Dockerfile में ENV के माध्यम से स्पष्ट रूप से डुप्लिकेट करना होगा — ARG और ENV Docker में मौलिक रूप से अलग तंत्र हैं, और ARG निर्माण स्तर के बाद तुरंत गायब हो जाता है:
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY
ENV HTTP_PROXY=${HTTP_PROXY}
ENV HTTPS_PROXY=${HTTPS_PROXY}
ENV NO_PROXY=${NO_PROXY}
RUN apt-get update && apt-get install -y curl
एक और बारीकी: Docker डेमन स्वयं रजिस्ट्री से इमेज डाउनलोड करने के लिए प्रॉक्सी का उपयोग कर सकता है — यह Dockerfile में सेट नहीं किया जाता, बल्कि systemd यूनिट कॉन्फ़िगरेशन में /etc/systemd/system/docker.service.d/http-proxy.conf में सेट किया जाता है, जिसे अक्सर कंटेनर के अंदर वेरिएबल्स के साथ भ्रमित किया जाता है।
जाल 4: docker-compose और सेवाओं के बीच वेरिएबल्स का उत्तराधिकार
docker-compose में, होस्ट के पर्यावरण वेरिएबल्स स्वचालित रूप से कंटेनरों में नहीं भेजे जाते हैं, यदि आपने उन्हें स्पष्ट रूप से environment सेक्शन में नहीं लिखा है या .env फ़ाइल का उपयोग नहीं किया है। एक सामान्य गलती है — docker-compose up चलाने से पहले टर्मिनल में प्रॉक्सी सेट करना और यह उम्मीद करना कि सभी सेवाएँ इसे उठाएँगी।
version: "3.9"
services:
scraper:
build:
context: .
args:
HTTP_PROXY: "${HTTP_PROXY}"
HTTPS_PROXY: "${HTTPS_PROXY}"
environment:
- HTTP_PROXY=${HTTP_PROXY}
- HTTPS_PROXY=${HTTPS_PROXY}
- NO_PROXY=localhost,127.0.0.1,db,redis
depends_on:
- db
- redis
NO_PROXY पर ध्यान दें: docker-compose नेटवर्क के भीतर कंटेनर एक-दूसरे को सेवा नामों (db, redis) के माध्यम से संदर्भित करते हैं, न कि localhost के माध्यम से। यदि सेवा नामों को अपवादों में जोड़ना भूल जाते हैं, तो कंटेनरों के बीच सारा आंतरिक ट्रैफिक भी बाहरी प्रॉक्सी के माध्यम से जाएगा, जिससे देरी बढ़ जाएगी और यदि प्रॉक्सी आंतरिक प्रोटोकॉल जैसे PostgreSQL या Redis को अनुमति नहीं देती है तो कनेक्शन टूट सकता है।
जाल 5: CI/CD रनर्स और प्रॉक्सी के रहस्य लीक
GitHub Actions, GitLab CI और Jenkins में प्रॉक्सी वेरिएबल्स अक्सर रनर या पूरी संगठन के स्तर पर सेट किए जाते हैं, और यह दो समस्याएँ उत्पन्न करता है। पहली, यदि प्रॉक्सी का URL लॉगिन और पासवर्ड को स्पष्ट रूप से शामिल करता है, तो यह किसी भी कमांड में निर्माण लॉग में दिखाई देता है जो वातावरण को प्रिंट करता है (env, printenv, स्क्रिप्ट में डिबगिंग आउटपुट)। दूसरी, स्वयं-होस्टेड रनर्स कभी-कभी होस्ट के सिस्टम प्रॉक्सी को विरासत में लेते हैं, जो CI जॉब के ट्रैफिक के लिए नहीं होता है।
# .github/workflows/build.yml
jobs:
build:
runs-on: ubuntu-latest
env:
HTTP_PROXY: ${{ secrets.PROXY_URL }}
HTTPS_PROXY: ${{ secrets.PROXY_URL }}
NO_PROXY: "localhost,127.0.0.1,github.com"
steps:
- uses: actions/checkout@v4
- name: कनेक्शन का परीक्षण करें
run: curl -sS https://api.example.com/health
सुरक्षा का नियम: प्रॉक्सी के URL को केवल CI में रहस्यों में रखें (GitHub Secrets, GitLab CI/CD Variables के साथ "masked" फ्लैग), कभी भी डिबगिंग लॉग में पूरे वातावरण वेरिएबल्स को प्रिंट न करें, और NO_PROXY को इस तरह सीमित करें कि CI प्लेटफ़ॉर्म (जैसे, github.com, gitlab.com) के अनुरोध प्रॉक्सी के माध्यम से न जाएँ — अन्यथा निर्माण अटक सकता है यदि प्रॉक्सी उस समय पीक लोड पर अनुपलब्ध है।
जाल 6: प्रॉक्सी के लॉगिन और पासवर्ड में विशेष वर्ण
यदि प्रॉक्सी का पासवर्ड @, :, / या # जैसे वर्ण शामिल करता है, तो URL-पार्सर बस गलत जगहों पर स्ट्रिंग को तोड़ देता है। क्लासिक गलती: पासवर्ड P@ssw0rd को स्ट्रिंग http://user:P@[email protected]:8080 में पार्सर इस तरह पढ़ता है जैसे होस्ट "[email protected]" है, न कि "proxy.com"।
समाधान — हमेशा लॉगिन और पासवर्ड को वेरिएबल में डालने से पहले URL-कोड करें:
# Python: प्रॉक्सी स्ट्रिंग बनाने से पहले पासवर्ड को कोड करें
import urllib.parse
user = "login"
password = "P@ss:w0rd/1"
encoded_password = urllib.parse.quote(password, safe="")
proxy_url = f"http://{user}:{encoded_password}@proxy.example.com:8080"
import os
os.environ["HTTPS_PROXY"] = proxy_url
# Node.js: encodeURIComponent के माध्यम से समान निर्माण
const user = "login";
const password = "P@ss:w0rd/1";
const encoded = encodeURIComponent(password);
const proxyUrl = `http://${user}:${encoded}@proxy.example.com:8080`;
process.env.HTTPS_PROXY = proxyUrl;
जाल 7: एप्लिकेशन जो पर्यावरण वेरिएबल्स को अनदेखा करते हैं
सभी HTTP क्लाइंट सिस्टम प्रॉक्सी वेरिएबल्स का सम्मान नहीं करते। Python में लाइब्रेरी requests इन्हें स्वचालित रूप से requests.Session() के माध्यम से पढ़ती है, लेकिन यदि आपने एक बार स्पष्ट रूप से proxies={} शब्दकोश को कॉल में पास किया, तो यह पर्यावरण वेरिएबल्स को ओवरराइड कर देता है और ट्रैफिक सीधे जाएगा, भले ही HTTP_PROXY सिस्टम में सेट किया गया हो।
import requests
# खाली शब्दकोश proxies पर्यावरण वेरिएबल्स को ओवरराइड करता है
response = requests.get("https://api.example.com", proxies={})
# सही — स्पष्ट रूप से प्रॉक्सी पास करें या बिल्कुल proxies न भेजें
proxies = {
"http": "http://user:[email protected]:8080",
"https": "http://user:[email protected]:8080",
}
response = requests.get("https://api.example.com", proxies=proxies)
Node.js में встроенный fetch बिना अतिरिक्त लाइब्रेरी के HTTP_PROXY के बारे में नहीं जानता। आपको undici को ProxyAgent के साथ या क्लासिक https-proxy-agent को स्पष्ट रूप से जोड़ना होगा:
const { ProxyAgent, setGlobalDispatcher } = require("undici");
const proxyUrl = process.env.HTTPS_PROXY;
if (proxyUrl) {
setGlobalDispatcher(new ProxyAgent(proxyUrl));
}
fetch("https://api.example.com/data")
.then(res => res.json())
.then(console.log);
Java को भी पर्यावरण वेरिएबल्स के बजाय अलग सिस्टम प्रॉपर्टीज की आवश्यकता होती है: -Dhttp.proxyHost=proxy.example.com -Dhttp.proxyPort=8080 -Dhttps.proxyHost=proxy.example.com -Dhttps.proxyPort=8080। JVM में HTTP_PROXY पर्यावरण वेरिएबल्स डिफ़ॉल्ट रूप से पढ़े नहीं जाते।
प्रॉक्सी वेरिएबल्स का सही परीक्षण कैसे करें
एप्लिकेशन की डिबगिंग में समय बर्बाद करने से पहले, वेरिएबल और प्रॉक्सी को कोड से अलग-अलग जांचें। यह घंटों की बचत करता है।
# 1. जांचें कि वेरिएबल वास्तव में वर्तमान सत्र में सेट है
env | grep -i proxy
# 2. curl के माध्यम से सीधे प्रॉक्सी की कार्यक्षमता की जांच करें
curl -x "$HTTP_PROXY" -v https://api.ipify.org
# 3. कंटेनर के अंदर जांचें कि वेरिएबल पहुँची है
docker exec -it my_container env | grep -i proxy
# 4. जांचें कि NO_PROXY वास्तव में आवश्यक होस्ट को बाहर करता है
curl -v --noproxy "internal.corp" https://service.internal.corp/health
यदि कार्य बाहरी API के लिए बड़े पैमाने पर अनुरोध, मार्केटप्लेस का पार्सिंग या CI पाइपलाइन से विज्ञापन के भू-लक्षित परीक्षण करना है, तो लोड के लिए सही प्रकार का प्रॉक्सी चुनना महत्वपूर्ण है। CI में स्थिर उच्च-लोड परिदृश्यों के लिए आमतौर पर डेटा सेंटर प्रॉक्सी पर्याप्त होते हैं — ये बड़े पैमाने पर निर्माण और परीक्षण ट्रैफिक के लिए रेजिडेंट्स की तुलना में तेज और सस्ते होते हैं। और यदि आपकी पाइपलाइन किसी विशेष क्षेत्र के वास्तविक उपयोगकर्ता IP से वेबसाइट के व्यवहार की जांच करती है, तो बेहतर है कि रहवासी प्रॉक्सी का उपयोग करें — ये "डेटा सेंटर" IP के आधार पर ब्लॉक होने के जोखिम को कम करते हैं।
डिप्लॉयमेंट से पहले चेकलिस्ट
- वेरिएबल्स को दोनों केस में सेट किया गया है
- URL प्रॉक्सी में लॉगिन और पासवर्ड URL-कोडेड हैं
urllib.parse.quoteयाencodeURIComponentके माध्यम से - NO_PROXY में उपकरणों के बीच संगतता के लिए डोमेन और वाइल्डकार्ड प्रारूप शामिल हैं
- docker-compose में NO_PROXY में Compose नेटवर्क से सेवा नाम शामिल हैं, न कि केवल localhost
- Docker build के लिए build-args को Dockerfile में ENV के माध्यम से runtime env से अलग पास किया गया है
- CI में प्रॉक्सी के URL के साथ रहस्यों को मास्क किया गया है और डिबगिंग लॉग में प्रिंट नहीं किया गया है
- Java एप्लिकेशनों के लिए प्रॉक्सी को सिस्टम प्रॉपर्टीज -D के माध्यम से सेट किया गया है, न कि केवल env के माध्यम से
- httpoxy से सुरक्षा की जांच की गई है — क्लाइंट से Proxy हेडर को वेब सर्वर स्तर पर शून्य किया गया है
निष्कर्ष
HTTP_PROXY, HTTPS_PROXY और NO_PROXY वेरिएबल्स एक साधारण सम्मेलन हैं, जो प्रैक्टिकल में केस सेंसिटिविटी, अपवादों के सिंटैक्स, Docker build और Docker run के बीच सीमाओं, docker-compose में वातावरण के उत्तराधिकार, CI लॉग में रहस्यों के रिसाव और अंततः, यह कि हर लाइब्रेरी इन वेरिएबल्स को पढ़ती है या नहीं, के कारण टूट जाते हैं। curl और docker exec के माध्यम से प्रत्येक वेरिएबल को अलग से जांचें, इससे पहले कि आप एप्लिकेशन के बिजनेस लॉजिक में बग की तलाश करें।
यदि आपकी इन्फ्रास्ट्रक्चर बाहरी वेबसाइटों के पार्सिंग, विज्ञापन के भू-लक्षित परीक्षण या CI पाइपलाइन से IP द्वारा ब्लॉक को बायपास करने पर निर्भर है, तो केवल पर्यावरण वेरिएबल्स को सही ढंग से पास करना ही नहीं, बल्कि कार्य के लिए उपयुक्त प्रॉक्सी प्रकार का चयन करना भी महत्वपूर्ण है। मोबाइल ट्रैफिक और मोबाइल ऑपरेटरों के साथ व्यवहार की जांच करने वाले एप्लिकेशनों के परीक्षण के लिए मोबाइल प्रॉक्सी उपयुक्त हैं — ये वास्तविक सेलुलर नेटवर्क के IP प्रदान करते हैं और एंटी-फ्रॉड सिस्टम के फ़िल्टर में कम आते हैं।