tulis ulang http ke https dengan ngnix di belakang load balancer

13

Saya menggunakan penyeimbang beban Rackspace yang memungkinkan saya untuk mengatur kunci ssl saya / pem di dalam panel admin. Semuanya berfungsi dengan baik, saya bisa menggunakan protokol http dan https. Tetapi jika saya mencoba mengalihkan http ke https menggunakan:

server{
  listen *:80;
  server_name mydomain.com www.mydomain.com; 
  rewrite ^ https://mydomain.com$request_uri? permanent;

... Saya mendapatkan loop pengalihan. Saya sadar saya tidak mendengarkan port 443 tapi itu karena penyeimbang beban menangani itu untuk saya. Saya juga mencoba membungkus penulisan ulang if ($scheme ~* http){tanpa hasil.

Bagian lain dari pertanyaan saya adalah bahwa saya ingin menghapus www dari url, dapatkah saya melakukan ini dengan penulisan ulang tunggal? Bukankah seharusnya penulisan ulang di atas juga menangani hal ini?

Terima kasih atas bantuan Anda!

jwerre
sumber
Penyeimbang beban harus mengirimkan beberapa indikasi kepada Anda apakah koneksi itu HTTPS. Tanyakan Rackspace. (Oh, dan Anda mungkin tidak ingin menyingkirkan www ...)
Michael Hampton
Menarik, saya akan melihatnya. Mengapa Anda pikir saya tidak harus menyingkirkan www?
jwerre

Jawaban:

14

sciurus benar dalam Cloud Load Balancers Rackspace yang mengatur X-Forwarded-Proto ke https ketika SSL diturunkan di load balancer. Untuk menghindari loop redirect di nginx, Anda harus dapat menambahkan berikut ini ke locationbagian dalam konfigurasi vhost:

if ($http_x_forwarded_proto = "http") {
            rewrite  ^/(.*)$  https://mydomain.com/$1 permanent;
}

Ini harus menghindari loop pengalihan tanpa batas sambil mengarahkan permintaan non-https ke https.

slade
sumber
18

Dengan menggunakan variabel server bawaan nginx $request_uridan $server_nameAnda dapat melakukan ini tanpa menggunakan ekspresi reguler sama sekali. Tambahkan berikut ini ke locationblok server Anda dan Anda selesai:

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

Ini mengasumsikan load balancer Anda mengirimkan $http_x_forwarded_protoheader bersama dengan permintaan ke instance backend Anda. Header umum lainnya termasuk $http_x_forwarded_schemedan juga adil $scheme.

Informasi lebih lanjut dapat ditemukan di dokumentasi Pitgin dan Kesalahan Umum nginx : https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#taxing-rewrites

Luke Peterson
sumber
5
Harus pasti menggunakan pengembalian atas penulisan ulang. Terpilih.
designermonkey
1
Anda dapat menggunakan $hostsebagai gantinya$server_name
Yossi
tidak bekerja dengan server_name _; jadi kita harus menggunakan variabel $ host seperti yang disarankan @Yossi.
Razvan Grigore
1

Penyeimbang beban selalu berbicara kepada Anda melalui http. Apa yang terjadi adalah

  1. Browser membuat permintaan ke port 80 pada load balancer
  2. Penyeimbang beban membuat permintaan ke port 80 di server web Anda
  3. Server web Anda mengirimkan pengalihan ke pengguna
  4. Pengguna membuat permintaan ke port 443 pada penyeimbang beban

Langkah 2-4 terus berulang sampai browser mendeteksi loop redirect dan menyerah.

EDIT: Untuk mengatasi ini, hanya melakukan penulisan ulang ketika header X-Forwarded-Proto diatur ke http. Header itu adalah bagaimana penyeimbang beban Rackspace memberi tahu server web Anda protokol yang melaluinya ia menerima permintaan.

sciurus
sumber
Saya kira itu akan menjelaskan mengapa $ server_protocol selalu mengembalikan HTTP
jwerre
Jadi Anda menjawab mengapa ini terjadi ... ada saran tentang cara memperbaikinya?
jwerre