Nginx में SSL को बाध्य या पुनर्निर्देशित कैसे करें?


222

मेरे पास एक उपडोमेन पर एक साइनअप पेज है जैसे: https://signup.example.com

यह केवल HTTPS के माध्यम से सुलभ होना चाहिए, लेकिन मुझे चिंता है कि लोग किसी तरह HTTP के माध्यम से इस पर ठोकर खा सकते हैं और 404 प्राप्त कर सकते हैं।

मेरा html / सर्वर ब्लॉक इस तरह दिखता है:

html {
  server {
    listen 443;
    server_name signup.example.com;

    ssl                        on;
    ssl_certificate        /path/to/my/cert;
    ssl_certificate_key  /path/to/my/key;

    ssl_session_timeout 30m;

    location / {
      root /path/to/my/rails/app/public;
      index index.html;
        passenger_enabled on;
    }
  }
}

मैं क्या जोड़ सकता हूं ताकि जो लोग http://signup.example.comपुनर्निर्देशित हो जाएं https://signup.example.com? (FYI करें मुझे पता है कि रेल प्लग हैं जो मजबूर कर सकते हैं SSLलेकिन उससे बचने की उम्मीद कर रहे थे)


जवाबों:


145

नेगनेक्स नुकसान के अनुसार , अनावश्यक कैप्चर को छोड़ना बेहतर है, $request_uriइसके बजाय का उपयोग करना। उस स्थिति में, किसी भी क्वेरी आर्ग को दोगुना करने से nginx को रोकने के लिए एक प्रश्न चिह्न जोड़ें।

server {
    listen      80;
    server_name signup.mysite.com;
    rewrite     ^   https://$server_name$request_uri? permanent;
}

68
या, आपके द्वारा लिंक की गई साइट के अनुसार, "बेहतर" :return 301 http://domain.com$request_uri;
nh2

13
एक टिप्पणी। $ server_name $ पहले server_name चर को चुनता है। तो इस बारे में सचेत रहें यदि आपके कॉन्फ़िगरेशन में गैर FQN नाम हैं
इंजीनियरडवे

2
@ nh2 यह return 301..." गलत तरीके से कई रीडायरेक्ट" त्रुटि का उपयोग करने के बाद से प्रलेखन का एक और मामला है, जबकि पुनर्लेखन वास्तव में काम करता है।
माइक बेथानी

