"Www" निकालें और nginx के साथ "https" पर पुनर्निर्देशित करें


57

मैं nginx में एक नियम बनाना चाहता हूँ जो दो काम करता है:

  1. "Www। निकालता है।" अनुरोध से यू.आर.आई.
  2. यदि अनुरोध URI "http" हो तो "https" पर पुनर्निर्देशित करता है

उन चीजों में से प्रत्येक को व्यक्तिगत रूप से कैसे करना है, इसके बहुत सारे उदाहरण हैं, लेकिन मैं एक समाधान का पता नहीं लगा सकता हूं जो दोनों को सही ढंग से करता है (यानी एक अनुप्रेषित लूप नहीं बनाता है और सभी मामलों को ठीक से संभालता है)।

इसे इन सभी मामलों को संभालने की आवश्यकता है:

1. http://www.example.com/path
2. https://www.example.com/path
3. http://example.com/path
4. https://example.com/path

इन सभी को बिना लूपिंग के https://example.com/path (# 4) पर समाप्त होना चाहिए । कोई विचार?


मैंने अभी www.mydomain.com को DNS स्तर पर mydomain.com पर पुनर्निर्देशित किया है और नॉन-https के लिए 301 से nginx में https जोड़ा है। ऐसा लगता है कि ठीक होना चाहिए _ \ _ (_) _ / j
जोनाथनबेल

जवाबों:


94

इसे पूरा करने का सबसे अच्छा तरीका तीन सर्वर ब्लॉक का उपयोग करना है: एक को http से https में पुनर्निर्देशित करना, एक को https www-name को no-www पर पुनर्निर्देशित करना, और एक को वास्तव में अनुरोधों को संभालना है। Ifs के बजाय अतिरिक्त सर्वर ब्लॉक का उपयोग करने का कारण यह है कि सर्वर का चयन हैश टेबल का उपयोग करके किया जाता है, और बहुत तेज है। सर्वर-स्तर का उपयोग करना, जिसका अर्थ है कि यदि हर अनुरोध के लिए चलाया जाता है, जो बेकार है। इसके अलावा, फिर से लिखे गए यूरिया को फिर से लिखना बेकार है, क्योंकि nginx के पास पहले से ही $ uri और $ request_uri वैरिएबल्स में (बिना और क्वेरी स्ट्रिंग के, क्रमशः) यह जानकारी है।

server {
    server_name www.example.com example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl;
    ssl_certificate /path/to/server.cert;
    ssl_certificate_key /path/to/server.key;
    server_name www.example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl;
    ssl_certificate /path/to/server.cert;
    ssl_certificate_key /path/to/server.key;
    server_name example.com;

    <locations for processing requests>
}

2
क्या मध्य ब्लॉक आवश्यक है? क्या पहले ब्लॉक को www से गैर-www में पहले से ही लिखना नहीं है?
pbreitenbach

3
पहला ब्लॉक केवल http को हैंडल करता है। Https: // www.example.com/ से https: // example.com/ पर https अनुरोधों को रीडायरेक्ट करने के लिए मध्य ब्लॉक आवश्यक है। (अतिरिक्त रिक्त स्थान के लिए क्षमा करें, मैं इसे https अन्यथा नहीं दिखा सकता हूं)
kolbyjack

1
सिर्फ एक मामूली प्रारूपण नोट - यदि आप एक लिंक बनाने से बचना चाहते हैं, तो आप बैक-कोट्स के अंदर टिप्पणी पाठ डाल सकते हैं, जो कि एक छोटे से अंडरलाइन है। यह इस तरह दिखाई देगा:https://example.com/
Cyclops

9
दूसरे ब्लॉक को भी प्रमाणित जानकारी चाहिए।
मिका

