سؤال كيفية فرض أو إعادة توجيه إلى SSL في nginx؟


لدي صفحة اشتراك في نطاق فرعي مثل: https://signup.example.com

يجب الوصول إليه عبر HTTPS فقط ، لكنني قلق من احتمال تعثر الأشخاص بطريقة ما عبر HTTP والحصول على الرقم 404.

يبدو كتلة html / server في nginx كما يلي:

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 ؟ (لمعلوماتك هناك بعض الإضافات القضبان التي يمكن أن قوة SSL ولكن كان على أمل تجنب ذلك)


210
2018-03-22 18:45


الأصل


ممكن نسخة من في Nginx ، كيف يمكنني إعادة كتابة جميع طلبات http إلى https مع الحفاظ على النطاق الفرعي؟ - Nasreddine


الأجوبة:


بالنسبة الى nginx المزالق، من الأفضل بشكل طفيف حذف الالتقاط غير الضروري ، باستخدام $request_uri في حين أن. في هذه الحالة ، إلحاق علامة استفهام لمنع nginx من مضاعفة أي استعلام args.

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

137
2018-03-22 19:22



أو ، وفقًا للموقع الذي ربطته ، "أفضل": return 301 http://domain.com$request_uri; - nh2
تعليق واحد. يقوم $ $ server_name $ بالتقاط أول متغير server_name. لذا كن على دراية بذلك إذا كان لديك أسماء FQN في التكوين الخاص بك - engineerDave
@ nh2 هذه حالة أخرى لكون الوثائق خاطئة منذ استخدامها return 301... تسبب خطأ "عدد كبير جدًا من عمليات إعادة التوجيه" بينما تعمل طريقة إعادة الكتابة بالفعل. - Mike Bethany
هذا هو الآن موثقة باسم "سيئة أيضا". MikeBethany return 301 يعمل ، ما لم يكن (أظن) أنك تحفزه أيضا بالنسبة إلى عناوين URL الصحيحة ، من خلال الاستماع إلى كلا المنفذين (مثال التهيئة. تحريك المشكلة: اتخاذها serverfault.com/a/474345/29689's الإجابة الأولى وإهمال if). - Blaisorblade
أتساءل ما الذي تغير على مر السنين وما إذا كانت هذه الإجابة الأخرى أفضل: serverfault.com/a/337893/119666 - Ryan


أفضل طريقة كما هو موضح في كيف الرسمية هو باستخدام return التوجيه:

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

236
2017-09-03 23:50



أقصر الإجابة وعملت تماما في حالتي - mateusz.fiolka
هذا هو الموصى به عموما لأنها ترجع أ 301 Moved Permanently (تم نقل روابطك بشكل دائم) بالإضافة إلى إعادة الكتابة - sgb
هذا لا يعمل لأنه يتسبب في حدوث خطأ "كثرة عمليات إعادة التوجيه" حتى في حالة ضبطه proxy_set_header X-Forwarded-Proto https; - Mike Bethany
MikeBethany أنت تحدد listen 443; في نفس الكتلة؟ - Joe B
يجب أن يكون هذا هو الجواب المقبول. - sjas


هذه هي الطريقة الصحيحة والأكثر فاعلية إذا كنت تريد الاحتفاظ بها كلها في كتلة خادم واحدة:

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;
}

108
2018-01-31 20:43



لقد صوّت بعض الجبناء هذه الإجابة دون أن يقولوا لماذا ، على الرغم من أن هذه الإجابة صحيحة. ربما واحد آخر من هؤلاء "إذا كان الشر" الطائفيين. إذا كنت تزعج نفسك بقراءة وثائق Nginx حول If ، ستعرف أن IfIsNOTEvil ، تستخدم CERTAIN فقط في سياق {} الموقع ، لا نقوم بذلك هنا. إجابتي هي الطريقة الصحيحة لفعل الأشياء! - DELETEDACC
لم أقم بالتصويت ، لكني أود الإشارة إلى أنه تم تغيير الإعداد الافتراضي إلى "default_server" في أحدث الإصدارات. - spuder
الحل الأول لا يمكن أن يكون الأكثر كفاءة ، إذا كان الثاني أكثر كفاءة. حتى أنك وصفت ، لماذا لا ينبغي عليك استخدام ما إذا كان هناك: "أنه يتجنب الاضطرار إلى التحقق من متغير النظام $ على كل طلب". إن الهدف من عدم استخدام ifs لا يتعلق بالأداء فقط ، بل يتعلق أيضًا بالتصريح وليس ضروريًا. - pepkin88
+1 إذا كان ($ program = http) - Fernando Kosh
يجب استخدام مضيف $ هنا ، كما هو مذكور في الإجابات الأخرى. - Artem Russakovskii