1
यह अब "बीएडी" के रूप में भी प्रलेखित है। @MikeBethany return 301जब तक (मुझे लगता है), काम करता है आप इसे ट्रिगर कर रहे हैं भी सही URL के लिए, (दोनों बंदरगाहों पर सुन config के उदाहरण से समस्या को ट्रिगर:। लेने serverfault.com/a/474345/29689's पहले उत्तर और छोड़ देते हैं, तो )।
ब्लिसॉर्बलेड

1
मुझे आश्चर्य है कि पिछले कुछ वर्षों में क्या बदल गया है और क्या यह अन्य उत्तर बेहतर है: serverfault.com/a/337893/119666
रयान

256

इसका सबसे अच्छा तरीका जैसा कि आधिकारिक में बताया गया है कि returnनिर्देश का उपयोग कैसे किया जाता है :

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

5
सबसे छोटा जवाब और मेरे मामले में पूरी तरह से काम किया
mateusz.fiolka

1
यह आम तौर पर सिफारिश की जाती है क्योंकि यह एक 301 Moved Permanently(आपके लिंक स्थायी रूप से स्थानांतरित हो गए) के साथ-साथ फिर से लिखता है
sgb

1
यह काम नहीं करता है क्योंकि यह "बहुत अधिक रीडायरेक्ट" त्रुटि का कारण बनता है, भले ही आपने सेट किया होproxy_set_header X-Forwarded-Proto https;
माइक बेथानी

1
@ मायकेबेटी क्या आप listen 443;एक ही ब्लॉक में परिभाषित कर रहे हैं ?
जो बी

2
यह स्वीकृत उत्तर होना चाहिए।
साजा

119

यह सही और सबसे कारगर तरीका है अगर आप इसे एक सर्वर ब्लॉक में रखना चाहते हैं:

server {
    listen   80;
    listen   [::]:80;
    listen   443 default_server ssl;

    server_name www.example.com;

    ssl_certificate        /path/to/my/cert;
    ssl_certificate_key  /path/to/my/key;

    if ($scheme = http) {
        return 301 https://$server_name$request_uri;
    }
}

उपरोक्त सभी कुछ, "फिर से लिखना" या "यदि ssl_protocol" आदि का उपयोग करना धीमा और बदतर है।

यहाँ एक ही है, लेकिन इससे भी अधिक कुशल है, केवल http प्रोटोकॉल पर फिर से लिखने से यह हर अनुरोध पर $ योजना चर की जाँच करने से बचता है। लेकिन गंभीरता से, यह इतनी मामूली बात है कि आपको उन्हें अलग करने की आवश्यकता नहीं है।

server {
    listen   80;
    listen   [::]:80;

    server_name www.example.com;

    return 301 https://$server_name$request_uri;
}
server {
    listen   443 default_server ssl;

    server_name www.example.com;

    ssl_certificate        /path/to/my/cert;
    ssl_certificate_key  /path/to/my/key;
}

8
महान, कुछ कायर ने इस जवाब को बिना कहे वोट दिया, भले ही यह उत्तर सही हो। हो सकता है कि उनमें से एक और "अगर बुराई है"। यदि आप के बारे में Nginx प्रलेखन को पढ़ने के लिए परेशान करते हैं, तो आपको पता चल जाएगा कि IfIsNOTEvil, बस CERTAIN एक स्थान {} संदर्भ में इसका उपयोग करता है, जिनमें से कोई भी हम यहां नहीं करते हैं। मेरा जवाब काम करने का बिल्कुल सही तरीका है!
DELETEDACC

2
मैंने इसे वोट नहीं किया, लेकिन मैं यह बताना चाहूंगा कि डिफ़ॉल्ट को हाल के संस्करणों में 'default_server' में बदल दिया गया है।
थूक

पहला समाधान सबसे कुशल नहीं हो सकता है, अगर दूसरा भी अधिक कुशल है। और आपने यह भी बताया कि, अगर आपको वहाँ का उपयोग क्यों नहीं करना चाहिए: "यह हर अनुरोध पर $ योजना चर की जाँच करने से बचता है"। इफ़्स का उपयोग न करने की बात केवल प्रदर्शन के बारे में नहीं है, बल्कि घोषणात्मक होने के बारे में भी है, और अनिवार्य नहीं है।
pepkin88

+1 के लिए यदि ($ योजना = http)
फर्नांडो कोश

यहाँ $ होस्ट का उपयोग करना चाहिए, जैसा कि अन्य उत्तरों में बताया गया है।
आर्टेम रसाकोवस्की

56

यदि आप नई दोहरी HTTP और HTTPS सर्वर परिभाषा का उपयोग कर रहे हैं, तो आप निम्न का उपयोग कर सकते हैं:

server {
    listen   80;
    listen   [::]:80;
    listen   443 default ssl;

    server_name www.example.com;

    ssl_certificate        /path/to/my/cert;
    ssl_certificate_key  /path/to/my/key;

    if ($ssl_protocol = "") {
       rewrite ^   https://$server_name$request_uri? permanent;
    }
}

यह मेरे लिए काम करता है और पुनर्निर्देशित लूप का कारण नहीं बनता है।

संपादित करें:

जगह ले ली:

rewrite ^/(.*) https://$server_name/$1 permanent;

प्रतीक की फिर से लिखी लाइन के साथ।


2
@DavidPashley आपके समाधान ने मेरे लिए एक आकर्षण की तरह काम किया। धन्यवाद
जयेश गोपालन

1
If you are using the new dual HTTP and HTTPS server definitionतो आपको इसे अलग करना चाहिए।
VBart

2
सुरुचिपूर्ण और सही काम करता है!
जैकट्रेड

2
यह एकमात्र समाधान था जिसने मेरे लिए मेरे लारवेल / होमस्टेड नेग्नेक्स कॉन्फ़िगरेशन के साथ काम किया।
जेरेड एटनियर

1
इसके अलावा फिर से लिखना चाहिए return 301 https://$server_name$request_uri;क्योंकि यह पसंदीदा तरीका है।
जेयर्ड एटनियर

27

फिर भी एक और संस्करण, जो होस्ट को संरक्षित करता है: हेडर का अनुरोध करता है और नगीनैक्स नुकसान पर "GOOD" उदाहरण का अनुसरण करता है :

server {
    listen   10.0.0.134:80 default_server;

    server_name  site1;
    server_name  site2;
    server_name  10.0.0.134;

    return 301 https://$host$request_uri;
}

यहाँ परिणाम हैं। ध्यान दें कि $server_nameइसके बजाय का उपयोग $hostहमेशा के लिए अनुप्रेषित करेगा https://site1

# curl -Is http://site1/ | grep Location
Location: https://site1/

# curl -Is http://site2/ | grep Location
Location: https://site2/


# curl -Is http://site1/foo/bar | grep Location
Location: https://site1/foo/bar

# curl -Is http://site1/foo/bar?baz=qux | grep Location
Location: https://site1/foo/bar?baz=qux

Note that using $server_name instead of $host would always redirect to https://site1ऐसा नहीं है कि क्या $request_uriहै?
जुरगेन पॉल

2
$request_uriएक होस्ट या डोमेन नाम शामिल नहीं है। दूसरे शब्दों में, यह हमेशा "/" वर्ण से शुरू होता है।
पीटर

2
अब तक का सबसे अच्छा जवाब।
आशीष

3
मुझे यकीन नहीं है कि वोटों में यह जवाब इतना कम क्यों है। यह केवल एक ही उपयोग करने लायक है।
zopieux 18

2
खिचड़ी भाषा का मानना ​​है कि बहुत से लोग $ server_name का उपयोग करते हैं यह इसे करने का सही तरीका है
ग्रेग एनिस

3

सुनिश्चित करें कि आप किसी भी कुकीज़ पर 'सुरक्षित' सेट करते हैं, अन्यथा उन्हें HTTP अनुरोध पर भेजा जाएगा और Firesheep जैसे उपकरण द्वारा पकड़ा जा सकता है।


1
server {
    listen x.x.x.x:80;

    server_name domain.tld;
    server_name www.domian.tld;
    server_name ipv4.domain.tld;

    rewrite     ^   https://$server_name$request_uri? permanent;
}

यह बेहतर काम करता है मुझे लगता है। xxxx आपके सर्वर के आईपी को संदर्भित करता है। यदि आप Plesk 12 के साथ काम कर रहे हैं, तो आप जो भी चाहें डोमेन के लिए "nvarx.conf" फ़ाइल को निर्देशिका में "/var/www/vhosts/system/domain.tld/conf" में बदलकर कर सकते हैं। कॉन्फ़िगरेशन सहेजने के बाद nginx सेवा को पुनरारंभ करना न भूलें।


rewrite ^ https://$host$request_uri? permanent; एक बेहतर समाधान होगा क्योंकि आपके पास vhost पर कई सर्वर नाम हो सकते हैं

0

मुझे लगता है कि यह सबसे सरल उपाय है। केवल HTTPS और www के लिए गैर-HTTPS और गैर- WWW यातायात दोनों को मजबूर करता है।

server {
    listen 80;
    listen 443 ssl;

    server_name domain.tld www.domain.tld;

    # global HTTP handler
    if ($scheme = http) {
        return 301 https://www.domain.tld$request_uri;
    }

    # global non-WWW HTTPS handler
    if ($http_host = domain.tld) {
        return 303 https://www.domain.tld$request_uri;
    }
}

EDIT - अप्रैल 2018: सॉल्यूशन w / o इफ मेरे पोस्ट में यहां पाया जा सकता है: https://stackoverflow.com/a/36777526/6076984


1
क्या नगीनों की स्थिति में बुराई और अक्षमता को गलत नहीं माना जाता है?
PKHunter

हाँ, वे सामान्य तौर पर हैं। लेकिन इस साधारण जांच के लिए मुझे नहीं लगता। मेरे पास एक उचित कॉन्फ़िगरेशन फ़ाइल है जिसमें अधिक कोड लेखन शामिल है, लेकिन IF की पूरी तरह से बचा जाता है।
स्टैमस्टर

Google 303 के बजाय 301 का उपयोग करने की सलाह देता है। स्रोत: support.google.com/webmasters/answer/6073543?hl=en
dylanh724

@DylanHunt - मैंने केवल परीक्षण के लिए 303 को छोड़ दिया, ध्यान दें कि 1 हैंडलर 301 पर सेट किया गया था, केवल 2nd मैं बदलना भूल गया :) इसके अलावा, समाधान w / o IF का: stackoverflow.com/a/36777526-6076984
stamster
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.