SSD Nodes Learn Hosting plans →
गाइड Matt Connorलेखक: Matt Connor

HTTP क्या है: सर्वर एडमिन के लिए पूरी जानकारी

HTTP प्रोटोकॉल के काम करने का तरीका, status codes, headers और nginx logs के बारे में जानें। इस गाइड में HTTP/3 और TLS के महत्व को विस्तार से समझाया गया है।

HTTP क्या है?

HTTP (hypertext transfer protocol) उन नियमों का समूह है जिनका उपयोग क्लाइंट और वेब सर्वर किसी चीज़ का अनुरोध करने और उसे वापस भेजने के लिए करते हैं। क्लाइंट एक अनुरोध भेजता है: एक method जैसे कि GET, एक path जैसे कि /pricing, एक protocol version, headers की एक सूची, और कभी-कभी एक body। सर्वर 200 जैसे status code के साथ उत्तर देता है, जिसके बाद उसके अपने headers और आमतौर पर एक body होती है। आपके सर्वर पर हर page view और हर API (application programming interface) कॉल इसी एक एक्सचेंज का दोहराव है।

HTTP अपनी कोई state नहीं रखता है। सर्वर को याद नहीं रहता कि आपने एक सेकंड पहले क्या पूछा था, इसलिए जो कुछ भी मेमोरी की तरह व्यवहार करता है, उदाहरण के लिए login session, वह हर एक अनुरोध पर एक header में ले जाया जाता है। यह एक गुण आगे दी गई अधिकांश बातों की व्याख्या करता है: caching पूरी तरह से header पर आधारित है, और एक load balancer आपके अगले अनुरोध को बिना कुछ तोड़े किसी अलग backend पर भेज सकता है।

नीचे दी गई हर चीज़ सर्वर साइड से उस मॉडल का स्वरूप है, जो आपके access log और nginx config में दिखाई देता है।

एक raw request और response, annotated

यहाँ एक पूर्ण HTTP/1.1 request दिया गया है। एक खाली लाइन headers को समाप्त करती है, और उस लाइन के बाद जो कुछ भी है वह body है। एक GET में सामान्यतः कोई body नहीं होती है।