إذا كنت تستخدم تعريف خادم 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;

مع خط إعادة كتابة براتيك.


56
2017-08-08 11:12



DavidPashley يعمل الحل الخاص بك مثل سحر بالنسبة لي. شكر - Jayesh Gopalan
If you are using the new dual HTTP and HTTPS server definition ثم يجب فصلها. - VBart
أنيق ويعمل الكمال! - jipipayo
كان هذا هو الحل الوحيد الذي عمل بالنسبة لي مع تكوين Laravel / Homestead Nginx الخاص بي. - Jared Eitnier
كما يجب أن يكون خط إعادة الكتابة return 301 https://$server_name$request_uri; لأن هذه هي الطريقة المفضلة. - Jared Eitnier


بعد متغير آخر ، يحافظ على المضيف: رأس الطلب ويتبع المثال "جيد" على nginx المزالق:

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

27
2018-04-11 12:20



Note that using $server_name instead of $host would always redirect to https://site1 ليس هذا ما $request_uri هو ل؟ - Jürgen Paul
$request_uri لا يحتوي على مضيف أو اسم مجال. بمعنى آخر ، يبدأ دائماً بحرف "/". - Peter
أفضل إجابة حتى الآن. - Ashesh
لست متأكدًا من سبب انخفاض هذه النسبة في الأصوات. انها الوحيدة التي تستحق استخدامها. - zopieux
لا أعتقد أن الكثير من الناس يستخدمون $ server_name هذه هي الطريقة الصحيحة للقيام بذلك - Greg Ennis


تأكد من تعيين "آمن" على أي ملفات تعريف ارتباط ، وإلا فسيتم إرسالها على طلب HTTP ويمكن الحصول عليها باستخدام أداة مثل Firesheep.


3
2018-03-23 00:40





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;
}

هذا يعمل بشكل أفضل أعتقد. يشير x.x.x.x إلى عنوان IP لخادمك. إذا كنت تعمل مع Plesk 12 ، فيمكنك القيام بذلك عن طريق تغيير ملف "nginx.conf" في الدليل "/var/www/vhosts/system/domain.tld/conf" لأي نطاق تريده. لا تنس إعادة تشغيل خدمة nginx بعد حفظ التكوين.


1
2017-08-23 19:40



rewrite ^ https://$host$request_uri? permanent;  سيكون أفضل حل لأنه قد يكون لديك العديد من أسماء الخوادم على vhost


أعتقد أن هذا هو الحل الأكثر بساطة. يفرض على كل من HTTPS و non-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;
    }
}

تعديل - أبريل 2018: الحل بدونه يمكن العثور على IF في مشاركتي هنا: https://stackoverflow.com/a/36777526/6076984


0
2018-04-21 18:30



أليست شروط IF تعتبر شريرة وغير فعالة في عالم nginx؟ - PKHunter
نعم هم ، بشكل عام. لكن بالنسبة لهذه الشيكات البسيطة ، لا أعتقد ذلك. لدي ملف تكوين مناسب يتضمن المزيد من كتابة التعليمات البرمجية ، ولكن يتجنب استخدام IF بشكل كامل. - stamster
تنصح Google باستخدام الرقم 301 بدلاً من 303. المصدر: support.google.com/webmasters/answer/6073543؟hl=en - dylanh724
DylanHunt - غادرت 303 فقط للاختبار ، تأخذ ملاحظة أن تم تعيين معالج 1 إلى 301 ، الثانية فقط نسيت لتغيير :) أيضا ، حل ث / س IF: stackoverflow.com/a/36777526/6076984 - stamster