Http और https के अनुरोध को nginx के साथ एक ही पोर्ट का उपयोग करके


16

मैं सोच रहा था कि क्या nginx उसी पोर्ट पर http और https अनुरोधों को संभालने में सक्षम है । [*]

यही मैं करने की कोशिश कर रहा हूं। मैं http अनुरोधों को संभालने वाला एक वेब सर्वर (लाइटटैप) और एक सी प्रोग्राम चला रहा हूं, जो https के माध्यम से डॉक्यूमेंट ट्री के एक विशेष सेक्शन का काम करता है। ये दो प्रक्रियाएँ एक ही सर्वर पर चलती हैं।

फ़ायरवॉल स्तर पर, मेरे पास इस सर्वर में केवल एक पोर्ट अग्रेषण ट्रैफ़िक हो सकता है । तो मुझे क्या करना चाहिए इस सर्वर पर nginx स्थापित करने के लिए इतना है कि यह एक बंदरगाह पर अनुरोधों के लिए सुनता है और फिर:

ए) सभी http://myhost.com/ * अनुरोधों को रीडायरेक्ट करता है ताकि वे लोकलहोस्ट पर जाएं: 8080 (जहां लाइटटैप सुन रहा है)

B) यदि कोई उपयोगकर्ता उदाहरण के लिए, URL से शुरू होने वाले URL का अनुरोध करता है, तो https: // myhost.com/app, यह उस अनुरोध को स्थानीयहोस्ट: 8008 (C प्रोग्राम) को भेजता है। ध्यान दें कि इस स्थिति में, दूरस्थ ब्राउज़र और नगीनक्स के बीच ट्रैफ़िक को एन्क्रिप्ट किया जाना चाहिए।

क्या आपको लगता है कि यह संभव हो सकता है? यदि यह है, तो यह कैसे किया जा सकता है?

मुझे पता है कि दो अलग-अलग पोर्ट का उपयोग करके यह कैसे करना है। चुनौती है कि मैं सिर्फ एक बंदरगाह के साथ यह कर रहा हूँ (दुर्भाग्य से, मैं इस विशेष वातावरण पर फ़ायरवॉल विन्यास पर नियंत्रण नहीं है, तो यह एक प्रतिबंध है कि मैं नहीं बचा सकता है)। फ़ायरवॉल को बायपास करने के लिए ssh के माध्यम से रिवर्स पोर्ट फ़ॉवरिंग जैसी तकनीकों का उपयोग करना या तो काम नहीं करेगा, क्योंकि यह उन दूरस्थ उपयोगकर्ताओं के लिए काम करना चाहिए जिनके पास वेब ब्राउज़र और इंटरनेट लिंक से अधिक कुछ नहीं है।

यदि यह nginx क्षमताओं से परे है, तो क्या आप किसी अन्य उत्पाद के बारे में जानते हैं जो इस आवश्यकताओं को पूरा कर सकता है? (अब तक मैं इसे लाइटटैप और पाउंड के साथ सेट करने में असफल रहा हूं)। मैं भी अपाचे से बचना पसंद करूँगा (हालाँकि अगर मैं इसका उपयोग करना चाहता हूँ तो यह एकमात्र संभव विकल्प है)।

अग्रिम धन्यवाद, एलेक्स

[*] बस स्पष्ट होना, मैं एक ही पोर्ट के माध्यम से एन्क्रिप्टेड और अनएन्क्रिप्टेड HTTP कनेक्शन को संभालने के बारे में बात कर रहा हूं । यह कोई फर्क नहीं पड़ता कि एन्क्रिप्शन एसएसएल या टीएलएस के माध्यम से किया जाता है।


HTTPS अनुरोध डिफ़ॉल्ट रूप से 443 पोर्ट पर जाते हैं, इसलिए भले ही आप यह काम कर सकें (और मुझे लगता है कि यह थोड़ा हैकरी के साथ संभव है), आपको लिंक के रूप में yourhost.com और yourhost.com:80 का उपयोग करना होगा (या yourhost.com:443 और yourhost.com )।
जेंची

ठीक है, मैं सर्वर फाल्ट में नया हूं और मुझे नहीं पता कि मैं अपना प्रश्न हटा सकता हूं या नहीं। चूंकि ऐसा लगता है कि समस्या को स्पष्ट रूप से पर्याप्त रूप से तैयार नहीं किया गया है, इसलिए मैं इसके बजाय एक नया प्रश्न खोलूंगा। वैसे भी, इस मुद्दे के लिए उपयोगी सुझावों के साथ योगदान करने वाले सभी को बहुत धन्यवाद।
एलेमार्टिनी