GET /pricing HTTP/1.1
Host: example.com
User-Agent: curl/8.5.0
Accept: */*
Accept-Encoding: gzip
  • GET वह method है, जो बताता है कि आप क्या करवाना चाहते हैं। GET डेटा पढ़ता है, POST डेटा भेजता है, PUT डेटा को बदलता (replace) है, DELETE डेटा को हटाता है, HEAD body के बिना GET के headers मांगता है।
  • /pricing वह path है। Hostname request line का हिस्सा नहीं होता है, इसीलिए अगला header मौजूद होता है।
  • HTTP/1.1 वह protocol version है जिसका उपयोग client कर रहा है।
  • Host: example.com उस site का नाम बताता है जिसे client चाहता है। HTTP/1.1 के लिए यह अनिवार्य है, इसलिए nginx बिना इसके आने वाले request का उत्तर 400 Bad Request के साथ देता है।
  • बाकी headers प्राथमिकताएं हैं। Accept-Encoding: gzip बताता है कि client decompress कर सकता है, इसलिए server को body compress करने की अनुमति है।

Response का आकार भी समान होता है, जिसमें सबसे ऊपर एक status line होती है।

HTTP/1.1 200 OK
Date: Thu, 06 Aug 2026 09:12:44 GMT
Server: nginx
Content-Type: text/html; charset=utf-8
Content-Length: 5310
Cache-Control: public, max-age=300

<!doctype html>...
  • 200 OK status code और उसका reason phrase है। Code ही महत्वपूर्ण है। Phrase केवल सजावट है और clients इसे अनदेखा कर देते हैं।
  • Content-Type client को बताता है कि आने वाले bytes के साथ क्या करना है।
  • Content-Length bytes में body का आकार है, ताकि client को पता चल सके कि body कहाँ समाप्त होती है। जब आकार पहले से ज्ञात न हो, तो server इसके बजाय Transfer-Encoding: chunked भेजता है और शून्य लंबाई के chunk के साथ अंत को चिह्नित करता है।
  • Cache-Control browser और बीच के किसी भी cache को बताता है कि वे इस response को कब तक fresh मान सकते हैं। एक बार जब इसकी आयु max-age seconds से अधिक हो जाती है, तो यह stale हो जाता है, जिसका अर्थ यह नहीं है कि इसे हटा दिया गया है: एक cache stale copy को रख सकता है और पूरी body को फिर से download करने के बजाय आपके server के साथ उसे revalidate कर सकता है।
  • Headers के बाद की खाली लाइन उन्हें body से अलग करती है, दोनों दिशाओं में।

Header के नाम case insensitive होते हैं, और प्रत्येक लाइन एक carriage return और उसके बाद line feed के साथ समाप्त होती है, न कि केवल एक newline के साथ। आप इन्हें हाथ से टाइप नहीं करेंगे, लेकिन packet capture में आप इनका सामना करेंगे।

एक वास्तविक pair को देखने के लिए, अपनी किसी site पर इसे चलाएं:

curl -sS -o /dev/null -D - https://example.com/

-D - response headers को आपके terminal पर लिखता है और -o /dev/null body को हटा देता है। curl -I के बजाय इसे प्राथमिकता दें, क्योंकि -I एक HEAD request भेजता है। एक application server जो HEAD को GET से अलग तरह से handle करता है (और कई ऐसा करते हैं), वह आपको ऐसे headers दिखाएगा जो कोई browser कभी प्राप्त नहीं करता। curl -v दोनों पक्षों को print करता है, जिसमें request lines को > और response lines को < के साथ चिह्नित किया जाता है।

आपके nginx access log में request line कैसी दिखती है

nginx एक combined log format प्रदान करता है, और इसकी परिभाषा इस प्रकार है:

log_format combined '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';

इसके द्वारा उत्पन्न एक पंक्ति:

203.0.113.45 - - [06/Aug/2026:09:12:44 +0000] "GET /pricing HTTP/1.1" 200 5310 "https://example.com/" "Mozilla/5.0 (X11; Linux x86_64) Chrome/127.0.0.0 Safari/537.36"
  • 203.0.113.45 का अर्थ $remote_addr है, वह पता जिसने TCP (transmission control protocol) connection खोला। एक proxy के पीछे यह proxy का पता होता है, न कि visitor का, जब तक कि आपने नीचे वर्णित realip module को इसे बदलने के लिए configure न किया हो।
  • पहला - एक निश्चित placeholder है। दूसरा $remote_user है, जो केवल तभी भरा जाता है जब HTTP basic authentication का उपयोग हो रहा हो।
  • "GET /pricing HTTP/1.1" का अर्थ $request है, जो पूरी मूल request line है। nginx के default log escaping के साथ, double quote, backslash और 32 से कम या 126 से अधिक के किसी भी byte को \xXX के रूप में लिखा जाता है, इसलिए यह पंक्ति सटीक है लेकिन हमेशा byte-for-byte नहीं होती।
  • 200 वह status है जो आपके server ने return किया, न कि वह status जो visitor ने देखा।
  • 5310 का अर्थ $body_bytes_sent है, केवल body का आकार। Response headers की गिनती नहीं होती, इसलिए यह संख्या वास्तव में भेजे गए bytes से हमेशा कम होती है।
  • अंतिम दो quoted fields Referer और User-Agent हैं। दोनों client से आते हैं, इसलिए दोनों में कुछ भी हो सकता है।

Junk data भी escaped रूप में log हो जाता है। एक client जो आपके plaintext port 80 पर TLS (transport layer security) में बात करता है, वह एक 400 पंक्ति छोड़ता है जिसकी request field "\x16\x03\x01\x02\x00\x01" जैसे escaped bytes से शुरू होती है। \x16 TLS handshake record type है, इसलिए वे bytes एक ClientHello की शुरुआत हैं, न कि कोई request line। आपका server सही ढंग से व्यवहार कर रहा है। कोई चीज़ HTTPS को HTTP port की ओर point कर रही है।

अपने log format में $server_protocol भी जोड़ें। यह HTTP/1.1, HTTP/2.0 या HTTP/3.0 प्रिंट करता है, और यह साबित करने का सबसे तेज़ तरीका है कि protocol परिवर्तन वास्तव में प्रभावी हो गया है।

जब आपकी अपनी साइट ये status codes return करे, तो उनका क्या अर्थ होता है

पहला अंक class को दर्शाता है, और आपको सबसे पहले class को ही पढ़ना चाहिए।

2xx का अर्थ है कि यह सफल रहा। सामान्य read के लिए 200 OK। किसी ऐसी चीज़ को बनाने के बाद POST, 201 Created मिलता है। 204 No Content का अर्थ है सफलता, लेकिन वापस भेजने के लिए कुछ नहीं है, जो आमतौर पर DELETE का उत्तर होता है।

3xx का अर्थ है कि कहीं और देखें। 301 स्थायी होता है और browsers इसे गहराई से cache करते हैं, कभी-कभी तब तक जब तक user अपनी profile clear न कर दे, इसलिए गलत hostname पर point करने वाला 301 ठीक करना बहुत कठिन होता है। जब आप redirect की testing कर रहे हों, तब 302 का उपयोग करें। 304 Not Modified एक सफलता है, error नहीं: client ने एक conditional request भेजी थी, या तो If-None-Match जिसमें एक ETag (entity tag) था जिसे आप अभी भी पहचानते हैं, या If-Modified-Since जिसमें एक ऐसी तारीख थी जिसके बाद से resource में कोई बदलाव नहीं हुआ है, इसलिए आपने केवल headers भेजे और body नहीं। यदि logs 304 से भरे हैं, तो इसका मतलब है कि caching सही ढंग से काम कर रही है।

4xx का अर्थ है कि request गलत थी। 400 Bad Request का अर्थ है malformed input। 401 Unauthorized का वास्तविक अर्थ unauthenticated है, और इसमें एक WWW-Authenticate header होना चाहिए जो scheme का नाम बताए। 403 Forbidden का अर्थ है कि request समझ में आ गई थी लेकिन फिर भी उसे अस्वीकार कर दिया गया। 404 Not Found एक ऐसा path है जो मौजूद नहीं है, या जिसे server स्वीकार नहीं करना चाहता, क्योंकि कुछ applications access के बिना clients से resource छिपाने के लिए 403 के बजाय 404 का उत्तर देती हैं। 405 Method Not Allowed सही path है लेकिन गलत method के साथ, जो static file location पर POST करने पर मिलता है। 413 का अर्थ है body, nginx के client_max_body_size से बड़ी है, जो default रूप से 1 megabyte होता है, और error log में इसकी पुष्टि client intended to send too large body के साथ होती है।

Static file पर 403 का कारण लगभग हमेशा filesystem होता है, न कि कोई HTTP rule। कोई भी config बदलने से पहले /var/log/nginx/error.log पढ़ें। open() "/srv/site/index.html" failed (13: Permission denied) का अर्थ है कि nginx worker user file को पढ़ नहीं सकता, अक्सर इसलिए क्योंकि parent directory में others के लिए execute permission नहीं होती। directory index of "/srv/site/" is forbidden का अर्थ है कि path एक ऐसी directory पर resolve हुआ जिसमें कोई index file नहीं है जबकि autoindex off है।

5xx का अर्थ है कि आपकी तरफ से कुछ टूट गया है। 500 एक सामान्य server error है, और आपकी अपनी साइट पर यह आमतौर पर आपकी application में किसी unhandled error की ओर इशारा करता है। 502 Bad Gateway का अर्थ है कि nginx को upstream से कोई उपयोगी response नहीं मिला, और error log कारण बताता है: connect() failed (111: Connection refused) while connecting to upstream का अर्थ है कि proxy_pass पर दिए गए address पर कोई service listening नहीं है। 504 Gateway Timeout का अर्थ है कि nginx ने upstream का इंतज़ार करना छोड़ दिया। सामान्य स्थिति वह है जहाँ upstream ने connection स्वीकार किया लेकिन proxy_read_timeout (default रूप से 60 seconds) के भीतर कुछ नहीं कहा, जिसे log में upstream timed out (110: Connection timed out) while reading response header from upstream के रूप में record किया जाता है। एक connection attempt जो proxy_connect_timeout (default रूप से 60 seconds) के भीतर पूरी नहीं होती, वह भी 504 पर समाप्त होती है, और log line फिर while connecting to upstream पर समाप्त होती है। 503 Service Unavailable का अर्थ है कि server अस्थायी रूप से request को संभालने में असमर्थ है, आमतौर पर इसलिए क्योंकि वह overloaded है या scheduled maintenance के लिए down है। ध्यान दें कि nginx का अपना rate limiter 503 return करता है, क्योंकि limit_req_status default रूप से 503 होता है। यदि आप अपने log में 429 Too Many Requests ढूँढ रहे हैं और उसके बजाय 503 मिल रहा है, तो यही कारण है। सटीक code प्राप्त करने के लिए limit_req_status 429; सेट करें।

सर्वर चलाते समय महत्वपूर्ण headers

Host साइट का चयन करता है। एक IP address सैकड़ों hostnames को serve कर सकता है, और nginx यह तय करने के लिए कि कौन सा server block उत्तर देगा, Host की तुलना server_name से करता है। यदि कुछ भी मेल नहीं खाता है, तो nginx default server का उपयोग करता है, जो उस address और port पर listening करने वाला पहला block होता है, जब तक कि किसी अन्य को default_server के रूप में चिह्नित न किया गया हो। एक नए virtual host से गलत साइट प्राप्त होने का कारण लगभग हमेशा यही होता है: नाम मेल नहीं खाया, इसलिए request default पर चली गई। DNS को छुए बिना इसका परीक्षण करें:

curl -sS -o /dev/null -D - -H 'Host: app.example.com' http://127.0.0.1/

User-Agent क्लाइंट द्वारा लिखा गया एक स्व-विवरण है, और यह free text है। logs पढ़ते समय इसे एक संकेत के रूप में उपयोग करें। इसे कभी भी नियंत्रण के रूप में उपयोग न करें, क्योंकि जो क्लाइंट इसके बारे में झूठ बोलना चाहता है वह आसानी से ऐसा कर सकता है, इसलिए User-Agent द्वारा scraper को ब्लॉक करना केवल विनम्र लोगों को ही बाहर करता है।

Content-Type यह तय करता है कि bytes की व्याख्या कैसे की जाए: API request के लिए application/json, एक पेज के लिए text/html; charset=utf-8। nginx file extensions को /etc/nginx/mime.types के साथ types में map करता है, और packaged nginx.conf, default_type application/octet-stream; को सेट करता है, इसलिए जिस extension को nginx नहीं जानता, वह file render होने के बजाय download के रूप में दी जाती है। इसका दृश्य लक्षण एक ऐसा पेज है जो बिना styling के लोड होता है जबकि browser console Refused to apply style from ... because its MIME type ('text/plain') is not a supported stylesheet MIME type प्रिंट करता है। MIME का अर्थ multipurpose internet mail extensions है, जो वह naming scheme है जिससे वे type strings आती हैं।

Cache-Control वह तरीका है जिससे आप अपने सर्वर और पाठक के बीच हर cache को नियंत्रित करते हैं। public, max-age=31536000, immutable उन assets के लिए उपयुक्त है जिनके filename में content hash होता है, क्योंकि content बदलने पर नाम बदल जाता है। no-store किसी भी user-specific चीज़ पर लागू होता है, क्योंकि एक shared cache जो logged-in पेज को रखता है, वह उसे अगले व्यक्ति को दे देगा जो उसी URL के लिए अनुरोध करता है। private बीच की सेटिंग है: browser इसे रख सकता है, लेकिन shared cache नहीं रख सकता।

X-Forwarded-For इसलिए मौजूद है क्योंकि एक proxy visitor को छिपा देता है। एक बार जब request reverse proxy से गुजरती है, तो $remote_addr proxy का address होता है, इसलिए आपके logs, आपकी geolocation और आपकी rate limiting सभी एक ही client को देखते हैं जब तक कि आप मूल address को restore नहीं कर देते। Proxy को मूल address को आगे बढ़ाना होता है:

proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

इसके बाद receiving server को यह निर्देश देना आवश्यक है कि वह इस पर भरोसा करे, और यह भी स्पष्ट करना होगा कि उसे वास्तव में किस पर भरोसा करना है:

set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;

ये दो directives nginx के realip module से संबंधित हैं। यह $remote_addr को forwarded address से बदल देता है और connection के अपने address को $realip_remote_addr में रखता है। यदि आप nginx को स्वयं compile करते हैं, तो --with-http_realip_module जोड़ें, क्योंकि यह module डिफ़ॉल्ट रूप से build नहीं होता है।

केवल उन ranges को सूचीबद्ध करें जिन्हें आप नियंत्रित करते हैं। X-Forwarded-For plain text है जिसे कोई भी client भेज सकता है, इसलिए set_real_ip_from 0.0.0.0/0; एक visitor को वह address चुनने देता है जिसे आप log करते हैं और जिसे आपका rate limiter count करता है।

X-Forwarded-Proto एक विशिष्ट और बहुत सामान्य विफलता को रोकता है। आपका proxy TLS को समाप्त करता है और request को plain HTTP पर application को forward करता है। Application एक plain request देखता है, तय करता है कि visitor को HTTPS पर होना चाहिए, और 301 https://example.com/ के साथ उत्तर देता है। Browser इसका पालन करता है, proxy फिर से TLS को समाप्त करता है और फिर से plain HTTP forward करता है, और यह loop तब तक दोहराता है जब तक कि browser ERR_TOO_MANY_REDIRECTS के साथ हार नहीं मान लेता। X-Forwarded-Proto: https भेजने से application को पता चलता है कि visitor पहले से ही HTTPS पर है, इसलिए यह redirect करना बंद कर देता है।

HTTP/1.1 बनाम HTTP/2 बनाम HTTP/3: आपके लिए क्या बदलता है

HTTP/1.1 टेक्स्ट-आधारित है, और व्यावहारिक रूप से यह प्रति कनेक्शन एक समय में एक ही request को संभालता है। Connection: keep-alive अगले request को उसी TCP कनेक्शन का पुन: उपयोग करने की अनुमति देता है, जिससे सेटअप की लागत बचती है, लेकिन responses अभी भी उसी क्रम में वापस आते हैं जिस क्रम में उनका अनुरोध किया गया था। यह प्रोटोकॉल pipelining की भी अनुमति देता है, जहाँ एक client उत्तरों की प्रतीक्षा किए बिना कई requests भेज सकता है, लेकिन क्रम का नियम अभी भी लागू होता है और कोई भी आधुनिक ब्राउज़र डिफ़ॉल्ट रूप से pipelining को चालू नहीं रखता है। एक धीमी response उसके पीछे कतारबद्ध हर चीज़ को रोक देती है। इसे head-of-line blocking कहते हैं, और ब्राउज़र एक ही समय में एक ही hostname के लिए कई कनेक्शन खोलकर इसे हल करते हैं।

HTTP/2 उन्हीं methods और status codes को बनाए रखता है, और framing को बाइनरी में बदल देता है। कई requests एक कनेक्शन को स्वतंत्र streams के रूप में साझा करते हैं, और बार-बार आने वाले header टेक्स्ट को कंप्रेस किया जाता है, जो महत्वपूर्ण है क्योंकि एक आधुनिक request में बहुत अधिक डेटा होता है। कनेक्शन अभी भी TCP है, इसलिए एक खोया हुआ पैकेट उस कनेक्शन पर हर stream को तब तक रोक देता है जब तक कि retransmission न आ जाए। Head-of-line blocking खत्म नहीं हुई। यह HTTP से नीचे transport layer पर चली गई। Server push HTTP/2 का हिस्सा था और व्यावहारिक रूप से अब समाप्त हो चुका है, क्योंकि Chrome ने 2022 में इसके लिए समर्थन हटा दिया था।

HTTP/3 फिर से उन्हीं semantics को बनाए रखता है और TCP को QUIC से बदल देता है, जो UDP (user datagram protocol) पर बना एक transport है। QUIC streams पूरी तरह से स्वतंत्र हैं, इसलिए एक खोया हुआ पैकेट केवल उसी stream को रोकता है जिससे वह संबंधित था। TLS 1.3 को ऊपर से जोड़ने के बजाय QUIC handshake में ही बनाया गया है, इसलिए एक नए कनेक्शन को कम round trips की आवश्यकता होती है। इसके दो व्यावहारिक परिणाम होते हैं: आपके सर्वर द्वारा HTTP/3 के लिए उपयोग किया जाने वाला UDP port रास्ते में आने वाले प्रत्येक firewall में खुला होना चाहिए, और कोई भी नेटवर्क जो UDP को थ्रॉटल या ब्लॉक करता है, वह clients को वापस HTTP/2 पर धकेल देगा। वह port आमतौर पर 443 होता है, लेकिन प्रोटोकॉल सर्वर को किसी भी UDP port का उपयोग करने की अनुमति देता है, क्योंकि जो विज्ञापन ब्राउज़रों को HTTP/3 की ओर निर्देशित करता है, वह हमेशा port का स्पष्ट उल्लेख करता है।

आपके लिए ठोस रूप से क्या बदलता है। ब्राउज़र आमतौर पर HTTP/3 से शुरू नहीं होते हैं। वे HTTP/2 या HTTP/1.1 पर कनेक्ट होते हैं, response पर Alt-Svc: h3=":443"; ma=86400 header देखते हैं, और उस host के बाद के कनेक्शन के लिए HTTP/3 का उपयोग करते हैं। इसका अपवाद DNS में एक HTTPS record है जिसका alpn मान h3 को सूचीबद्ध करता है, जो Firefox जैसे ब्राउज़र को पहले ही कनेक्शन पर HTTP/3 खोलने की अनुमति देता है। वह record एक अतिरिक्त संकेत है, प्रतिस्थापन नहीं, इसलिए header कोई वैकल्पिक सजावट नहीं है। यह खोज का मुख्य तंत्र है। nginx में, HTTP/2 संस्करण 1.25.1 में अपना स्वयं का directive बन गया (server ब्लॉक के अंदर http2 on;, जो पुराने listen ... http2 पैरामीटर की जगह लेता है), और QUIC mainline 1.25.0 में आया, जहाँ एक HTTP/3 साइट को सामान्य listen 443 ssl; के साथ listen 443 quic reuseport; की आवश्यकता होती है। HTTP/3 मॉड्यूल डिफ़ॉल्ट रूप से निर्मित नहीं होता है (--with-http_v3_module), और nginx का दस्तावेज़ीकरण अभी भी इसके समर्थन को प्रायोगिक (experimental) बताता है।

Proxies यहाँ परिपक्वता में भिन्न हैं, और इसे उस संस्करण के साथ जांचना उचित है जिसे आप वास्तव में चला रहे हैं। नवंबर 2026 तक, Caddy बिना किसी कॉन्फ़िगरेशन के डिफ़ॉल्ट रूप से HTTP/3 प्रदान करता है। nginx को ऊपर वर्णित स्पष्ट quic listener और Alt-Svc header की आवश्यकता होती है। Traefik इसे एक स्पष्ट http3 विकल्प के माध्यम से प्रत्येक entry point पर सक्षम करता है। यदि आप कई Docker ऐप्स के सामने Traefik पर TLS समाप्त करते हैं, तो आपके आगंतुकों को मिलने वाला प्रोटोकॉल संस्करण वहीं तय हो जाता है, और प्रॉक्सी से आपके कंटेनर तक का hop आमतौर पर सादा HTTP/1.1 होता है, चाहे ब्राउज़र ने कुछ भी negotiate किया हो।

मानने के बजाय सत्यापित करें। curl --http3 -sS -o /dev/null -D - https://example.com/ केवल तभी काम करता है जब curl -V अपनी विशेषताओं में HTTP3 को सूचीबद्ध करता है, और अधिकांश वितरण बिल्ड में यह शामिल नहीं होता है। विश्वसनीय जांच आपका अपना log है: format में $server_protocol जोड़ें और पढ़ें कि वास्तविक ब्राउज़र क्या negotiate करते हैं। इससे पहले, पुष्टि करें कि आपके quic listener द्वारा उपयोग किया जाने वाला UDP port, ऊपर कॉन्फ़िगरेशन में 443, वास्तव में खुला है, क्योंकि एक firewall जो केवल TCP 443 की अनुमति देता है, वह HTTP/3 को चुपचाप विफल होने देगा जबकि साइट HTTP/2 पर काम करती रहेगी। आपके Linux सर्वर पर कौन से ports खुले हैं और सुन रहे हैं, यह जानना जांचने वाली पहली चीज है।

HTTPS: HTTP एक प्रोटोकॉल है, TLS उसका आवरण है

HTTPS कोई अलग प्रोटोकॉल नहीं है। यह वही HTTP रिक्वेस्ट और स्टेटस कोड हैं जो एक TLS सेशन के भीतर भेजे जाते हैं। Port 80 पर ये बिना किसी एन्क्रिप्शन के भेजे जाते हैं और port 443 पर एन्क्रिप्टेड रूप में। TLS हैंडशेक पहले पूरा होता है, उसके बाद ही HTTP रिक्वेस्ट एन्क्रिप्टेड चैनल के अंदर जाती है। इसी क्रम के कारण सर्टिफिकेट संबंधी समस्या का कोई स्टेटस कोड नहीं होता: विफलता एक भी HTTP बाइट भेजे जाने से पहले ही हो जाती है, इसलिए कोई रिस्पॉन्स कोड नहीं होता।

एक सर्वर पर कई साइट्स होस्ट करते समय क्रम का एक विवरण महत्वपूर्ण है। सर्टिफिकेट का चयन SNI (server name indication) का उपयोग करके किया जाता है, जो TLS हैंडशेक का एक फील्ड है। यह किसी भी HTTP हेडर के मौजूद होने से पहले होस्टनेम को स्पष्ट रूप से ले जाता है। इसलिए सर्वर पहले SNI से सर्टिफिकेट चुनता है, और फिर दूसरे चरण में Host हेडर से वर्चुअल होस्ट चुनता है। ये दो अलग-अलग लुकअप हैं जो सामान्यतः एक-दूसरे से मेल खाते हैं। जब वे मेल नहीं खाते, तो ब्राउज़र NET::ERR_CERT_COMMON_NAME_INVALID जैसा नेम मिसमैच दिखाता है और कोई रिक्वेस्ट नहीं भेजता, क्योंकि आपके डिफ़ॉल्ट सर्वर का सर्टिफिकेट ऐसे नाम के लिए पेश किया गया था जिसे वह कवर नहीं करता।

एक पब्लिक साइट के लिए, एक वास्तविक सर्टिफिकेट प्राप्त करें और उसे अपने आप रिन्यू होने दें। Certbot with Let's Encrypt on nginx सर्टिफिकेट पाथ को आपके सर्वर ब्लॉक में लिख देता है और आपके लिए रिन्यूअल टाइमर इंस्टॉल कर देता है। ऐसे होस्टनेम के लिए जिसे कोई पब्लिक अथॉरिटी वैलिडेट नहीं कर सकती, जैसे कि कोई इंटरनल नाम या आपके अपने नेटवर्क पर कोई bare IP एड्रेस, a self-signed certificate on Ubuntu एक ईमानदार विकल्प है, बशर्ते आप यह स्वीकार करें कि हर क्लाइंट को उस पर भरोसा करने के लिए कहना होगा।

एक बार TLS काम करने लगे, तो port 80 के सभी ट्रैफिक को port 443 पर भेजें:

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

Strict-Transport-Security को तभी जोड़ें जब आप पूरी तरह सुनिश्चित हों। add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always; हेडर ब्राउज़रों को उस होस्टनेम के लिए दो साल तक plain HTTP को अस्वीकार करने के लिए कहता है, और वे इसे अपने कैश से मानते हैं। इसका मतलब है कि बाद में हेडर को हटाने से यह सेटिंग वापस नहीं बदलती। शुरुआत में max-age को कुछ घंटों के लिए रखें, पुष्टि करें कि हर सबडोमेन वास्तव में HTTPS पर है, और फिर इसे बढ़ाएं।

FAQ

HTTP और HTTPS में क्या अंतर है?

HTTPS, TLS (transport layer security) session के भीतर भेजा गया HTTP है। इसके methods और status codes समान होते हैं। अंतर यह है कि client और TLS terminate करने वाले बिंदु के बीच bytes encrypted होते हैं, और default port 80 से बदलकर 443 हो जाता है। चूंकि TLS handshake पहली HTTP byte भेजे जाने से पहले पूरा हो जाता है, इसलिए certificate failure कभी भी status code उत्पन्न नहीं करता है। यही कारण है कि browser certificate warning में 403 जैसे नंबर के बजाय NET::ERR_CERT_COMMON_NAME_INVALID जैसी error का नाम दिखाई देता है।

मेरी साइट 502 Bad Gateway क्यों दिखा रही है?

nginx से मिलने वाला 502 यह दर्शाता है कि nginx उस upstream से उपयोगी response प्राप्त नहीं कर सका जिसे वह proxy कर रहा है, इसलिए visitor का request सही था लेकिन nginx के पीछे कुछ गड़बड़ है। /var/log/nginx/error.log पढ़ें। connect() failed (111: Connection refused) while connecting to upstream का अर्थ है कि proxy_pass में दिए गए address और port पर कोई service listening नहीं है, इसलिए जाँचें कि application चल रही है और आपकी अपेक्षा के अनुसार bound है। no live upstreams while connecting to upstream का अर्थ है कि बार-बार विफलताओं के बाद upstream block के प्रत्येक सर्वर को down चिह्नित कर दिया गया है। इसकी तुलना 504 Gateway Timeout से करें, जिसका अर्थ है कि nginx ने upstream की प्रतीक्षा में समय समाप्त (timeout) कर दिया है, या तो proxy_connect_timeout के भीतर connection पूरा होने के लिए या proxy_read_timeout के भीतर response के लिए।

मेरा access log हर visitor के लिए एक ही IP address क्यों दिखाता है?

क्योंकि $remote_addr उस address को record करता है जिसने TCP connection खोला है, और reverse proxy या content delivery network के पीछे वह address proxy का होता है। visitor का address इसके बजाय X-Forwarded-For header में आता है। proxy पर proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; सेट करें, फिर receiving nginx पर set_real_ip_from को proxy के address range पर और real_ip_header X-Forwarded-For; सेट करें। केवल उन ranges को सूचीबद्ध करें जिन्हें आप नियंत्रित करते हैं, क्योंकि वह header ऐसा text है जिसे कोई भी client भेज सकता है। इसलिए पूरे internet से उस पर भरोसा करने से visitor उस address को चुन सकता है जिसे आप log करते हैं और जिसे आप rate limit करते हैं।

क्या मुझे HTTP/2 या HTTP/3 चालू करने की आवश्यकता है?

HTTP/2 चालू करना फायदेमंद है, क्योंकि यह उस साइट पर केवल एक directive है जिसमें पहले से ही TLS है, और यह प्रति-connection request सीमा को हटा देता है जो कई छोटी फाइलों वाले पेज को धीमा बनाती है। HTTP/3 का लाभ कम और अनिश्चित है, और इसके लिए आपको एक open UDP port (आमतौर पर 443) की आवश्यकता होती है, साथ ही QUIC support के साथ एक proxy build की भी। याद रखें कि browsers आमतौर पर HTTP/3 पर तभी स्विच करते हैं जब वे पहले के response पर Alt-Svc header देखते हैं, या HTTPS DNS record देखते हैं जो h3 को सूचीबद्ध करता है। इसलिए इनमें से किसी एक के बिना, आपकी listen लाइन कुछ भी कहे, कोई बदलाव नहीं होता है। अपने log format में $server_protocol जोड़ें और उस पर समय खर्च करने से पहले मापें कि visitors वास्तव में क्या negotiate कर रहे हैं।

फाइल मौजूद होने पर भी 403 Forbidden का क्या अर्थ है?

static साइट पर 403 आमतौर पर HTTP rule के बजाय filesystem permission की समस्या होती है। open() ... failed (13: Permission denied) का /var/log/nginx/error.log में अर्थ है कि nginx worker user फाइल को पढ़ नहीं सकता है। यह अक्सर इसलिए होता है क्योंकि parent directory में others के लिए execute permission नहीं होती है, न कि इसलिए कि फाइल mode स्वयं गलत है। directory index of ... is forbidden का अर्थ है कि request एक ऐसी directory पर resolve हुई है जिसमें कोई index फाइल नहीं है जबकि autoindex बंद है। matching location block में एक स्पष्ट deny rule भी 403 लौटाता है, इसलिए जब error log में कुछ न दिखे तो उस block को पढ़ें।

क्या यह लेख उपयोगी था?

#http#https#web-server#headers#http3