Perintah openssl s_client selalu mengatakan 400 Permintaan Buruk

10

Saya mencoba menguji server yang berfungsi normal di browser web, dengan opsi openssl s_client, menghubungkannya langsung menggunakan openssl mengembalikan 400 Bad Request:

openssl s_client -servername example.com -connect example.com:443 -tls1
(some information about the certificate)

GET / HTTP/1.1 
(and the error occurs **immediately** - no time to include more headers like Host:)

Penting: Saya sudah mencoba untuk menempatkan Host: header, masalahnya adalah ketika saya menjalankan GET, kesalahan terjadi segera meninggalkan saya tidak ada kesempatan untuk memasukkan lebih banyak header. Ganti example.com dengan host saya ...

Luciano Andress Martini
sumber
1
Saya biasanya echo: echo -e "GET / HTTP/1.1\r\nHost: example.com.br\r\n\r\n" | openssl s_client .... Ini \r\npenting karena itulah yang dikatakan standar HTTP untuk dilakukan. Dua pasangan CRLF di akhir permintaan juga penting karena itulah yang dikatakan standar. Juga lihat Bagaimana Anda memasukkan "gema" ke "openssl"?
Dikatakan SELESAI, tetapi tidak ada respons untuk situs web, apakah itu normal? Perhatikan bahwa saya tidak bisa menulis Host: header dalam bentuk yang saya minta, itu memberi saya kesalahan di akhir get.
Luciano Andress Martini
Saya menebak (dan ini hanya dugaan), tetapi Anda tidak memberikan nama dokumen yang benar; atau Anda tidak menyediakan cookie atau token akses. Server mendapatkan permintaan Anda, dan kemudian kesalahan dengan kode kesalahan 4xx untuk menunjukkan kesalahan klien. Anda mungkin perlu GET /index.html ...atau Anda mungkin perlu mengatur cookie. Anda mungkin harus mencoba dengan curlatau wget, dan posting penuh permintaan dan respon, termasuk kesalahan. Jika tidak, Anda harus memberikan nama server dan URL nyata sehingga kami dapat menjalankan tes.
Saya tahu nama yang tepat untuk URL ketika saya mengkonfigurasi server, dan yang aneh adalah bahwa ia bekerja di browser web, sangat aneh untuk tidak ingin bekerja menggunakan openssl bahkan jika saya menentukan nama domain yang tepat di Host: tajuk. Kesalahan 500 sangat mungkin bahwa saya mengirim data dalam teks biasa (menggunakan telnet misalnya), tetapi openssl telah digunakan ... Saya pikir saya hanya akan menyerah .... Tidak begitu penting, hanya karena saya melihat contoh bagaimana telnet situs web ssl, dan ingin mencobanya, tetapi tidak baik-baik saja.
Luciano Andress Martini
"Saya pikir saya hanya akan menyerah ..." - Jika Anda akan pensiun, silakan hapus pertanyaannya. T&J tidak akan selesai, dan pertanyaan tidak akan pernah memiliki jawaban yang diterima. Dalam kondisi ini, ini dapat menyebabkan masalah bagi pengunjung di masa mendatang. Jika Anda perlu bantuan menghapus pertanyaan, tandai untuk perhatian moderator.

Jawaban:

19

Menurut https://bz.apache.org/bugzilla/show_bug.cgi?id=60695 perintah saya adalah:

openssl s_client -crlf -connect www.pgxperts.com:443

di mana -crlf berarti, sesuai dengan bantuan perintah openssl,

-crlf - mengkonversi LF dari terminal ke CRLF

Lalu saya bisa memasukkan perintah multiline dan tidak ada "permintaan buruk" sebagai respons setelah commandline pertama lagi.

Wei He
sumber
Lebih baik sekarang, tetapi tidak berfungsi ketika saya mencoba untuk menentukan host, hanya jika saya mendapatkan sederhana.
Luciano Andress Martini
4

OK memiliki hal yang sama sendiri dan butuh waktu untuk mencari tahu.

Saya tidak dapat menemukan cara untuk mengirim beberapa baris dalam permintaan saat menggunakan s_client secara interaktif. Selalu mengirim permintaan segera setelah Anda memasukkan baris pertama. Jika seseorang tahu bagaimana menyiasatinya, tolong beri tahu saya!

Sunting : Saya melihat Wei Dia telah memposting cara untuk melakukan ini - gunakan -crlfbendera tetapi meninggalkan jawaban ini di sini sebagai metode alternatif.

Sementara itu, seperti yang disarankan jww, Anda harus menggunakan echoini:

echo -e "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n" | openssl s_client ...

Masalah berikutnya adalah bahwa secara default openssl menutup koneksi ketika file input ditutup. Yang mana tidak langsung saat menggunakan echoseperti ini. Jadi Anda tidak punya waktu untuk melihat responsnya dan sebaliknya hanya melihat hasil DIBUAT! :-(

Anda dapat menambahkan sleepperintah echo untuk menyiasatinya (perhatikan tanda kurung penting):

(echo -e "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"; sleep 10) | openssl s_client ...

Atau, lebih baik dari itu, Anda dapat menggunakan -ign_eofopsi untuk membiarkan koneksi terbuka:

echo -e "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n" | openssl s_client -ign_eof ...

Atau lebih baik lagi, jika Anda hanya peduli dengan respons HTTP maka gunakan -quiteopsi yang menyembunyikan sebagian besar kebisingan TLS dan juga setel opsi -ign_eof untuk Anda:

echo -e "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n" | openssl s_client -quiet ...
Barry Pollard
sumber
3

Dari apa yang saya lihat, 400 Permintaan Buruk kemungkinan terkait dengan penggunaan HTTP / 1.1 di baris GET Anda.

Apakah Anda menambahkan header "Host:" setelah permintaan GET? RFC menyatakan bahwa untuk HTTP / 1.1, header Host diperlukan:

https://www.ietf.org/rfc/rfc2616.txt

19.6.1.1 Perubahan untuk Menyederhanakan Server Web Multi-homed dan Menghemat Alamat IP

Persyaratan bahwa klien dan server mendukung header permintaan Host, melaporkan kesalahan jika header permintaan Host (bagian 14.23) hilang dari permintaan HTTP / 1.1, dan menerima URI absolut (bagian 5.1.2) adalah di antara yang paling penting perubahan yang ditentukan oleh spesifikasi ini.

elem103
sumber
2

Anda dapat mengeluarkan permintaan GET dengan OpenSSL:

openssl s_client -quiet -connect cdn.sstatic.net:443 <<eof
GET /stackexchange/js/universal-login.js HTTP/1.1
Connection: close
Host: cdn.sstatic.net

eof

Perhatikan bahwa Anda juga dapat menggunakan "HTTP / 2", tetapi berhati-hatilah karena beberapa server (mis. Github.com) tidak mendukungnya.

Steven Penny
sumber