Berurusan dengan nginx 400 Kesalahan "Permintaan HTTP biasa telah dikirim ke port HTTPS"


115

Saya menjalankan aplikasi Sinatra di belakang penumpang / nginx. Saya mencoba membuatnya merespons panggilan http dan https. Masalahnya adalah, ketika keduanya didefinisikan di blok server, panggilan https ditanggapi secara normal tetapi http menghasilkan kesalahan 400 "Permintaan HTTP biasa telah dikirim ke port HTTPS". Ini untuk halaman statis jadi saya kira Sinatra tidak ada hubungannya dengan ini. Ada ide tentang cara memperbaikinya?

Berikut blok servernya:

server {
        listen 80;
        listen 443  ssl;
        server_name localhost;
        root /home/myhome/app/public;
        passenger_enabled on;

        ssl on;
        ssl_certificate      /opt/nginx/ssl_keys/ssl.crt;
        ssl_certificate_key  /opt/nginx/ssl_keys/ssl.key;
        ssl_protocols        SSLv3 TLSv1;
        ssl_ciphers          HIGH:!aNULL:!MD5;

        location /static {
            root  /home/myhome/app/public;
            index  index.html index.htm index.php;
        }

        error_page 404 /404.html;

        # redirect server error pages to the static page /50x.html
        error_page 500 /500.html;

        access_log /home/myhome/app/logs/access.log;
        error_log /home/myhome/app/logs/error.log;
}

Dalam kasus saya, url di browser: my.example.com:443tidak berfungsi. Mengubah itu malah https://my.example.comberhasil. Aneh, tidak pernah mengalami masalah ini dengan apache.
Sebastian

1
ssl on;memberi tahu NGINX ke server SETIAP konten melalui SSL. Gunakan tanda "ssl" di akhir listen 443;mis. listen 443 ssl;Jika server Anda memberikan lalu lintas http dan https, dan hapus ssl on;perintah.
Stphane

Jawaban:


195

Saya mengalami masalah serupa. Ia bekerja di satu server dan tidak di server lain dengan konfigurasi Nginx yang sama. Temukan solusi yang dijawab oleh Igor di sini http://forum.nginx.org/read.php?2,1612,1627#msg-1627

Iya. Atau Anda dapat menggabungkan server SSL / non-SSL dalam satu server:

server {
  listen 80;
  listen 443 default ssl;

  # ssl on   - remember to comment this out

}

Per apa yang dikatakan rapam iosif, pastikan Anda juga memasukkanssl off;
aceofspades

20
Anda hanya perlu menghapus garis ssl on;(tidak perlu menambahkan ssl). Juga, karena saya tidak ingat versi Nginx, tidak ada lagi kebutuhan untuk digunakan defaultpada listen 443line. Jadi konfigurasi OP baik-baik saja, hanya perlu menghapus ssl ondan seharusnya berfungsi.
laurent

@bobojam jangan sungkan untuk mencantumkan penjelasan dari jawaban saya, agar jawaban anda lebih lengkap. Saya telah meminta penulis OP untuk menerima jawaban Anda.
Alexander Azarov

2
Bagaimana cara menyelesaikan tujuan SSL dengan berkomentar ssl on. @ MichaelJ.Evans jawaban di bawah ini adalah solusi yang jauh lebih baik.
Neel

1
Sepertinya tidak berfungsi dengan banyak file conf. Mengatakan ada 2 default duplikat. Gunakan solusi Alexander.
Ryall

39

Jawaban di atas salah karena sebagian besar pengujian 'apakah HTTPS koneksi ini' untuk memungkinkan penyajian halaman melalui http terlepas dari keamanan sambungan.

Jawaban aman menggunakan halaman kesalahan pada kode kesalahan http 4xx NGINX khusus untuk mengarahkan klien untuk mencoba kembali permintaan yang sama ke https. (seperti diuraikan di sini /server/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx )

OP harus menggunakan:

server {
  listen        12345;
  server_name   php.myadmin.com;

  root         /var/www/php;

  ssl           on;

  # If they come here using HTTP, bounce them to the correct scheme
  error_page 497 https://$host:$server_port$request_uri;

  [....]
}

1
Anda mungkin ingin $ server_name daripada $ host, nama_server mungkin disetel ke CN yang diautentikasi oleh sertifikat SSL. Dengan begitu, pengguna tidak akan mendapatkan layar ketakutan jika mereka masuk melalui IP atau localhost.
George

