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


10

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を私のホストに置き換えます...


1
私はいつもechoecho -e "GET / HTTP/1.1\r\nHost: example.com.br\r\n\r\n" | openssl s_client ...。これ\r\nは、HTTP標準がそうするように言っていることなので重要です。要求の最後にある2つのCRLFペアも重要です。これは、標準でそうするためです。また、「エコー」を「openssl」にどのようにパイプするかを

完了と表示されていますが、ウェブサイトへの応答はありません。それは正常ですか?Host:ヘッダーを私が尋ねた形式で書くことができないことに注意してください、それは私にgetの終わりにエラーを与えます。
Luciano Andress Martini

私は推測しています(そしてその推測にすぎません)が、正しいドキュメント名を指定していません。または、Cookieまたはアクセストークンを提供していません。サーバーはリクエストを取得し、クライアントエラーを示す4xxエラーコードでエラーを取得します。する必要があるかもしれGET /index.html ...ませんまたはあなたはクッキーを設定する必要があるかもしれません。curlまたはを試して、エラーを含む完全なリクエストとレスポンスwgetを投稿する必要があります。それ以外の場合は、実際のサーバー名とURLを指定して、テストを実行できるようにする必要があります。

私はサーバーを構成したときにURLの正しい名前を知っていますが、奇妙なのは、それがWebブラウザーで動作していることです。ホストで正しいドメイン名を指定しても、opensslを使用したくないのは非常に奇妙です。ヘッダ。500エラーは、データをプレーンテキストで送信している可能性が非常に高い(たとえばtelnetを使用)が、opensslが使用されています...あきらめるだけだと思います...それほど重要ではありません。 sslのWebサイトにtelnetで接続して、それを試したいが、うまくいかない例。
Luciano Andress Martini

「私はあきらめるつもりだと思います...」 -退職する場合は、質問を削除してください。Q&Aは完了せず、質問の回答は承認されません。この状態では、将来の訪問者に問題を引き起こす可能性があります。質問の削除についてサポートが必要な場合は、モデレーターの注意のためにフラグを付けてください。

回答:


19

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

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

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

-crlf-LFを端末からCRLFに変換します

次に、複数行のコマンドを入力し、最初のコマンドラインの後の応答として「不正な要求」はなくなりました。


それは今はより良いですが、単純なgetを実行した場合にのみ、ホストを指定しようとしても機能しません。
Luciano Andress Martini 2017

4

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

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

編集:私はウェイヘーがこれを行う方法を投稿しているのを確認します- -crlfフラグを使用しますが、この回答は別の方法としてここに残します。

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

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

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

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

(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 ...

3

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

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

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

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

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


2

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など)ではサポートされていないので注意してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.