जवाबों:


18

स्टेटस कोड्स पर विकिपीडिया लेख के अनुसार, http ट्रैफ़िक को https पोर्ट (त्रुटि कोड 497) पर भेजे जाने पर Nginx का एक कस्टम त्रुटि कोड है

और error_page पर nginx डॉक्स के अनुसार , आप एक URI को परिभाषित कर सकते हैं जो एक विशिष्ट त्रुटि के लिए दिखाया जाएगा।
इस प्रकार हम एक uri बना सकते हैं जो क्लाइंट्स को भेजा जाएगा जब एरर कोड 497 उठाया जाएगा।

nginx.conf

#lets assume your IP address is 89.89.89.89 and also that you want nginx to listen on port 7000 and your app is running on port 3000

server {
    listen 7000 ssl;

    ssl_certificate /path/to/ssl_certificate.cer;
    ssl_certificate_key /path/to/ssl_certificate_key.key;
    ssl_client_certificate /path/to/ssl_client_certificate.cer;

    error_page 497 301 =307 https://89.89.89.89:7000$request_uri;

    location / {
        proxy_pass http://89.89.89.89:3000/;

        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Protocol $scheme;
    }
}

हालाँकि यदि कोई ग्राहक GET को छोड़कर किसी अन्य विधि के माध्यम से अनुरोध करता है, तो वह अनुरोध GET में बदल जाएगा। इस प्रकार ग्राहक उस अनुरोध विधि को संरक्षित करता है जिसमें ग्राहक आया था; हम एरर प्रोसेसिंग रिडायरेक्ट का उपयोग करते हैं जैसा कि एरर_पेज पर नगनेक्स डॉक्स में दिखाया गया है

और यही कारण है कि हम 301 =307रीडायरेक्ट का उपयोग करते हैं ।

यहां दिखाई गई nginx.conf फ़ाइल का उपयोग करके, हम उसी पोर्ट पर http और https सुनने में सक्षम हैं


17

जो खोज रहे हैं उनके लिए:

जोड़ें ssl on;और error_page 497 $request_uri;अपने सर्वर परिभाषा करने के लिए।


8
होवरहेल्स उत्तर के लिए थोड़ा सुधार: अपनी सर्वर परिभाषा में जोड़ें ssl on;और error_page 497 =200 $request_uri;। यह 200 के लिए स्थिति कोड बदल जाएगा
Mawi12345

यह सर्व दोष उत्तर बताता है कि यह समाधान क्यों काम करता है।
सिलिकॉनमाइंड

4

यदि आप वास्तव में चतुर होना चाहते हैं, तो आप आने वाले डेटा स्ट्रीम के पहले जोड़े बाइट्स को सूँघने के लिए एक कनेक्शन प्रॉक्सी चीज़ का उपयोग कर सकते हैं, और बाइट 0 की सामग्री के आधार पर कनेक्शन को बंद कर सकते हैं: यदि यह 0x16 (एसएसएल / टीएलएस) है हैंडशेक 'बाइट), एसएसएल साइड से कनेक्शन पास करें, यदि यह एक वर्णमाला वर्ण है, तो सामान्य HTTP करें। पोर्ट नंबरिंग के बारे में मेरी टिप्पणी लागू होती है


2

हाँ, यह संभव है, लेकिन nginx स्रोत कोड को पैच करने की आवश्यकता है (HoverHell में पैचिंग के बिना समाधान है)। नगनेक्स इसे गलत कॉन्फ़िगरेशन के बजाय गलत कॉन्फ़िगरेशन के रूप में मानता है।

चर $ ssl_session_id को सादे और एसएसएल कनेक्शन के बीच अंतर करने के लिए इस्तेमाल किया जा सकता है।

नंगेक्स-0.7.65 के खिलाफ पैच:

--- src/http/ngx_http_request.c-orig    2011-05-03 15:47:09.000000000 +0200
+++ src/http/ngx_http_request.c 2011-05-03 15:44:01.000000000 +0200
@@ -1545,12 +1545,14 @@

    c = r->connection;

