
Go के लिए एक अनुकूलन योग्य HTTP/HTTPS प्रॉक्सी लाइब्रेरी जो नियमित फॉरवर्डिंग, CONNECT टनलिंग, MITM TLS इंटरसेप्शन, और प्रोग्रामेटिक अनुरोध/प्रतिक्रिया संशोधन का समर्थन करती है।
GoProxy एक लाइब्रेरी है जो Go (जिसे Golang भी कहा जाता है) का उपयोग करके एक कस्टमाइज़्ड HTTP/HTTPS प्रॉक्सी सर्वर बनाने के लिए है, जिसमें कई कॉन्फ़िगर करने योग्य सेटिंग्स उपलब्ध हैं।
इस प्रोजेक्ट का लक्ष्य एक ऑप्टिमाइज़्ड प्रॉक्सी सर्वर प्रदान करना है, जो उचित मात्रा में ट्रैफ़िक के साथ उपयोग योग्य हो, फिर भी कस्टमाइज़ेबल और प्रोग्रामेबल हो।
प्रॉक्सी स्वयं केवल एक net/http हैंडलर है, इसलिए आप इसके ऊपर कई मिडलवेयर (पैनिक रिकवर, लॉगिंग, कम्प्रेशन, आदि) जोड़ सकते हैं। इसे किसी भी अन्य HTTP नेटवर्क लाइब्रेरी के साथ आसानी से एकीकृत किया जा सकता है।
goproxy का उपयोग करने के लिए, किसी को अपने ब्राउज़र (या किसी अन्य क्लाइंट) को HTTP प्रॉक्सी के रूप में goproxy का उपयोग करने के लिए सेट करना चाहिए।
Chrome और Firefox में ऐसा करने का तरीका यहाँ दिया गया है।
यदि आप base उदाहरण से शुरू करने का निर्णय लेते हैं, तो प्रॉक्सी के रूप में उपयोग करने वाला URL localhost:8080 है, जो हमारे उदाहरण में डिफ़ॉल्ट है।
क्लाइंट में किसी भी प्रमाणपत्र समस्या से बचने के लिए आपको प्रॉक्सी CA प्रमाणपत्र पर भी भरोसा करना होगा।
विशिष्ट होस्ट पर कुछ क्रियाएँ करें, एकल समानता तुलना या regex मूल्यांकन के साथअनुरोधों और प्रतिक्रियाओं में हेरफेर करेंकस्टम http.Transport का उपयोग करेंMITM प्रमाणपत्र कैश निर्दिष्ट कर सकते हैं, ताकि उन्हें बाद में उसी होस्ट के अन्य अनुरोधों के लिए पुनः उपयोग किया जा सके, जिससे CPU की बचत होती है। डिफ़ॉल्ट रूप से सक्षम नहीं है, लेकिन आपको इसे प्रोडक्शन में उपयोग करना चाहिए!कस्टम हैंडलर पर रीडायरेक्ट करें, जब लक्ष्य एक सापेक्ष पथ (जैसे /ping) होLogger इंटरफ़ेस को लागू करके आप उपयोग करने के लिए लॉगर चुन सकते हैंPreventCanonicalization को true पर सेट करके आप HTTP अनुरोध हेडर के कैनोनिकलाइज़ेशन को अक्षम कर सकते हैंक्या आपकी कंपनी GoProxy का उपयोग करती है? प्रोजेक्ट को बनाए रखने और स्वस्थ रखने में हमारी मदद करें! GoProxy को समर्थन देने से हम बग फिक्स और नई सुविधाओं पर अधिक समय समर्पित कर सकते हैं। बदले में, यदि आप Gold Supporter या Enterprise योजना चुनते हैं, तो हम आपकी कंपनी का लोगो यहाँ गर्व से प्रदर्शित करेंगे।
यदि आपको GoProxy को अपने प्रोजेक्ट में एकीकृत करने की आवश्यकता है, या आपको अपने फोर्क में बनाए रखने के लिए कुछ कस्टम सुविधाओं की आवश्यकता है, तो आप Erik (वर्तमान अनुरक्षक) से ईमेल द्वारा संपर्क कर सकते हैं, और आप साथ में चर्चा कर सकते हैं कि वह एक भुगतान किए गए स्वतंत्र सलाहकार के रूप में आपकी कैसे मदद कर सकता है।
यदि आपको कोई परेशानी, सुझाव है, या कोई बग मिलता है, तो GitHub issue खोलकर संपर्क करने में संकोच न करें।
यह स्वयंसेवकों द्वारा प्रबंधित एक ओपन सोर्स प्रोजेक्ट है, और हमें किसी भी चीज़ पर चर्चा करने में खुशी होगी जो इसे बेहतर बना सकती है।
समस्या को समझने में आसान बनाने के लिए सब कुछ समझाना सुनिश्चित करें, जिसमें issue के पीछे का कारण और आप क्या बदलना चाहते हैं, शामिल है।
यदि यह एक छोटा कोड परिवर्तन है, तो आप सीधे Pull Request भी खोल सकते हैं, लेकिन आपको विवरण में सब कुछ समझाना होगा।
यदि आप 5,000 पंक्तियों में बदलाव के साथ refactoring नामक पुल अनुरोध खोलते हैं, तो हम इसे मर्ज नहीं करेंगे... :D
इस प्रोजेक्ट का कोड BSD 3-Clause लाइसेंस के तहत जारी किया गया है, जो इसे वाणिज्यिक उपयोग के लिए भी उपयोगी बनाता है।
तो, आपने GoProxy को अपने किसी व्यक्तिगत प्रोजेक्ट में या जिस कंपनी के लिए आप काम करते हैं उसके किसी प्रोजेक्ट में पेश और एकीकृत किया है।
हमें इस लाइब्रेरी के साथ बनाए गए नए रचनात्मक समाधानों के बारे में जानकर खुशी होगी, इसलिए बेझिझक ईमेल के माध्यम से ऊपर सूचीबद्ध अनुरक्षक से संपर्क करें, यह समझाने के लिए कि आपको यह प्रोजेक्ट आपकी आवश्यकताओं के लिए उपयोगी क्यों लगा।
यदि आपने कंपनी के साथ गैर-प्रकटीकरण समझौते (Non Disclosure Agreement) पर हस्ताक्षर किए हैं, तो आप उन्हें अपनी आधिकारिक वेबसाइट पर इस विषय पर ब्लॉग पोस्ट लिखने का प्रस्ताव दे सकते हैं, ताकि यह जानकारी उनकी पसंद से सार्वजनिक हो जाए, और आप ब्लॉग पोस्ट का लिंक हमारे साथ साझा कर सकते हैं :)
केस स्टडीज़ का उद्देश्य समुदाय के साथ साझा करना है कि इस प्रोजेक्ट के सभी योगदानकर्ता अपनी मदद से दुनिया को क्यों बेहतर बना रहे हैं और लोग इसका उपयोग करके क्या बना रहे हैं।
कोडबेस आपके पुल अनुरोध कोड पर एक स्वचालित लिंट जाँच का उपयोग करता है। इसे खोलने से पहले, आपको यह जाँचना चाहिए कि आपके परिवर्तन इसका सम्मान करते हैं या नहीं, अपनी स्थानीय मशीन पर लिंटर चलाकर, ताकि आपको कोई आश्चर्य न हो।
लिंटर स्थापित करने के लिए:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
यह आपके $GOPATH/bin फ़ोल्डर में एक निष्पादन योग्य बनाएगा
($GOPATH एक पर्यावरण चर है, आमतौर पर
इसका मान ~/go के बराबर होता है, यदि आप इसके बारे में सुनिश्चित नहीं हैं तो अपनी मशीन पर इसका मान जाँचें)।
अपने शेल के पथ में bin फ़ोल्डर को शामिल करना सुनिश्चित करें, ताकि आप सीधे golangci-lint run कमांड का उपयोग कर सकें।
goproxy का अनुभव लेने के लिए, यहाँ आपके लिए एक बुनियादी HTTP/HTTPS प्रॉक्सी है जो केवल डेटा को गंतव्य तक अग्रेषित करता है:
package main
import (
"log"
"net/http"
"github.com/elazarl/goproxy"
)
func main() {
proxy := goproxy.NewProxyHttpServer()
proxy.Verbose = true
log.Fatal(http.ListenAndServe(":8080", proxy))
}
यह पंक्ति प्रॉक्सी के माध्यम से भेजे गए सभी अनुरोधों में X-GoProxy: yxorPoG-X हेडर जोड़ देगी, उन्हें गंतव्य पर भेजने से पहले:
proxy.OnRequest().DoFunc(
func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {
r.Header.Set("X-GoProxy","yxorPoG-X")
return r,nil
})
जब OnRequest() इनपुट खाली होता है, तो DoFunc में निर्दिष्ट फ़ंक्शन प्रॉक्सी पर आने वाले सभी अनुरोधों को संसाधित करेगा। इस मामले में, यह अनुरोध में एक हेडर जोड़ देगा और इसे कॉलर को वापस कर देगा।
प्रॉक्सी संशोधित अनुरोध को गंतव्य पर भेजेगा।
यदि आप अपने प्रकार में निर्दिष्ट इंटरफ़ेस लागू करते हैं, तो आप DoFunc के बजाय Do का भी उपयोग कर सकते हैं।
⚠️ ध्यान दें कि हमने प्रतिक्रिया के रूप में nil मान लौटाया। यदि लौटाई गई प्रतिक्रिया nil नहीं है, तो goproxy अनुरोध को छोड़ देगा और निर्दिष्ट प्रतिक्रिया को क्लाइंट को भेजेगा।
सर्वर स्थानीय समय क्षेत्र में 8 से 17 बजे के बीच www.reddit.com से कनेक्शन अस्वीकार करें:
proxy.OnRequest(goproxy.DstHostIs("www.reddit.com")).DoFunc(
func(req *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {
if h,_,_ := time.Now().Clock(); h >= 8 && h <= 17 {
resp := goproxy.NewResponse(req, goproxy.ContentTypeText, http.StatusForbidden, "Don't waste your time!")
return req, resp
}
return req, nil
})
DstHostIs एक ReqCondition लौटाता है, जो एक फ़ंक्शन है जो *http.Request प्राप्त करता है और एक बूलियन लौटाता है जो जाँचता है कि अनुरोध शर्त को संतुष्ट करता है या नहीं (और जिसे संसाधित किया जाएगा)।
DstHostIs("www.reddit.com") एक ReqCondition लौटाएगा जो true लौटाता है जब अनुरोध "www.reddit.com" पर निर्देशित होता है।
होस्ट समानता जाँच केस-असंवेदनशील है, DNS रिज़ॉल्वर के व्यवहार को दर्शाने के लिए, इसलिए भले ही उपयोगकर्ता "www.rEdDit.com" टाइप करे, तुलना शर्त को संतुष्ट करेगी।
जब समय सुबह 8:00 बजे से शाम 5:59 बजे के बीच होता है, तो हम DoFunc() में सीधे एक प्रतिक्रिया लौटाते हैं, इसलिए दूरस्थ गंतव्य को अनुरोध प्राप्त नहीं होगा और क्लाइंट को "Don't waste your time!" प्रतिक्रिया मिलेगी।
import "github.com/elazarl/goproxy"
examples फ़ोल्डर में प्रॉक्सी उपयोग के कुछ उदाहरण हैं, जो सबसे सामान्य मामलों को कवर करते हैं। उन पर एक नज़र डालें और शुभकामनाएँ!
प्रॉक्सी के व्यवहार में हेरफेर करने के लिए 3 विभिन्न प्रकार के हैंडलर हैं, जो निम्नानुसार हैं:
// handler called after receiving HTTP CONNECT from the client, and
// before proxy establishes connection with the destination host
httpsHandlers []HttpsHandler
// handler called before proxy sends HTTP request to destination host
reqHandlers []ReqHandler
// handler called after proxy receives HTTP Response from destination host,
// and before proxy forwards the Response to the client
respHandlers []RespHandler
आप किस चीज़ में हेरफेर करना चाहते हैं, इसके आधार पर, पिछली सूचियों में से प्रत्येक में हैंडलर जोड़ने के तरीके हैं:
// Add handlers to httpsHandlers
proxy.OnRequest(some ReqConditions).HandleConnect(YourHandlerFunc())
// Add handlers to reqHandlers
proxy.OnRequest(some ReqConditions).Do(YourReqHandlerFunc())
// Add handlers to respHandlers
proxy.OnResponse(some RespConditions).Do(YourRespHandlerFunc())
उदाहरण:
// This rejects the HTTPS request to *.reddit.com during HTTP CONNECT phase.
// Reddit URL check is case-insensitive because of (?i), so the block will work also if the user types something like rEdDit.com.
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("(?i)reddit.*:443$"))).HandleConnect(goproxy.AlwaysReject)
// Be careful about this example! It shows you a common error that you
// need to avoid.
// This will NOT reject the HTTPS request with URL ending with .gif because,
// if the scheme is HTTPS, the proxy will receive only URL.Hostname
// and URL.Port during the HTTP CONNECT phase.
proxy.OnRequest(goproxy.UrlMatches(regexp.MustCompile(`.*gif$`))).HandleConnect(goproxy.AlwaysReject)
// To fix the previous example, here there is the correct way to manipulate
// an HTTP request using URL.Path (target path) as a condition.
proxy.OnRequest(goproxy.UrlMatches(regexp.MustCompile(`.*gif$`))).Do(YourReqHandlerFunc())
यदि प्रॉक्सी के माध्यम से अनुरोध को संभालते समय कोई त्रुटि होती है, तो डिफ़ॉल्ट रूप से प्रॉक्सी त्रुटि संदेश को बॉडी सामग्री के रूप में HTTP त्रुटि 500 (आंतरिक सर्वर त्रुटि) लौटाता है।
यदि आप इस व्यवहार को ओवरराइड करना चाहते हैं, तो आप अपना स्वयं का RespHandler परिभाषित कर सकते हैं जो त्रुटि प्रतिक्रिया को बदलता है।
संदर्भ मापदंडों में, ctx.Error में हुई त्रुटि होती है, यदि कोई है, या nil मान, यदि कोई त्रुटि नहीं हुई है।
आप इसे अपनी इच्छानुसार संभाल सकते हैं, जिसमें बॉडी के रूप में कस्टम JSON लौटाना शामिल है। त्रुटि हैंडलर का उदाहरण:
proxy.OnResponse().DoFunc(func(resp *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
var dnsError *net.DNSError
if errors.As(ctx.Error, &dnsError) {
// Do not leak our DNS server's address
dnsError.Server = "<server-redacted>"
return goproxy.NewResponse(ctx.Req, goproxy.ContentTypeText, http.StatusBadGateway, dnsError.Error())
}
return resp
})
यदि लक्ष्य दूरस्थ सर्वर (या प्रॉक्सी क्लाइंट) को डेटा भेजते समय कोई त्रुटि होती है, तो त्रुटि को संभालने के लिए proxy.ConnectionErrHandler को बुलाया जाता है, यदि मौजूद है, अन्यथा एक डिफ़ॉल्ट हैंडलर का उपयोग किया जाएगा।
त्रुटि को फ़ंक्शन पैरामीटर के रूप में पारित किया जाता है न कि प्रॉक्सी संदर्भ के अंदर, इसलिए आपको इस हैंडलर में ctx.Error फ़ील्ड की जाँच नहीं करनी पड़ती है।
इस हैंडलर में आपके पास प्रॉक्सी क्लाइंट के साथ कच्चे कनेक्शन तक पहुँच है (एक io.Writer के रूप में), इसलिए आप आवश्यकता पड़ने पर उस पर कोई भी HTTP डेटा भेज सकते हैं, जिसमें त्रुटि डेटा शामिल है।
कोई गारंटी नहीं है कि कनेक्शन पहले ही बंद नहीं हो गया है, इसलिए Write() एक त्रुटि लौटा सकता है।
त्रुटि हैंडलर कॉल के बाद कनेक्शन प्रॉक्सी लाइब्रेरी द्वारा स्वचालित रूप से बंद कर दिया जाएगा, इसलिए आपको इसके बारे में चिंता करने की आवश्यकता नहीं है।
यह प्रोजेक्ट 10 साल पहले बनाया गया था, और परिपक्वता के चरण तक पहुँच गया है। इसे सुरक्षित रूप से प्रोडक्शन में उपयोग किया जा सकता है, और कई प्रोजेक्ट पहले से ही ऐसा करते हैं।
यदि भविष्य में कोई ब्रेकिंग चेंज होता है, तो Go मॉड्यूल का एक नया संस्करण जारी किया जाएगा (जैसे v2)।