El comando Openssl s_client siempre dice 400 Solicitud incorrecta

10

Estoy tratando de probar un servidor que funciona normalmente en el navegador web, con la opción openssl s_client, conectándolo directamente mediante openssl devuelve la 400 Solicitud incorrecta:

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:)

Importante: ya traté de poner el encabezado Host: la cuestión es que cuando ejecuto GET, el error ocurre de inmediato y no me da la posibilidad de incluir más encabezados. Reemplazar example.com con mi host ...

Luciano Andress Martini
fuente
1
Por lo general echo: echo -e "GET / HTTP/1.1\r\nHost: example.com.br\r\n\r\n" | openssl s_client .... Esto \r\nes significativo porque eso es lo que dice hacer el estándar HTTP. Dos pares de CRLF al final de la solicitud también es importante porque eso es lo que el estándar dice que haga. Consulte también ¿Cómo canaliza "echo" en "openssl"?
Dice HECHO, pero no hay respuesta para el sitio web, ¿es eso normal? Tenga en cuenta que no puedo escribir el encabezado Host: en el formulario que solicité, me da el error al final de la obtención.
Luciano Andress Martini
Supongo (y es solo una suposición), pero no está proporcionando el nombre correcto del documento; o no está proporcionando una cookie o token de acceso. El servidor recibe sus solicitudes y luego los errores con un código de error 4xx para indicar un error del cliente. Es posible GET /index.html ...que deba configurar una cookie. Probablemente debería tratar con curlo wget, y después de la completa solicitud y respuesta, incluyendo el error. De lo contrario, debe proporcionar un nombre de servidor real y una URL para que podamos ejecutar las pruebas.
Sé el nombre correcto para la URL cuando configuré el servidor, y lo extraño es que está funcionando en el navegador web, es muy extraño no querer trabajar usando openssl incluso si especifico el nombre de dominio correcto en el Host: encabezamiento. Es muy probable que el error 500 esté enviando datos en texto plano (usando telnet, por ejemplo), pero se está utilizando openssl ... Creo que me rendiré ... No es tan importante, es solo porque veo Un ejemplo de cómo hacer un telnet de un sitio web SSL y si quiere probarlo, pero no funciona bien.
Luciano Andress Martini
"Creo que me rendiré ..." - Si se va a retirar, elimine la pregunta. Las preguntas y respuestas no se completarán, y la pregunta nunca tendrá una respuesta aceptada. En este estado, podría causar problemas para futuros visitantes. Si necesita ayuda para eliminar la pregunta, márquela para la atención del moderador.

Respuestas:

19

De acuerdo con https://bz.apache.org/bugzilla/show_bug.cgi?id=60695 mi comando fue:

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

donde -crlf significa, según la ayuda del comando openssl,

-crlf - convierte LF de terminal a CRLF

Entonces podría ingresar comandos multilínea y ninguna "solicitud incorrecta" como respuesta después de la primera línea de comando.

Wei He
fuente
Ahora es mejor, pero no funciona cuando trato de especificar un host, solo si hago un get simple.
Luciano Andress Martini
4

OK tuve lo mismo y me tomó un tiempo resolverlo.

No puedo encontrar una manera de enviar varias líneas en la solicitud cuando uso s_client de forma interactiva. Siempre envía la solicitud de inmediato tan pronto como ingrese la primera línea. Si alguien sabe cómo solucionar esto, ¡házmelo saber!

Editar : Veo que Wei ha publicado la forma de hacer esto: use la -crlfbandera pero deje esta respuesta aquí como un método alternativo.

Mientras tanto, como sugirió jww, debe usar echopara esto:

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

El siguiente problema es que, por defecto, openssl cierra la conexión cuando se cierra el archivo de entrada. Lo que se hace inmediatamente cuando se usa echoasí. ¡Así que no tienes tiempo para ver la respuesta y solo ves la salida HECHO! :-(

Puede agregar un sleepcomando de eco para evitar esto (tenga en cuenta que los corchetes son importantes):

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

O, mejor que eso, puede usar la -ign_eofopción para dejar la conexión abierta:

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

O mejor aún, si solo le preocupan las respuestas HTTP, use la -quiteopción que oculta la mayor parte del ruido TLS y también establece esa opción -ign_eof para usted:

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

Por lo que puedo ver, es probable que la 400 Solicitud incorrecta esté relacionada con el uso de HTTP / 1.1 en su línea GET.

¿Agregó un encabezado "Host:" después de la solicitud GET? El RFC establece que para HTTP / 1.1, se requiere un encabezado de host:

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

19.6.1.1 Cambios para simplificar los servidores web de alojamiento múltiple y conservar las direcciones IP

Los requisitos que los clientes y servidores admiten el encabezado de solicitud del Host, informan un error si falta el encabezado de solicitud del Host (sección 14.23) en una solicitud HTTP / 1.1 y aceptan URI absolutos (sección 5.1.2) entre los más importantes cambios definidos por esta especificación.

elem103
fuente
2

Puede emitir una solicitud GET con 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

Tenga en cuenta que también puede usar "HTTP / 2", pero tenga cuidado porque algunos servidores (por ejemplo, github.com) no lo admiten.

Steven Penny
fuente