3
इस उत्तर की कोशिश करते हुए, मैं एक और समस्या में भाग गया। मैं 301 से अनुप्रेषित सोचा सकता है www.sub.example.comकरने के लिए sub.example.comऔर उसके बाद ही एक SSL प्रमाणपत्र प्राप्त करने के लिए sub.example.comअब मुझे पता है कि ssl प्रमाणपत्र की जांच 301 रीडायरेक्ट से पहले होता है, तो यह काम नहीं कर सकता। यहाँ और अधिक विवरण: serverfault.com/a/358625/144811
ग्रूज़ल्स

11

यह मेरे लिए काम करता है:

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

server {
    listen              443 ssl;
    server_name         www.yourdomain.com;
    ssl_certificate     /path/to/certificate.crt;
    ssl_certificate_key /path/to/private/key.pem;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    return              301 https://yourdomain.com$request_uri;
}

server {
    listen              443 ssl;
    server_name         yourdomain.com;
    ssl_certificate     /path/to/certificate.crt;
    ssl_certificate_key /path/to/private/key.pem;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;

    # do the proper handling of the request
}

ध्यान रखें कि दोनों yourdomain.com और www.yourdomain.com चाहिए से मेल नहीं खाता में हो। यह एक वाइल्डकार्ड प्रमाणपत्र या सर्वर वैकल्पिक नाम के साथ संभव है जैसा कि यहां बताया गया है । ऐसा करने वाले अच्छे और मुफ्त प्रमाणपत्रों के लिए https://www.startssl.com की जाँच करें । ( एडिथ : क्रोम संस्करण 56 के साथ शुरुआत करके, एसटीएसएल प्रमाणपत्रों पर अब भरोसा नहीं किया जाएगा। इसके बजाय https://letsencrypt.org/ आज़माएं ।)


यह वास्तव में काम करता है, लेकिन मुझे लगा कि यह बहुत अधिक डुप्लिकेट कॉन्फ़िगरेशन लाइनों के बिना अधिक स्पष्ट तरीके से किया जा सकता है।
zloynemec

@zloynemec आप SSL सामान को एक अलग .conf फ़ाइल में रख सकते हैं और includeनियम का उपयोग करके इसे SSL सर्वर ब्लॉक दोनों में जोड़ सकते हैं।
Igettäjä

इसके अलावा, यदि आप क्लाउडफ़ेयर का उपयोग कर रहे हैं, तो आपको 2 उप-डोमेन (www + कुछ) को रीडायरेक्ट और प्रॉक्सी करने में सक्षम होने के लिए $ 10 / मो सर्टिफ़िकेट का भुगतान करने की आवश्यकता है। अगर कोई वर्कअराउंड है तो मुझे बताएं।
फ्रीडो सेप

7

इसी तरह के सैकड़ों मामलों के साथ इतना समय बिताने के बाद, मैं निम्नलिखित स्निपेट के साथ आया हूं। यह छोटा है और किसी भी चीज को फिट करने के लिए इसे आसानी से छोटा किया जा सकता है।

server {
    listen 80;
    listen 443 ssl;
    server_name example.com www.example.com;
    ssl_certificate /path/to/my/certs/example.com/fullchain.pem;
    ssl_certificate_key /path/to/my/certs/example.com/privkey.pem;

    # Redirect to the correct place, if needed
    set $https_redirect 0;
    if ($server_port = 80) { set $https_redirect 1; }
    if ($host ~ '^www\.') { set $https_redirect 1; }
    if ($https_redirect = 1) {
        return 301 https://example.com$request_uri;
    }

    location / {
    # ...
}

ओह, लेकिन ifबुराई है !

हाँ यह हो सकता है। लेकिन यह एक कारण के लिए मौजूद है, और उन लोगों को कोई नुकसान नहीं पहुंचाना चाहिए जो जानते हैं कि इसका सही उपयोग कैसे करें। ;)


मुझे यह पसंद है, लेकिन क्या आपके पास प्रदर्शन हिट पर कोई डेटा है? धन्यवाद!
फ्रीडो सेप

1
ईमानदारी से, मैंने ऐसा कभी नहीं किया, लेकिन मेरा मानना ​​है कि अलग-अलग नियमों की तुलना में शायद ही कोई प्रभाव होगा क्योंकि प्रभाव बहुत अधिक है।
एमिलर

