9

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

  • 1
    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”? – user56041 Jun 14 '17 at 12:54
  • 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. – Luciano Andress Martini Jun 14 '17 at 13:29
  • 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. – user56041 Jun 14 '17 at 20:46
  • 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. – Luciano Andress Martini Jun 16 '17 at 13:21
  • "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. – user56041 Jun 16 '17 at 13:33
18

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.

  • It is better now, but does not work when i try to specify a host, only if i do a simple get. – Luciano Andress Martini Jul 25 '17 at 18:36
4

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

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.

1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.