P: En uno de nuestros servidores, el servidor web no está configurado para admitir SSLv2 o SSLv3. Ambos están deshabilitados en el lado del servidor. Solo es compatible con TLSv1. ¿Cómo puedo hacer que curl funcione tanto desde la línea de comandos como desde dentro de mi código PHP?
Especifique el protocolo en la línea de comandos Curl
Las siguientes son las diversas opciones de protocolo admitidas en la línea de comando por curl:
- -0 (o) –http1.0 para HTTP 1.0 (H)
- -1 (o) –tlsv1 para TLSv1 (SSL)
- -2 (o) –sslv2 para SSLv2 (SSL)
- -3 (o) –sslv3 para SSLv3 (SSL)
En este ejemplo, este servidor en particular funciona en HTTP normal. No hay problemas aquí.
$ curl http://192.168.101.1 <html><body><h1>It works!</h1></body></html>
Consulte esto:15 ejemplos prácticos de comandos cURL de Linux
Pero, si usa SSLv3, usando la opción -3, devuelve el mensaje de error "falla de protocolo de enlace de alerta sslv3".
$ curl -3 https://192.168.101.1 curl: (35) error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
Si usa SSLv2, usando la opción -2, devuelve el mensaje de error "Protocolo SSL desconocido".
$ curl -2 https://192.168.101.1 curl: (35) Unknown SSL protocol error in connection to 192.168.101.1:443
En este caso, en este servidor en particular, solo admite TLS. Entonces, use la opción -1 como se muestra a continuación.
$ curl -1 https://192.168.101.1 curl: (60) SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
En este caso, dado que estamos utilizando la dirección IP, que no coincide con el certificado SSL que está instalado en el servidor web. Por lo tanto, recibimos el mensaje de error anterior "SSL3_GET_SERVER_CERTIFICATE:verificación de certificado fallida".
Curl por defecto realiza la verificación del certificado SSL. Si utiliza un paquete de autoridad de CA, el nombre del paquete predeterminado es curl-ca-bundle.crt. Puede especificar un paquete diferente usando la opción –cacert.
Pero, en nuestro caso, queremos usar el protocolo TLSv1, pero sin la verificación del certificado SSL. Para ello, utilice la opción -k (o la opción –insecure), que no realizará la verificación del certificado SSL.
El siguiente es un uso de la opción -k.
$ curl -k https://192.168.101.1 curl: (35) Unknown SSL protocol error in connection to 192.168.101.1:443
Si desea conocer más detalles sobre el error arrojado por el comando CURL, use la opción -v. Como ves a continuación. Incluso cuando no pasamos la opción de protocolo, desde el resultado del comando, podemos ver que está tratando de usar SSLv2 para esto.
$ curl -k -v https://192.168.101.1 * About to connect() to 192.168.101.1 port 443 * Trying 192.168.101.1... connected * Connected to 192.168.101.1 (192.168.101.1) port 443 * successfully set certificate verify locations: * CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none * SSLv2, Client hello (1): Unknown SSL protocol error in connection to 192.168.101.1:443 * Closing connection #0 curl: (35) Unknown SSL protocol error in connection to 192.168.101.1:443
Solución desde la línea de comandos
Consulte esto:wget vs curl:Cómo descargar archivos usando wget y curl
Entonces, en nuestro caso, dado que SSLv2 y SSLv3 están deshabilitados en el lado del servidor, y por alguna razón si curl no configura automáticamente el protocolo correcto, lo siguiente funciona cuando queremos usar solo el protocolo TLSv1 con curl desde la línea de comando como se muestra a continuación.
$ curl -k -1 https://192.168.101.1 <html><body><h1>It works!</h1></body></html>
Si desea ver los detalles de lo que hace exactamente, pase la opción -v como se muestra a continuación.
$ curl -k -1 -v https://192.168.101.1
Lo anterior también se puede hacer usando las siguientes opciones alternativas
$ curl --insecure --tlsv1 --verbose https://192.168.101.1
Nuevamente, en el comando anterior:
- -1 (o) –tlsv1 para TLSv1 (SSL)
- -k (o) –insecure para permitir conexiones a sitios SSL sin certificados (H)
- -v (o) –verbose para hacer que la operación sea más comunicativa (v minúscula)
Solución desde PHP
Desde su código PHP, si está utilizando las funciones cURL y desea configurar las opciones de protocolo, debe usar la función curl_setopt o curl_setopt_array.
Use curl_setopt si desea establecer solo una opción.
curl_setopt($c, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
En lo anterior:
- $c es la variable curl que obtuvo de la función curl_init(), cuando creó un nuevo recurso cURL desde su programa PHP.
- CURLOPT_SSLVERSION es un nombre de opción curl.
- CURL_SSLVERSION_TLSv1 es un valor curl para la opción correspondiente en el parámetro #2
También puede usar un número en lugar de "CURL_SSLVERSION_TLSv1". En este ejemplo, esto es equivalente a 1.
curl_setopt($c, CURLOPT_SSLVERSION, 1);
Los siguientes son posibles valores CURLOPT_SSLVERSION que puede establecer. Puede usar la constante descriptiva o el número correspondiente que se muestra a continuación.
- CURL_SSLVERSION_DEFAULT (0)
- CURL_SSLVERSION_TLSv1 (1)
- CURL_SSLVERSION_SSLv2 (2)
- CURL_SSLVERSION_SSLv3 (3)
- CURL_SSLVERSION_TLSv1_0 (4)
- CURL_SSLVERSION_TLSv1_1 (5)
- CURL_SSLVERSION_TLSv1_2 (6)
Cuando desee configurar la opción CURL múltiple, use curl_setopt_array como se muestra a continuación. Aquí, además de configurar CURLOPT_SSLVERSION, también configura algunas otras opciones de curl.
En este caso, el segundo parámetro será una matriz que contendrá múltiples opciones de CURL como se muestra a continuación.
curl_setopt_array($c, array ( CURLOPT_SSL_VERIFYHOST => 0, CURLOPT_SSL_VERIFYPEER => 0, CURLOPT_SSLVERSION => 1 ));