web-dev-qa-db-ja.com

opensslコマンドs_clientは常に400 Bad Requestと表示します

Openssl s_clientオプションを使用してWebブラウザーで正常に動作しているサーバーをテストしようとしています。opensslを使用して直接接続すると、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:)

重要:既にHost:ヘッダーを配置しようとしましたが、GETを実行するとエラーがすぐに発生し、ヘッダーを追加する機会がありません。 example.comを自分のホストに置き換えます...

https://bz.Apache.org/bugzilla/show_bug.cgi?id=60695 によると、私のコマンドは:

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

ここで-crlfは、opensslコマンドのヘルプに従って、

-crlf-変換LF端末からCRLFに変換

次に、複数行のコマンドを入力し、最初のコマンドラインの後の応答として「悪い要求」はもうありません。

19
Wei He

OK私自身も同じことがあり、理解するのにしばらく時間がかかりました。

S_clientをインタラクティブに使用する場合、リクエストで複数の行を送信する方法が見つかりません。最初の行を入力するとすぐに、リクエストは常にすぐに送信されます。誰かがこれを回避する方法を知っているなら、私に知らせてください!

編集:Wei Heがこれを行う方法を投稿したようです--crlfフラグですが、この回答は別の方法としてここに残します。

その間、jwwが示唆したように、これにはechoを使用する必要があります。

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

次の問題は、デフォルトでopensslが入力ファイルを閉じるときに接続を閉じることです。これは、echoをこのように使用するとすぐに行われます。したがって、応答を確認する時間はなく、代わりにDONE出力を確認するだけです。 :-(

Echoコマンドにsleepを追加すると、これを回避できます(角括弧は重要です)。

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

または、それよりも優れた-ign_eof接続を開いたままにするオプション:

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

または、HTTP応答のみに関心がある場合は、-quiteオプションは、TLSノイズのほとんどを隠し、その-ign_eofオプションを設定します。

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

私が見ることができることから、400 Bad Requestは、GET行でのHTTP/1.1の使用に関連している可能性があります。

GETリクエストの後に「Host:」ヘッダーを追加しましたか? RFCには、HTTP/1.1の場合、ホストヘッダーが必要であると記載されています。

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

19.6.1.1マルチホームWebサーバーを簡素化し、IPアドレスを節約するための変更

クライアントとサーバーがホストリクエストヘッダーをサポートし、ホストリクエストヘッダー(セクション14.23)がHTTP/1.1リクエストにない場合にエラーを報告し、絶対URI(セクション5.1.2)を受け入れるという要件が最も重要ですこの仕様で定義された変更。

3
elem103

OpenSSLを使用してGETリクエストを発行できます。

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

「HTTP/2」を使用することもできますが、一部のサーバー(github.comなど)ではサポートされていないので注意してください。

2
Steven Penny