nginx try_files redirect menggunakan skema yang salah ketika di belakang penyeimbang beban terminasi SSL (haproxy)

8

Saya memiliki server nginx 1.6.2 yang berjalan sebagai backend di belakang load balancer yang melakukan terminasi SSL. Semua komunikasi ke server backend melewati HTTP.

Diagram dari apa yang terjadi:

          /--http---> frontend:80  --\
client --+                            +--http---> backend:8000
          \--https--> frontend:443 --/

                      LOAD BALANCER                BACKENDS

Untuk tujuan pengujian saya hanya memiliki satu backend saat ini. Penyeimbang beban menjalankan HAProxy 1.5, yang saya kendalikan.

Saya memiliki try_filesarahan yang cukup khas di serverblok saya di konfigurasi nginx backend:

server {
    server_name frontend;
    ...
    try_files $uri $uri/ =404;
    ...
}

Sekarang, secara default, ketika saya mengakses direktori tanpa garis miring, misalnya https://frontend/somedir, nginx ingin mengirim HTTP 301 redirect ke URL absolut seperti http://frontend:8000/somedir/.

Saya dapat membuat nginx menghilangkan nomor port 8000 menggunakan port_in_redirect off.

Namun saya tidak bisa memperbaiki http://skema di awal nginx redirect yang dihasilkan. Yang terbaik yang bisa saya dapatkan dari nginx adalah pengalihan dari https://frontend/somedirke http://frontend/somedir/, secara efektif menghapus SSL!

Penyeimbang beban mengirim X-Forwarded-Prototajuk tetapi saya tidak melihat cara apa pun untuk nginx untuk berkonsultasi ketika menyusun pengalihannya; sebenarnya ada jawaban 2012 yang mengatakan nginx langsung tidak bisa melakukan ini, dan solusinya adalah mengganti load balancer dengan nginx. IMHO ini hal yang terlalu sepele untuk menjamin perubahan tumpukan yang drastis.

Apakah ada yang berubah sejak 2012 di sini? Saya tidak benar-benar ingin menulis ulang pengalihan ini di tingkat HAProxy: HTTPS disengaja yang sebenarnya ke pengalihan HTTP dari aplikasi web mungkin mendapatkan "HTTPSed kembali" jika saya selalu selalu menulis ulang skema untuk Location:header respons yang sama dengan skema permintaan dibuat dengan.

EDIT:

Ini adalah konfigurasi diminimalkan yang menunjukkan nginx menghasilkan Location:URL absolut . Perhatikan tidak ada penulisan ulang.

user nobody nobody;
worker_processes auto;
worker_rlimit_nofile 4096;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
    multi_accept on;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    # TODO: Tune fastcgi_buffers/other buffers

    # Configure keepalive connections
    keepalive_timeout 15;
    keepalive_requests 1000;

    # Hide server version.
    server_tokens off;

    # Do not allow any directory indexes anywhere.
    # This is the default, but it is here for extra paranoia.
    autoindex off;

    # gzip text content.
    gzip on;
    gzip_vary on;
    gzip_disable "msie6";
    gzip_comp_level 2;
    gzip_min_length 1024;
    gzip_types  text/css
                text/plain
                text/xml
                application/json
                application/javascript;

    server {
        listen 8000 default_server;

        root /usr/share/nginx/html;
        index index.html index.htm;

        server_name localhost;

        location / {
            try_files $uri $uri/ =404;
        }
    }
}

Dan jika Anda menggunakan ikal untuk melihat header - perhatikan saya telah membuat direktori di testdirbawah /usr/share/nginx/html:

[myuser@dev nginx]$ curl -i http://localhost:8000/testdir
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Thu, 26 Mar 2015 14:35:49 GMT
Content-Type: text/html
Content-Length: 178
Location: http://localhost:8000/testdir/
Connection: keep-alive

<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
mutron
sumber
nginx wants to send an HTTP 301 redirect to an absolute URL- nginx tidak melakukan itu kecuali Anda memiliki aturan penulisan ulang yang eksplisit untuk melakukannya - tolong tunjukkan konfigurasi lengkap Anda.
AD7six
Saya menambahkan konfigurasi, dipangkas untuk hanya menggambarkan masalah ini. Saya tidak melakukan penulisan ulang eksplisit.
mutron
1
Anda harus mengkonfigurasi balancer Anda untuk mengganti protokol di Location:header karena nginx tidak tahu apa itu protokol asli.
Alexey Ten
2
@AlexeyTen Anda ingin memposting itu sebagai jawaban sehingga saya bisa menyetujuinya? Saya belum menemukan cara untuk melakukan ini di nginx, jadi perubahan pada penyeimbang beban memang tampaknya menjadi satu-satunya cara.
mutron
1
Ini masih bug dengan rilis nginX terbaru! Apakah ada yang tahu jika sudah ada laporan bug? Tidak dapat menemukannya.
Roel van Duijnhoven

Jawaban:

2

Maju cepat ke 2019 dan Anda dapat:

absolute_redirect off; 
port_in_redirect off;

Dari dokumen untukabsolute_redirect :

Jika dinonaktifkan, arahan ulang yang dikeluarkan oleh nginx akan relatif.

Danila Vershinin
sumber
-1

Anda perlu memberitahu penyeimbang beban untuk menulis ulang httpke httpsdalam permintaan seperti:

proxy_redirect http:// $scheme://;
HostFission
sumber