我正在尝试使用 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 节)。本规范定义的更改。