+    /* disable plain http over https port warning
     if (r->plain_http) {
         ngx_log_error(NGX_LOG_INFO, c->log, 0,
                       "client sent plain HTTP request to HTTPS port");
         ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
         return;
     }
+    */

#if (NGX_HTTP_SSL)

सर्वर कॉन्फ़िगरेशन:

server {
    listen 80;
    index index.html;

    location / {
        root html;
        if ($ssl_session_id) {
            root html_ssl;
        }
    }

    ssl on;
    ssl_certificate cert.crt;
    ssl_certificate_key cert.key;
}

1

मुझे नहीं लगता कि ऐसा कुछ भी है जो एक ही बंदरगाह पर दो अलग-अलग प्रोटोकॉल को संभाल सकता है ...

मुझे इस बात की उत्सुकता है कि आप केवल एक ही पोर्ट को आगे क्यों कर सकते हैं, लेकिन यह एक तरफ ... यह आदर्श नहीं है, लेकिन अगर मैं आपके जूते में था, तो मैं सब कुछ https पर करूंगा।


हाय विल, और आपके उत्तर के लिए धन्यवाद! मुझे लगता है कि https पर सब कुछ परोसना एक विकल्प हो सकता है, हालांकि मैं इसे उस तरीके से सेट करने में सक्षम होना चाहूंगा जिस तरह से मैंने वर्णन किया है। हो सकता है कि यह तब किया जा सकता है यदि सामने वाला वेब सर्वर (रिवर्स प्रॉक्सी के रूप में कार्य करता है) एक सामान्य http सत्र स्थापित कर सकता है और फिर इसे पोर्ट को बदले बिना https में अपग्रेड कर सकता है। मुझे लगता है कि इस व्यवहार को RFC2817 (HTTP / 1.1 के साथ TLS में अपग्रेड करना) में वर्णित किया गया है, लेकिन मुझे यकीन नहीं है कि nginx या अन्य वेब सर्वर को पता है कि उस मानक से कैसे निपटा जाए।
एलेमार्टिनी

मेरे पास एक पूरे RFC को पढ़ने का समय नहीं है (और मुझे यकीन नहीं है कि मैं इसे समझने के लिए पर्याप्त स्मार्ट हूं!) लेकिन क्या आप सुरक्षित सत्र स्थापित होने या विभिन्न सत्रों को पूरा करने से पहले मानक बातचीत के बारे में बात कर रहे हैं? मुझे लगता है कि मैं थोड़ा और अधिक समझता हूं - सर्वर दो बंदरगाहों पर काम कर रहा है और यह प्रॉक्सी है जो अनुरोध को संदर्भित करता है - शांत लगता है लेकिन मैंने इसे कभी नहीं देखा है। शायद एक समाधान एक बंदरगाह पर एक ही सुरक्षित साइट बनाने और एक पूरी आभासी निर्देशिका होने के माध्यम से हो सकता है जो बस दूसरी वेबसाइट को विरासत में मिला / आयात करता है? यह सभी मुद्दों पर नहीं मिलता है, लेकिन बस काम कर सकता है: S
विलियम हिल्सम

1

आप एक ही पोर्ट पर HTTP और HTTPS दोनों का समर्थन नहीं कर सकते हैं, क्योंकि कनेक्शन के दोनों छोर एक निश्चित भाषा से बात करने की उम्मीद कर रहे हैं, और अगर दूसरे छोर से कुछ और बोल रहे हैं तो वे काम करने के लिए पर्याप्त चतुर नहीं हैं।

जैसा कि विल्स के जवाब में आपकी टिप्पणी का सुझाव दिया गया है, आप टीएलएस अपग्रेड का उपयोग कर सकते हैं (मेरा मानना ​​है कि नए नगनेक्स रिलीज इसका समर्थन करते हैं, हालांकि मैंने कोशिश नहीं की है), लेकिन यह HTTP और HTTPS नहीं चल रहा है, यह सिर्फ TLS अपग्रेड के साथ HTTP चल रहा है। समस्या अभी भी ब्राउज़र समर्थन है - अधिकांश ब्राउज़र (अभी भी) इसका समर्थन नहीं करते हैं। यदि आपको ग्राहकों का एक सीमित पूल मिला है, तो यह एक संभावना है, हालांकि।


