Openssl 命令 s_client 总是显示 400 Bad Request

Openssl 命令 s_client 总是显示 400 Bad Request

我正在尝试使用 openssl s_client 选项测试在网络浏览器中正常工作的服务器,使用 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

根据https://bz.apache.org/bugzilla/show_bug.cgi?id=60695我的命令是:

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

其中 -crlf 表示,根据 openssl 命令的帮助,

-crlf - 将 LF 从终端转换为 CRLF

然后我可以输入多行命令,并且在第一个命令行之后不再有“错误请求”作为响应。

答案2

好吧,我自己也有同样的事情,花了一段时间才弄清楚。

交互使用 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 输出! :-(

您可以sleep在 echo 命令中添加 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 响应,那么使用-quiet隐藏大部分 TLS 噪音的选项,并为您设置 -ign_eof 选项:

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

答案3

您可以使用 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)不支持它。

答案4

据我所知,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 地址的更改

最重要的要求包括客户端和服务器支持主机请求标头、如果 HTTP/1.1 请求中缺少主机请求标头(第 14.23 节)则报告错误以及接受绝对 URI(第 5.1.2 节)。本规范定义的更改。

相关内容