सवाल "Www" निकालें और nginx के साथ "https" पर रीडायरेक्ट करें


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

  1. "Www।" को हटा देता है अनुरोध यूआरआई से
  2. यदि अनुरोध यूआरआई "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) लूपिंग के बिना। कोई विचार?


42
2018-04-11 16:37


मूल


मैंने बस www.mydomain.com को mydomain.com पर DNS स्तर पर रीडायरेक्ट किया और nginx में गैर-https से https तक के लिए 301 जोड़ा। ऐसा लगता है कि ठीक होना चाहिए ¯ \ _ (ツ) _ / ¯ - jonathanbell


जवाब:


इसे पूरा करने का सबसे अच्छा तरीका तीन सर्वर ब्लॉक का उपयोग कर रहा है: एक 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>
}

61
2018-04-11 18:21



क्या मध्य ब्लॉक आवश्यक है? क्या पहले ब्लॉक पहले से www से गैर-www में पुनः लिख रहा है? - pbreitenbach
पहला ब्लॉक केवल http को संभालता है। Https अनुरोध http: // www.example.com/ से https: // example.com/ पर https अनुरोधों को पुनर्निर्देशित करने के लिए मध्य ब्लॉक आवश्यक है। (अतिरिक्त रिक्त स्थान के लिए खेद है, मैं इसे अन्यथा https नहीं दिखा सकता) - kolbyjack
सिर्फ एक मामूली प्रारूपण नोट - यदि आप एक लिंक बनाने से बचना चाहते हैं, तो आप टिप्पणी टेक्स्ट को बैक-कोट्स के अंदर डाल सकते हैं, जो कि टिल्डे के तहत है। यह इस तरह दिखाई देगा: https://example.com/ - Cyclops
दूसरे ब्लॉक को भी प्रमाण जानकारी की आवश्यकता है। - ricka
इस जवाब की कोशिश कर, मैं एक और समस्या में भाग गया। सोचा था कि मैं 301 से रीडायरेक्ट कर सकता था www.sub.example.com सेवा मेरे sub.example.com और उसके बाद केवल एक एसएसएल प्रमाण पत्र प्राप्त करें sub.example.com अब मुझे पता है कि एसएसएल प्रमाण पत्र 301 रीडायरेक्ट से पहले होता है, इसलिए यह काम नहीं कर सकता है। यहां अधिक स्पष्टीकरण: serverfault.com/a/358625/144811 - Gruzzles


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

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/ बजाय।)


8
2018-05-09 15:45



यह वास्तव में काम करता है, लेकिन मैंने सोचा कि इसे बहुत अधिक डुप्लिकेट कॉन्फ़िगरेशन लाइनों के बिना अधिक स्पष्ट तरीके से किया जा सकता है। - zloynemec
@zloynemec आप एसएसएल सामान को एक अलग .conf फ़ाइल में डाल सकते हैं और इसका उपयोग कर सकते हैं include एसएसएल सर्वर ब्लॉक दोनों में जोड़ने के लिए नियम। - Igettäjä
इसके अलावा यदि आप क्लाउडफ्लेयर का उपयोग कर रहे हैं तो आपको 2 सबडोमेन (www + कुछ) को रीडायरेक्ट और प्रॉक्सी करने में सक्षम होने के लिए $ 10 / mo प्रमाणपत्र का भुगतान करना होगा। अगर कोई कामकाज है तो मुझे बताएं। - Freedo


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

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 बुराई है!

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


6
2018-01-24 14:11



मुझे यह पसंद है, लेकिन क्या आपके पास प्रदर्शन हिट पर कोई डेटा है? धन्यवाद! - Freedo
ईमानदारी से मैंने कभी इसे बेंचमार्क नहीं किया, लेकिन मेरा मानना ​​है कि अलग-अलग नियमों की तुलना में शायद ही कोई प्रभाव नहीं होगा क्योंकि प्रभाव काफी समान है। - emyller


मैं एक प्रतिक्रिया कोड के साथ वापस लौटना पसंद करता हूं ताकि ब्राउज़र जानता है कि आप इसे किसी अन्य यूआरएल पर रीडायरेक्ट कर रहे हैं।

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

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

फिर एक और सर्वर विन्यास के लिए ब्लॉक https

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

3
2017-09-18 12:16





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

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

फिर nginx पुनरारंभ करें


0
2018-04-11 16:45



पुनरारंभ करते समय मुझे "विवादित सर्वर नाम" त्रुटि मिलती है। साथ ही, वह आदेश SSL के लिए पोर्ट 443 पर नहीं सुनेंगे और मुझे पुनर्निर्देशन के बारे में चिंता करने की आवश्यकता है https://www.example.com सेवा मेरे https://example.com भी। - Devin


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

आपके सादे HTTP सर्वर परिभाषा पर एंथोनिसोमर्सेट की तरह कुछ सुझाव दिया गया है, जो है:

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

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

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

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


0
2018-04-11 17:56



यह काम किया, धन्यवाद। मुझे आपकी सशर्तता बदलनी पड़ी if ($host = 'www.example.com') { चूंकि आपका रेगेक्स मेरे लिए काम नहीं कर रहा था, हालांकि। कोई विचार नहीं, क्योंकि यह सही दिखता है। - Devin
ध्यान दें कि अगर बुरा है और आम तौर पर घोषणात्मक तरीके का उपयोग करना बेहतर होता है। - Blaise


यहां पूरा उदाहरण दिया गया है जो मेरे लिए काम कर रहा है। समस्या यह थी कि मेरे पास एसएसएल विवरण नहीं था (ssl_certificate, आदि) www पुनर्निर्देशन ब्लॉक में। अपने लॉग जांचना याद रखें (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;
    }
}

0
2018-02-07 03:58