1
एन्क्रिप्टेड और अनएन्क्रिप्टेड HTTP ट्रैफिक को सिंगल पोर्ट के जरिए हैंडल किया जा सकता है। मैं जानना चाहता हूं कि क्या यह संभव है कि नगीनक्स या अन्य उत्पादों (जैसे लाइटटैप) का उपयोग करके रिवर्स प्रॉक्सी के रूप में कार्य किया जाए। काफी शायद इस तरह के सेटअप को अपाचे द्वारा संभाला जा सकता है, लेकिन मैं अपने मूल प्रश्न में उल्लेख करना भूल गया कि मैं अपाचे का उपयोग नहीं करना पसंद करूंगा (हालांकि अगर लिनक्स पर कोई अन्य विकल्प नहीं है, तो मैं इसे करूंगा यह पूरा करने के लिए मंच)।
एलेमार्टिनी

जैसा कि मैंने अपने जवाब में कहा, "मेरा मानना ​​है कि नए नगनेक्स रिलीज़ सपोर्ट [टीएलएस अपग्रेड], हालांकि मैंने कोशिश नहीं की है"। यदि आपको मेरे लिए मैनुअल पढ़ने की आवश्यकता है, तो आप भाग्य से बाहर हैं।
वूमबल

मुझे खेद है अगर मैंने यह धारणा दी कि मुझे किसी को मेरे लिए मैनुअल पढ़ने की जरूरत है। ऐसा लगता है कि समस्या (और इसके बारे में प्रश्न) का ठीक-ठीक वर्णन नहीं किया गया था (मेरी गलती), जो मैं पूछ रहा था या ज़रूरत थी उसकी अलग-अलग व्याख्याओं के लिए अग्रणी था। इसलिए मैंने इस मुद्दे के बारे में एक नया प्रश्न खोलने का फैसला किया और समस्या या इसके बारे में विशिष्ट प्रश्नों के संबंध में किसी भी संभावित भ्रम से बचने की कोशिश की। वैसे भी, अपने समय के लिए धन्यवाद और अपनी अंतर्दृष्टि साझा करने के लिए।
एलेमार्टिनी

0

मुझे यकीन नहीं है कि यह इसे कैसे खींचता है, लेकिन CUPSD पोर्ट 631 पर http और https दोनों का जवाब देता है। यदि nginx अब ऐसा नहीं कर सकता है, तो शायद वे सीख सकते हैं कि CUPS टीम इसे कैसे खींचती है, लेकिन CUPS के तहत है GPL, इसलिए nginx को अपने लाइसेंस को बदलते हुए देखना पड़ सकता है यदि वे ऐसी क्षमता को लागू करना चाहते हैं और कहीं और ऐसा करने के लिए कोड नहीं ढूंढ सकते।


0

सिद्धांत रूप में, आपके पास एक वेब पेज हो सकता है जो HTTP के माध्यम से सुलभ है, जो https: 443 पर एक WebSocket खोलने के लिए सक्षम है जो इसे कहीं भी करना चाहता है। WebSocket प्रारंभिक हैंडशेक HTTP है। तो, हाँ, एक असुरक्षित दिखने वाला पृष्ठ बनाना संभव है जो वास्तव में सुरक्षित संचार में सक्षम हो। आप इसे नेट्टी लाइब्रेरी के साथ कर सकते हैं ।


0

1.15.2 के बाद से यह ठीक से करना संभव है। जानकारी यहाँ देखें ।

अपने nginx.conf में इस तरह से एक ब्लॉक जोड़ें (http ब्लॉक के बाहर):

stream {
    upstream http {
        server localhost:8000;
    }

    upstream https {
        server localhost:8001;
    }

    map $ssl_preread_protocol $upstream {
        default https;
        "" http;
    }

    server {
        listen 8080;
        listen [::]:8080;
        proxy_pass $upstream;
        ssl_preread on;
    }
}

फिर आप अपना सामान्य सर्वर ब्लॉक बना सकते हैं, लेकिन इन विभिन्न बंदरगाहों पर सुन रहे हैं:

server {
    listen 8000;
    listen [::]:8000;
    listen 8001 ssl;
    listen [::]:8001 ssl;
...

इस तरह, स्ट्रीम ब्लॉक पूर्ववर्ती और यह पता लगाने में सक्षम है कि क्या यह टीएलएस है या नहीं (इस उदाहरण में पोर्ट 8080 पर), और फिर प्रॉक्सी इसे स्थानीय रूप से सही सर्वर पोर्ट पर भेज देता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.