- न्यूनतम कंटेनर इमेज में अक्सर curl या wget नहीं होते, इसलिए पैकेज इंस्टॉल किए बिना आंतरिक सर्विस कनेक्टिविटी जाँचने का वैकल्पिक तरीका उपयोगी होता है
- Bash का
/dev/tcp/host/port रीडायरेक्शन TCP socket खोल सकता है, इसलिए HTTP/1.1 अनुरोध स्ट्रिंग को सीधे लिखकर भेजा जा सकता है और response पढ़ा जा सकता है
/dev/tcp फ़ाइलसिस्टम path नहीं बल्कि Bash की आंतरिक सुविधा है, इसलिए ls /dev/tcp या दूसरे shell के सामान्य फ़ाइल access तरीके से यह काम नहीं करता
- यह तरीका redirect, chunked response, compression, retry, TLS को संभालने वाला सरल debugging तरीका नहीं है, और
Connection: close के बिना cat प्रतीक्षा में अटक सकता है
- रोज़मर्रा के HTTP कामों के लिए curl सही है, लेकिन टूल जोड़ना मुश्किल हो ऐसे छोटे कंटेनर में तेज़ कनेक्शन जाँच के लिए यह पर्याप्त है
Bash फ़ाइल डिस्क्रिप्टर से HTTP अनुरोध लिखना
- आंतरिक Docker नेटवर्क में किसी दूसरी सर्विस के
/health endpoint तक पहुँच हो रही है या नहीं, यह जाँचना था, लेकिन इमेज में curl या wget नहीं थे
- Bash TCP socket को फ़ाइल डिस्क्रिप्टर से जोड़ सकता है, इसलिए नीचे की तरह HTTP अनुरोध सीधे लिखकर भेजा जा सकता है
exec 3<>/dev/tcp/service/8642
printf 'GET /health HTTP/1.1\r\nHost: service\r\nConnection: close\r\n\r\n' >&3
cat <&3
service ऐसा hostname होना चाहिए जिसे मौजूदा execution location से resolve और reach किया जा सके
- यह Docker नेटवर्क में सेट किया गया container या service name हो सकता है
- कोई resolve होने वाला DNS name भी इस्तेमाल किया जा सकता है
- host और port को अपने environment के अनुसार बदलना होगा
- response output में status line, headers, खाली पंक्ति और body साथ में शामिल होंगे
- header जोड़ना हो तो अनुरोध समाप्त करने वाली खाली पंक्ति से पहले
\r\n पर समाप्त होने वाली और पंक्तियाँ जोड़ दें
exec 3<>/dev/tcp/service/8642
printf 'GET /v1/models HTTP/1.1\r\nHost: service\r\nAuthorization: Bearer %s\r\nConnection: close\r\n\r\n' "$API_KEY" >&3
cat <&3
/dev/tcp वास्तव में फ़ाइल क्यों नहीं है
/dev/tcp कोई वास्तविक device file नहीं, बल्कि Bash द्वारा संभाला जाने वाला रीडायरेक्शन है
- डिस्क पर यह path मौजूद नहीं होता, इसलिए
ls /dev/tcp विफल होगा
- दूसरे shell में
cat /dev/tcp/... चलाने पर भी त्रुटि मिलेगी
- Bash manual के अनुसार,
/dev/tcp/host/port में host वैध hostname या internet address हो और port पूर्णांक port number या service name हो, तो Bash TCP socket खोलने की कोशिश करता है
- Bash DNS lookup और
connect(2) करता है, और exec 3<> उस socket को फ़ाइल डिस्क्रिप्टर 3 से जोड़ देता है ताकि पढ़ना और लिखना दोनों संभव हों
HTTP क्लाइंट का विकल्प नहीं, अस्थायी जाँच का टूल
- यह तरीका कोई वास्तविक HTTP client नहीं है, इसलिए redirect, chunked response, compression, retry, TLS आदि को संभालता नहीं है
Connection: close header महत्वपूर्ण है
- इसके बिना server HTTP/1.1 के default व्यवहार के अनुसार कनेक्शन खुला रख सकता है
- इस स्थिति में
cat <&3 EOF का इंतज़ार करता रह सकता है और समाप्त नहीं होगा
timeout 6 bash -c '...' जैसी wrapping करने से उस स्थिति के लिए भी तैयार रहा जा सकता है जहाँ कनेक्शन बंद न हो
/dev/tcp raw socket खोलने का तरीका है, इसलिए यह केवल plain-text HTTP पर लागू होता है; https के लिए openssl s_client चाहिए
- यह POSIX feature नहीं, Bash feature है, इसलिए Debian के
/bin/sh यानी dash या zsh में इसका उपयोग नहीं किया जा सकता; bash को सीधे चलाना होगा
- Bash build के समय
--enable-net-redirections से सक्षम होने वाला compile-time option है
- निष्कर्षतः, यह curl का सामान्य विकल्प कम और इंस्टॉलेशन जोड़े बिना काम चलाना हो ऐसे छोटे कंटेनर में तेज़ी से कनेक्टिविटी जाँचने का साधन ज़्यादा है
1 टिप्पणियां
Hacker News की राय
90 के दशक के आखिर में बचपन में यह जानकर झटका लगा था कि
telnetसे 80, 25, 110 ports पर connect करके server से सीधे बात की जा सकती हैसाधारण
GET / HTTP/1.1request हाथ से टाइप कर सकते थे, या port 25 परHELO,mail-from,mail-toसे mail भेज सकते थे, और POP3 से mailbox listing और individual messages ला सकते थेयही अनुभव इस समझ की शुरुआत था कि “कोई जादू नहीं है”; computer का हर हिस्सा इंसानों ने बनाया है, और मेहनत करें तो एक हद तक उसे समझा जा सकता है
भविष्य में ज़्यादातर काम agents को सौंप दिए जाएंगे, लेकिन जो लोग model और safety guardrails के filters के बिना असली काम करने का तरीका सीखना चाहते हैं, उनके लिए कई systems में दिलचस्प छेद बचे रहेंगे
jacques.chirac@elysee.frजैसे address से mail भेजकर दोस्तों के सामने hacker जैसा दिखा जा सकता थायह बस structured text files बनाने, भेजने और पढ़ने के कई तरीकों के ऊपर चढ़ी हुई ढेर सारी abbreviations की परत थी
जिस दिन समझ आया कि database भी आखिर text file ही है, उस दिन थोड़ी देर बैठना पड़ा था
telnetसे POP3 और SMTP पर अलग-अलग connect करना पड़ता थाTLS भी
telnetसे नहीं होता, और कई servers HTTP requests पर सिर्फ redirect वापस देते हैंtelnetकी जगहopenssl s_clientइस्तेमाल करें तो TLS के भीतर text tunnel किया जा सकता है, लेकिन यह थोड़ा hack जैसा लगता हैअफसोस यह भी है कि आज के कई modern protocols binary encoding को prefer करते हैं, इसलिए dedicated tools के बिना wire level पर उन्हें छेड़ना मुश्किल हो गया है
फिर भी लगता है कि भविष्य में भी ऐसे लोग रहेंगे जो इसमें गहराई से उतरेंगे; डंडे से आग जलाना या मिट्टी की ईंट पकाना जैसी पुरानी skills मज़ेदार भी हैं और कभी-कभी सच में काम की भी
बल्कि AI की वजह से experiments और आसान हो गए हैं; RFC खंगाले बिना भी LLM से पूछकर, जैसे कि, आम IMAP commands का बड़ा हिस्सा सीखा जा सकता है
zshमें Bash के/dev/tcpसे अलगzsh/net/tcpऔरzsh/zftpmodules भी हैंhttps://zsh.sourceforge.io/Doc/Release/TCP-Function-System.h...
https://zsh.sourceforge.io/Doc/Release/Zsh-Modules.html#The-...
https://zsh.sourceforge.io/Doc/Release/Zftp-Function-System....
Plan 9 में सचमुच का synthetic file system
/netथा, इसलिए किसी भी program से यह काम और इससे भी ज़्यादा किया जा सकता थाकिसी दूसरी machine के
/netको 9P protocol से mount करके उसे instant VPN की तरह भी इस्तेमाल किया जा सकता था, और Linux पर 9front के साथ इसका प्रयोग किया जा सकता हैGo library में भी Plan 9 शैली के
/netके निशान दिखते हैं, शायद यह Rob Pike की विरासत हैexample.comपर यह ठीक से काम करता हैexec 3<>/dev/tcp/example.com/80से खोलें, फिरprintf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' >&3भेजें, और उसके बादcat <&3करें तोHTTP/1.1 200 OKमिलता हैआजकल ऐसे domains बहुत कम बचे हैं जो HTTPS को force नहीं करते, इसलिए ऐसे tests के लिए आखिरकार example.com पर जाना पड़ता है
example.comकाम आता हैbrowser में http://example.com खोलने पर captive portal page पर redirect हो जाता है, जिससे internet access की प्रक्रिया फिर से पूरी की जा सकती है
printfके अंदर actual newline डालें तब भी यह काम करता है\rहोना सही है, लेकिन उसे हटा दें तो भी काम चल जाता हैमज़ाक में कहा जा सकता है कि दोस्त के computer से बात करने के लिए सब
bash -i >& /dev/tcp/IP/PORT 0>&1का इस्तेमाल करते हैंBash HTTP नहीं बोलता, बल्कि TCP socket खोलने की सुविधा देता है
यहाँ किया जा रहा काम सीधे HTTP बोलना है, जो test या debugging के लिए ठीक है, और हाथ से करके देखना मज़ेदार भी हो सकता है, लेकिन असली unattended environment में ऐसा नकली HTTP client इस्तेमाल करना आखिरकार भारी पड़ सकता है
यह toy code HTTP को ठीक से parse नहीं करता, इसलिए टूट सकता है
बेशक Bash में पूरा HTTP/1.1 client भी लिखा जा सकता है, और pure Bash HTTP server भी बनाया जा सकता है: https://github.com/bahamas10/bash-web-server
कम पागलपन वाला विकल्प आम तौर पर
ncहोता है, और ज़्यादातर मामलों में वही ज़्यादा समझदारी भरा हैBash incoming connection स्वीकार करने के लिए TCP/UDP socket पर listen नहीं कर सकता
bash-web-serverproject C में लिखा socket listener build करता है, और runtime पर उसे “built-in” module की तरह dynamically load करके यह सुविधा देता है[0] https://github.com/bahamas10/bash-web-server/tree/main/loada...
ncया netcat जैसी कोई मिलती-जुलती utility बेहतर विकल्प होती, लेकिन उस समय इस्तेमाल की जा रही image में ऐसा कोई tool नहीं थाHTTP/1.1 और ज़रूरी
Hostheader आने से पहले से लोग हाथ से HTTP request टाइप करते रहे हैंगंभीर काम के लिए इसका इस्तेमाल करना पागलपन है, और Bash में web server बनाना भी वैसा ही है, लेकिन तेज़ testing के लिए यह काफ़ी अच्छा है
https://sdomi.pl/weblog/15-witchcraft-minecraft-server-in-ba...
मैंने यह तरीका Bauhinia team को CTF challenge solve करते देख कर सीखा
वह कई चरणों वाला CTF था, और शुरुआत में ROP chain से
systemshell मिल जाती थी, लेकिन वह लगभग जेल जैसा environment था जहाँ Bash के अलावा व्यावहारिक रूप से कुछ भी चलाया नहीं जा सकता थाइस्तेमाल करने लायक बस
readऔरcatजैसे command थे, इसलिएcat /dev/tcpका उपयोग किया, फिर उसे virtual terminal पर redirect किया, और उसकी सामग्री पढ़कर internal system URL निकाला और flag ढूँढ़ लियाinternal Docker network में container के बीच connectivity चेक करते समय मुझे यह तरीका मिला, क्योंकि image में न
curlथा नwgetहैरानी की बात यह थी कि Bash में
/dev/tcpहोता है, और थोड़ी shell magic से HTTP request जैसी चीज़ बनाई जा सकती हैउदाहरण के लिए
exec 3<>/dev/tcp/service/8642से खोलें, फिरprintf 'GET /health HTTP/1.1\r\nHost: service\r\nConnection: close\r\n\r\n' >&3भेजें, और उसके बादcat <&3करेंयहाँ
serviceवह hostname है जिससे जुड़ना है, और8642वह port है जिस पर HTTP की तरह बात करने की कोशिश की जा रही हैमुझे तो कोई कमी नहीं सूझती, और production image में भी मैं इसे लगभग ज़रूरी मानता हूँ
पुराने Debian और Debian-आधारित distro में यह सुविधा काम नहीं करती थी, क्योंकि virtual file के ज़रिए TCP access default रूप से disabled था
मेरी समझ के अनुसार 2009 में रुख बदला गया और यह feature enable कर दिया गया, और Bug #146464 में चर्चा और link मौजूद हैं
<https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=146464#37>
shell tool से network functionality तक सीधे पहुँचने के और भी कई तरीके हैं, जैसे
curl,wget, Perl केHEADऔरGETcommand,netcat/nc,socat,telnetआदिकिशोरावस्था में मुझे याद है कि मैं
echoसे दूसरे लोगों के/dev/pttyपर डरावने message भेजकर उन्हें चौंकाया करता थामेरे भेजे हुए message सामने वाले के खुले terminal पर जैसे जादू से प्रकट हो जाते थे
आज तक नहीं समझ पाया कि computer lab में हर client के लिए अलग account देकर भी उन्हें lock क्यों नहीं किया गया था; शायद वह उस समय VAX की सीमा रही होगी