Openssl command s_client always says 400 Bad Request

21,457

Solution 1

According to https://bz.apache.org/bugzilla/show_bug.cgi?id=60695 my command was:

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

where -crlf means, according to help of the openssl command,

-crlf - convert LF from terminal into CRLF

Then I could input multiline commands and no "bad request" as response after the first commandline any more.

Solution 2

OK had the same thing myself and took a while to figure out.

I can't find a way to send multiple lines in the request when using s_client interactively. It always sends the request immediately as soon as you've entered the first line. If someone knows how to get around this then please let me know!

Edit: I see Wei He has posted the way to do this - use the -crlf flag but leaving this answer here as an alternative method.

In the meantime, as jww suggested, you have to use echo for this:

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

The next issue is that by default openssl closes the connection when the input file closes. Which is does immediately when using echo like this. So you don't get time to see the response and instead just see the DONE output! :-(

You can add a sleep to the echo command to get around this (note the brackets are important):

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

Or, better than that, you can use the -ign_eof option to leave the connection open:

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

Or better yet, if you're only concerned with the HTTP responses then use the -quite option which hides most of the TLS noise and also sets that -ign_eof option for you:

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

Solution 3

You can issue a GET request with 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

Note that you can also use "HTTP/2", but be careful because some servers (e.g. github.com) do not support it.

Solution 4

From what I can see, the 400 Bad Request is likely to be related to the use of HTTP/1.1 in your GET line.

Did you add a "Host:" header after the GET request? The RFC states that for HTTP/1.1, a Host header is required:

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

19.6.1.1 Changes to Simplify Multi-homed Web Servers and Conserve IP Addresses

The requirements that clients and servers support the Host request- header, report an error if the Host request-header (section 14.23) is missing from an HTTP/1.1 request, and accept absolute URIs (section 5.1.2) are among the most important changes defined by this specification.

Share:
21,457

Related videos on Youtube

Luciano Andress Martini
Author by

Luciano Andress Martini

Information Security &amp; Linux

Updated on September 18, 2022

Comments

  • Luciano Andress Martini
    Luciano Andress Martini over 1 year

    I am trying to test a server that is working normal in web browser, with openssl s_client option, connecting it directly using openssl returns the 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:)
    

    Important: I already tried to put the Host: header, the thing is that when i run GET, the error occur immediately leaving me no chance to include more headers. Replace example.com with my host...

    • Admin
      Admin almost 7 years
      I usually echo: echo -e "GET / HTTP/1.1\r\nHost: example.com.br\r\n\r\n" | openssl s_client .... The \r\n is significant because that's what the HTTP standard says to do. Two CRLF pairs at the end of the request is also significant because that's what the standard says to do. Also see How do you pipe “echo” into “openssl”?
    • Luciano Andress Martini
      Luciano Andress Martini almost 7 years
      It says DONE, but no response for the website, is that normal? Note that i cant write the Host: header in the form that i asked, it gives me the error at the end of the get.
    • Admin
      Admin almost 7 years
      I'm guessing (and its just a guess), but you are not supplying the correct document name; or you are not supplying a cookie or access token. The server gets your requests, and then errors with a 4xx error code to indicate a client error. You may need to GET /index.html ... or you may need to set a cookie. You should probably try with curl or wget, and post the full request and response, including the error. Otherwise, you have to provide a real server name and URL so we can run the tests.
    • Luciano Andress Martini
      Luciano Andress Martini almost 7 years
      I know the right name for the URL as i configured the server, and the strange thing is that it is working on the web browser, is very strange to do not want to work using openssl even if i specify the right domain name on Host: header. The 500 error is very likely that i am sending data in plain text (using telnet for example), but openssl has being used... I think i will just give up.... Is not so important, is just because i see a example of how to telnet a ssl website, and want to try it, but it does not doing fine.
    • Admin
      Admin almost 7 years
      "I think i will just give up..." - If you are going to retire, then please delete the question. The Q&A will not complete, and the question will never have an accepted answer. In this state, it could cause problems for future visitors. If you need help deleting the question, then flag it for moderator attention.
    • Luciano Andress Martini
      Luciano Andress Martini almost 7 years
      I cannot delete the question... is giving me a error. Note that is not solved, but my experience with stack exchange is that questions with some issue that nobody experiences results in some bad reputation... specially if i dont accept any answers. This is very sad, because i am being honestly, and i am following the right procedures until now. Why you want to remove the telnet tag? It is related to telnet, openssl s_client is sometimes used to emulate the telnet effect in TCP protocols but with SSL, like HTTPS. The HTTP port is working fine on the same server, with telnet, get and host header
    • Luciano Andress Martini
      Luciano Andress Martini almost 7 years
      Well some people can get angry why just you dont accept my answer? Or this wonderful upvoted answer? and start to downvote, i haved this problems sometimes, not in this specifc community... But thank you i will leave the question if someone can emulate my problem i will appreciate, note i am running apache2 with a virtual host configured.
  • Luciano Andress Martini
    Luciano Andress Martini almost 7 years
    It is better now, but does not work when i try to specify a host, only if i do a simple get.
  • Barry Pollard
    Barry Pollard almost 4 years
    You do to put the host in. OpenSSL will send that automatically.