पुनर्निर्देशन पर बेंचमार्क? यह वास्तव में उचित नहीं है? (सच्चा सवाल, ट्रोल नहीं ^ ^)
मैट्रिक्स

3

मैं एक प्रतिक्रिया कोड के साथ वापस जाना पसंद करता हूं ताकि ब्राउज़र जानता है कि आप इसे दूसरे URL पर पुनर्निर्देशित कर रहे हैं।

server {
    listen   80;
    server_name  www.example.com;

    return 301 https://example.com$request_uri;
}

उसके बाद एक और सर्वर कॉन्फ़िगरेशन ब्लॉक करता है https

server {
        listen   443 ssl;
        server_name  example.com;
        ...
    }

0

कैसे इस उद्देश्य के लिए एक सर्वर ब्लॉक बनाने के बारे में:

server{
    listen 80;
    server_name www.example.net example.net;
    rewrite ^(.*) https://example.net$1 permanent;
}

फिर नगीने को फिर से शुरू करना


पुनः आरंभ करने पर मुझे "परस्पर विरोधी सर्वर नाम" त्रुटि मिलती है। इसके अलावा, कि आदेश SSL के लिए पोर्ट 443 पर नहीं सुनेगा और मैं पुनः निर्देशित के बारे में चिंता करने की जरूरत https://www.example.comकरने के लिए https://example.comके रूप में अच्छी तरह से।
डेविन

0

मुझे लगता है कि यह काम करना चाहिए।

आपके सादे HTTP सर्वर पर कुछ इस तरह का सुझाव दिया गया है, जैसे anthonysomerset ने सुझाव दिया है:

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

फिर अपने एसएसएल सर्वर परिभाषा पर:

if ($host ~ /^www\./) {
  rewrite ^(.*) https://example.net$1 permanent;
}

इस तरह से रीडायरेक्ट केवल एक बार अनुरोध के अनुसार होना चाहिए, कोई फर्क नहीं पड़ता कि उपयोगकर्ता मूल रूप से किस URL पर जाता है।


यह काम किया, धन्यवाद। if ($host = 'www.example.com') {हालाँकि मुझे आपकी हालत बदलने वाली थी, क्योंकि आपका रेग्क्स मेरे लिए काम नहीं कर रहा था, हालाँकि। पता नहीं क्यों, जैसा कि यह सही लगता है।
डेविन

ध्यान दें कि अगर बुराई है और आम तौर पर एक घोषणात्मक तरीके का उपयोग करना बेहतर है।
ब्लेस

0

यहाँ पूर्ण उदाहरण है जो मेरे लिए काम कर रहा है। समस्या यह थी कि मेरे पास ssl_certificatewww पुनर्निर्देशित ब्लॉक में ssl विवरण ( , आदि) नहीं था। अपने लॉग की जांच करना याद रखें ( sudo tail -f /var/log/nginx/error.log)!

# HTTP — redirect all traffic to HTTPS
server {
    listen 80;
    listen [::]:80 default_server ipv6only=on;
    return 301 https://$host$request_uri;
}

# HTTPS — redirects www to non-www
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name www.example.com;

    # Use the Let's Encrypt certificates
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Include the SSL configuration from cipherli.st
    include snippets/ssl-params.conf;
    return 301 https://example.com$request_uri;
}

# HTTPS — proxy all requests to the app (port 3001)
server {
    # Enable HTTP/2
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com sub.example.com;

    # Use the Let's Encrypt certificates
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Include the SSL configuration from cipherli.st
    include snippets/ssl-params.conf;

    # For LetsEncrypt:
    location ~ /.well-known {
        root /var/www/html;
        allow all;
    }

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://localhost:3001;
        proxy_ssl_session_reuse off;
        proxy_set_header Host $http_host;
        proxy_cache_bypass $http_upgrade;
        proxy_redirect off;
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.