Saya mencoba menerapkan ini pada instalasi lokal GitLab saya , tetapi menggunakan pengaturan Menyisipkan NGINX kustom ke dalam metode blok server GitLab sehingga nginx['custom_gitlab_server_config'] = "error_page 497 https://$host:$server_port$request_uri;"berhasil
Aaron C

17

Kesalahan mengatakan itu semua sebenarnya. Konfigurasi Anda memberi tahu Nginx untuk mendengarkan pada port 80 (HTTP) dan menggunakan SSL. Saat Anda mengarahkan browser ke http://localhost, browser mencoba menghubungkan melalui HTTP. Karena Nginx mengharapkan SSL, Nginx mengeluh dengan kesalahannya.

Solusinya sangat sederhana. Anda membutuhkan dua serverbagian:

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}

7
Anda sebenarnya tidak membutuhkan dua bagian server. Hapus baris "ssl on" dan ubah baris dengar sesuai jawaban @ bobojam.
toxaq

12

Saya mengalami masalah yang persis sama, saya memiliki jenis konfigurasi yang sama dengan contoh Anda dan saya berhasil melakukannya dengan menghapus baris:

ssl on;

Mengutip dok:

Jika server HTTP dan HTTPS sama, satu server yang menangani permintaan HTTP dan HTTPS dapat dikonfigurasi dengan menghapus perintah "ssl on" dan menambahkan parameter ssl untuk *: 443 port


1
Adakah kemungkinan Anda memiliki tautan ke dok?
Adam Parkin

12

Menurut artikel wikipedia tentang kode status . Nginx memiliki kode kesalahan khusus ketika lalu lintas http dikirim ke port https (kode kesalahan 497)

Dan menurut dokumen nginx di error_page , Anda dapat menentukan URI yang akan ditampilkan untuk kesalahan tertentu.
Dengan demikian kita dapat membuat uri yang akan dikirim klien ketika kode kesalahan 497 dimunculkan.

nginx.conf

#lets assume your IP address is 89.89.89.89 and also 
#that you want nginx to listen on port 7000 and your app is running on port 3000

server {
    listen 7000 ssl;
 
    ssl_certificate /path/to/ssl_certificate.cer;
    ssl_certificate_key /path/to/ssl_certificate_key.key;
    ssl_client_certificate /path/to/ssl_client_certificate.cer;

    error_page 497 301 =307 https://89.89.89.89:7000$request_uri;

    location / {
        proxy_pass http://89.89.89.89:3000/;

        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Protocol $scheme;
    }
}

Namun jika klien membuat permintaan melalui metode lain kecuali GET, permintaan itu akan diubah menjadi GET. Jadi untuk mempertahankan metode permintaan yang masuk melalui klien; kami menggunakan pengalihan pemrosesan kesalahan seperti yang ditunjukkan dalam dokumen nginx di error_page

Dan itulah mengapa kami menggunakan 301 =307pengalihan.

Dengan menggunakan file nginx.conf yang ditunjukkan di sini, kita dapat memiliki http dan https yang didengarkan pada port yang sama


ini berfungsi untuk saya - error_page 497 301 = 307 89.89.89.89:7000$request_uri ;
ugali soft

7

Berikut adalah contoh untuk mengkonfigurasi HTTP dan HTTPS di blok konfigurasi yang sama dengan dukungan ipv6 . Konfigurasi diuji di Server Ubuntu dan NGINX / 1.4.6 tetapi ini harus bekerja dengan semua server.

server {
    # support http and ipv6
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    # support https and ipv6
    listen 443 default_server ssl;
    listen [::]:443 ipv6only=on default_server ssl;

    # path to web directory
    root /path/to/example.com;
    index index.html index.htm;

    # domain or subdomain
    server_name example.com www.example.com;

    # ssl certificate
    ssl_certificate /path/to/certs/example_com-bundle.crt;
    ssl_certificate_key /path/to/certs/example_com.key;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
}

Jangan sertakan ssl onyang dapat menyebabkan 400error. Konfigurasi di atas seharusnya berfungsi

http://example.com

http://www.example.com

https://example.com

https://www.example.com

Semoga ini membantu!



4

Sebenarnya Anda bisa melakukan ini dengan:

ssl off; 

Ini memecahkan masalah saya dalam menggunakan nginxvhosts; sekarang saya dapat menggunakan SSL dan HTTP biasa. Bekerja bahkan dengan port gabungan.


Bekerja untuk saya di nginx / 1.6.3 :)
djthoms
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.