Otázka: Na jednom z našich serverů není webový server nastaven na podporu SSLv2 nebo SSLv3. Obojí je na straně serveru zakázáno. Podporuje pouze TLSv1. Jak mohu přimět curl, aby fungoval jak z příkazového řádku, tak zevnitř mého kódu PHP?
Odpověď: Ve většině případů curl automaticky vybere správný protokol a připojí se k němu. Můžete však také určit konkrétní protokol, který se má použít pro příkaz curl. V tomto příkladu musíte dát pokyn CURL, aby používal TLSv1, jak je vysvětleno v tomto tutoriálu.
Zadejte protokol na příkazovém řádku Curl
Následují různé možnosti protokolu podporované na příkazovém řádku pomocí curl:
- -0 (nebo) –http1.0 pro HTTP 1.0 (H)
- -1 (nebo) –tlsv1 pro TLSv1 (SSL)
- -2 (nebo) –sslv2 pro SSLv2 (SSL)
- -3 (nebo) –sslv3 pro SSLv3 (SSL)
V tomto příkladu tento konkrétní server pracuje na běžném HTTP. Tady žádné problémy.
$ curl http://192.168.101.1 <html><body><h1>It works!</h1></body></html>
Viz toto:15 praktických příkladů příkazů cURL pro Linux
Pokud však použijete SSLv3 a použijete volbu -3, vrátí chybovou zprávu „sslv3 alert handshake failure“.
$ curl -3 https://192.168.101.1 curl: (35) error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
Pokud použijete SSLv2 pomocí volby -2, vrátí chybovou zprávu „Neznámý protokol SSL“.
$ curl -2 https://192.168.101.1 curl: (35) Unknown SSL protocol error in connection to 192.168.101.1:443
V tomto případě na tomto konkrétním serveru podporuje pouze TLS. Použijte tedy volbu -1, jak je uvedeno níže.
$ 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
V tomto případě, protože používáme ip-adresu, která neodpovídá certifikátu SSL nainstalovanému na webovém serveru. Takže se nám zobrazuje výše uvedená chybová zpráva „SSL3_GET_SERVER_CERTIFICATE:ověření certifikátu se nezdařilo“.
Curl ve výchozím nastavení provádí ověření certifikátu SSL. Pokud používáte svazek oprávnění CA, pak výchozí název svazku je curl-ca-bundle.crt. Pomocí volby –cacert můžete zadat jiný balíček.
V našem případě však chceme použít protokol TLSv1, ale bez ověření certifikátu SSL. K tomu použijte volbu -k (nebo volbu –insecure), která neprovede ověření certifikátu SSL.
Následuje použití volby -k.
$ curl -k https://192.168.101.1 curl: (35) Unknown SSL protocol error in connection to 192.168.101.1:443
Pokud se chcete dozvědět více podrobností o chybě vyvolané příkazem CURL, použijte volbu -v. Jak vidíte níže. I když jsme neprošli volbou protokolu, z výstupu příkazu vidíme, že se k tomu pokouší použít SSLv2.
$ 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
Řešení z příkazového řádku
Viz toto:wget vs curl:Jak stahovat soubory pomocí wget a curl
Takže v našem případě, protože SSLv2 a SSLv3 jsou zakázány na straně serveru a z nějakého důvodu, pokud curl automaticky nenastaví správný protokol, následující funguje, když chceme použít pouze protokol TLSv1 s curl z příkazového řádku jako zobrazeno níže.
$ curl -k -1 https://192.168.101.1 <html><body><h1>It works!</h1></body></html>
Pokud chcete vidět podrobnosti o tom, co přesně to dělá, předejte volbu -v, jak je uvedeno níže.
$ curl -k -1 -v https://192.168.101.1
Výše uvedené lze také provést pomocí následujících alternativních možností
$ curl --insecure --tlsv1 --verbose https://192.168.101.1
Opět ve výše uvedeném příkazu:
- -1 (nebo) –tlsv1 pro TLSv1 (SSL)
- -k (nebo) –nezabezpečené pro povolení připojení k webům SSL bez certifikátů (H)
- -v (nebo) –verbose, aby byla operace hovornější (malé písmeno v)
Řešení z PHP
Z vašeho kódu PHP, pokud používáte funkce cURL a chcete nastavit možnosti protokolu, měli byste použít funkci curl_setopt nebo curl_setopt_array.
Pokud chcete nastavit pouze jednu možnost, použijte curl_setopt.
curl_setopt($c, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
Ve výše uvedeném:
- $c je proměnná curl, kterou jste získali z funkce curl_init(), když jste vytvořili nový zdroj cURL z vašeho programu PHP.
- CURLOPT_SSLVERSION je název možnosti curl.
- CURL_SSLVERSION_TLSv1 je hodnota curl pro odpovídající možnost v parametru č. 2
Místo „CURL_SSLVERSION_TLSv1“ můžete také použít číslo. V tomto příkladu je to ekvivalentní 1.
curl_setopt($c, CURLOPT_SSLVERSION, 1);
Následující jsou možné hodnoty CURLOPT_SSLVERSION, které můžete nastavit. Můžete použít buď popisnou konstantu, nebo odpovídající číslo, které je uvedeno níže.
- 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)
Pokud chcete nastavit více možností CURL, použijte curl_setopt_array, jak je znázorněno níže. Zde se kromě nastavení CURLOPT_SSLVERSION nastavuje také několik dalších možností zvlnění.
V tomto případě bude 2. parametrem pole, které bude obsahovat více možností CURL, jak je uvedeno níže.
curl_setopt_array($c, array ( CURLOPT_SSL_VERIFYHOST => 0, CURLOPT_SSL_VERIFYPEER => 0, CURLOPT_SSLVERSION => 1 ));