2015-09-10 143 views
4

我一直試圖用明確的TLS/SSL服務器推送到遠程FTP,並且連接保持超時。它是連接的,但我不知道它在哪裏停止,但我認爲這對於FTP/TLS/SSL控制通道是有用的。任何幫助將不勝感激。帶卷積TLS/SSL的PHP​​ curl FTP

通過FileZilla我可以連接沒有問題,但不通過捲曲。我可能錯過了一些東西,並希望這裏有人會知道使用curl重新創建會話的最佳方式。以下是FileZilla的調試輸出以及我在PHP/curl中處理的示例代碼。這裏是PHP代碼,下面是一個成功的FileZilla會話的副本。

這裏是版本,但我試過它在不同的系統上有相同的結果。

Curl: v7.43.0 

└─(08:04:00 on master ✹)──> php -v           ──(Thu,Sep10)─┘ 
PHP 5.5.27 (cli) (built: Jul 14 2015 17:04:01) 
Copyright (c) 1997-2015 The PHP Group 
Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies 
    with Xdebug v2.3.3, Copyright (c) 2002-2015, by Derick Rethans 

這裏是實際的代碼。

<?php 

$server_data = array(
    'transfer_id' => 123456789, 
    'post_url' => "ftps://ftps.widgetsltd.com", 
    'port' => 21, 
    'username' => 'widgetsftp', 
    'password' => 'password', 
); 

$filename = sprintf("%s-%s-%s.csv", 
        $server_data['transfer_id'], 
        microtime(TRUE), 
        rand(1000, 9999)); 

$temp_filename = sprintf("/tmp/%s", $filename); 
$ftp_data = "This is a test"; 

$fp = fopen($temp_filename, 'w'); 
fprintf($fp, "%s", $ftp_data); 
fclose($fp); 

$fp = fopen($temp_filename, 'r'); 

$ch = curl_init(); 

curl_setopt($ch, CURLOPT_VERBOSE, TRUE);  
curl_setopt($ch, CURLOPT_URL, sprintf("%s/%s", $server_data['post_url'], $filename)); 
curl_setopt($ch, CURLOPT_PORT, 21);  
curl_setopt($ch, CURLOPT_USERPWD, sprintf("%s:%s", $server_data['username'], $server_data['password'])); 

curl_setopt($ch, CURLOPT_UPLOAD, TRUE); 
curl_setopt($ch, CURLOPT_INFILE, $fp); 
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($temp_filename)); 

curl_setopt($ch, CURLOPT_USE_SSL, TRUE); 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); 
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_0); 
curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'AES-128-CBC'); 

curl_setopt($ch, CURLOPT_FTP_SSL, CURLOPT_FTPSSLAUTH); 
curl_setopt($ch, CURLOPT_FTPSSLAUTH, CURLFTPAUTH_TLS); 
curl_setopt($ch, CURLOPT_TIMEOUT, 5); 

print_r(array('curl_exec' => curl_exec($ch))); 
print_r(array(
      'curl_errno' => curl_errno($ch), 
      'curl_error' => curl_error($ch), 
     )); 

這是FileZilla會話。

Status:  Resolving address of ftps.widgetsltd.com 
Status:  Connecting to 123.123.123.123:21... 
Status:  Connection established, waiting for welcome message... 
Trace:   CFtpControlSocket::OnReceive() 
Response: 220-Microsoft FTP Service 
Response: 220 Widgets, LTD FTP server 
Trace:   CFtpControlSocket::SendNextCommand() 
Command: AUTH TLS 
Trace:   CFtpControlSocket::OnReceive() 
Response: 234 AUTH command ok. Expecting TLS Negotiation. 
Status:  Initializing TLS... 
Trace:   CTlsSocket::Handshake() 
Trace:   CTlsSocket::ContinueHandshake() 
Trace:   CTlsSocket::OnSend() 
Trace:   CTlsSocket::OnRead() 
Trace:   CTlsSocket::ContinueHandshake() 
Trace:   CTlsSocket::OnRead() 
Trace:   CTlsSocket::ContinueHandshake() 
Trace:   TLS Handshake successful 
Trace:   Protocol: TLS1.0, Key exchange: RSA, Cipher: AES-128-CBC, MAC: SHA1 
Status:  Verifying certificate... 
Status:  TLS connection established. 
Trace:   CFtpControlSocket::SendNextCommand() 
Command: USER s-rokfri 
Trace:   CTlsSocket::OnRead() 
Trace:   CFtpControlSocket::OnReceive() 
Response: 331 Password required for s-rokfri. 
Trace:   CFtpControlSocket::SendNextCommand() 
Command: PASS ******** 
Trace:   CTlsSocket::OnRead() 
Trace:   CFtpControlSocket::OnReceive() 
Response: 230-This service and information contained therein belong to Widgets, LTD. 
Response: 230 User logged in. 
Trace:   CFtpControlSocket::SendNextCommand() 
Command: OPTS UTF8 ON 
Trace:   CTlsSocket::OnRead() 
Trace:   CFtpControlSocket::OnReceive() 
Response: 200 OPTS UTF8 command successful - UTF8 encoding now ON. 
Trace:   CFtpControlSocket::SendNextCommand() 
Command: PBSZ 0 
Trace:   CTlsSocket::OnRead() 
Trace:   CFtpControlSocket::OnReceive() 
Response: 200 PBSZ command successful. 
Trace:   CFtpControlSocket::SendNextCommand() 
Command: PROT P 
Trace:   CTlsSocket::OnRead() 
Trace:   CFtpControlSocket::OnReceive() 
Response: 200 PROT command successful. 
Status:  Connected 
Trace:   CFtpControlSocket::ResetOperation(0) 
Trace:   CControlSocket::ResetOperation(0) 
Trace:   CFileZillaEnginePrivate::ResetOperation(0) 
Trace:   Measured latency of 141 ms 
Status:  Retrieving directory listing... 
Trace:   CFtpControlSocket::SendNextCommand() 
Trace:   CFtpControlSocket::ChangeDirSend() 
Command: PWD 
Trace:   CTlsSocket::OnRead() 
Trace:   CFtpControlSocket::OnReceive() 
Response: 257 "/" is current directory. 
Trace:   CFtpControlSocket::ResetOperation(0) 
Trace:   CControlSocket::ResetOperation(0) 
Trace:   CFtpControlSocket::ParseSubcommandResult(0) 
Trace:   CFtpControlSocket::ListSubcommandResult() 
Trace:   state = 1 
Trace:   CFtpControlSocket::ResetOperation(0) 
Trace:   CControlSocket::ResetOperation(0) 
Status:  Directory listing of "/" successful 
Trace:   CFileZillaEnginePrivate::ResetOperation(0) 

這裏是捲曲輸出。

* Trying 123.123.123.123... 
* Connected to ftps.widgetsltd.com (123.123.123.123) port 21 (#0) 
* SSL connection timeout 
* Closing connection 0 
Array 
(
    [curl_exec] => 
) 
Array 
(
    [curl_errno] => 28 
    [curl_error] => SSL connection timeout 
) 
+0

確實[這太問題(HTTP://計算器。com/questions/9906555/ftp-upload-file-to-distant-server-with-curl-and-php-uploads-a-blank-file)help? –

+1

不是真的,讓這更復雜的事情是顯式ssl。但是,謝謝。 – jbrahy

+0

想到我會試試:)希望我能有更多的幫助... –

回答

4

捲曲明顯嘗試使用隱式FTP(因爲它初始化TLS/SSL會話的任何FTP命令與服務器交換甚至之前)。

這是因爲您已指定ftps://前綴,該前綴用於隱式TLS。它有特殊的前綴,因爲隱含的TLS使用特殊的端口(990)。但你用CURLOPT_PORT覆蓋缺省值。

雖然顯式TLS使用標準FTP端口(21),所以它使用標準的ftp://前綴。要啓用明確的TLS,請使用CURLOPT_USE_SSL(您正在做的事情,只是通過錯誤的值,選項類型是枚舉,而不是布爾值)。

因此,代碼應該是:

$server_data = array(
    ... 
    'post_url' => "ftp://ftps.widgetsltd.com", // ftp:// URL 
    ... 
); 

curl_setopt($ch, CURLOPT_URL, sprintf("%s/%s", $server_data['post_url'], $filename)); 
curl_setopt($ch, CURLOPT_USE_SSL, CURLUSESSL_ALL); // Enable TLS/SSL 

注意,CURLOPT_FTP_SSL過時,而且是一個別名爲CURLOPT_USE_SSL。所以,設置兩者都沒有意義。

2

嘗試從ftps中刪除s://我設置了一個測試服務器,並且看到了與ftps vs ftp相同的錯誤。

'post_url' => "ftp://ftps.widgetsltd.com", 
+1

這是正確的,但馬丁有一個更好,更完整的答案。謝謝! – jbrahy

1

當您試圖讓我的FTPS連接使用PHP和cURL時,我收到了同樣的錯誤消息。我得到的錯誤是:curl_errno 28 - SSL連接超時。

我終於得到它使用下面的代碼工作。我意識到這個問題已經得到解答,但我想提供我的工作代碼以幫助其他人。

下面是如何使用PHP和捲曲的文件上傳到服務器FTPS:

<?php 
// !!! MAKE SURE SERVER ADDRESS STARTS WITH ftp://... 
$ftp_server="ftp://ftps.example.com"; 
$ftp_user_name="USERNAME"; 
$ftp_user_pass="PASSWORD"; 

$localFileName = "test.txt"; 
$remoteFileName = "/Export/test.txt"; 

$fp = fopen($localFileName, 'r'); 
$stderr = fopen("curl.txt", "w"); //for error msg logging 

$ch = curl_init(); 

curl_setopt($ch, CURLOPT_URL, $ftp_server.$remoteFileName); 
curl_setopt($ch, CURLOPT_PORT, 21); 
curl_setopt($ch, CURLOPT_USERPWD, "$ftp_user_name:$ftp_user_pass"); 
curl_setopt($ch, CURLOPT_UPLOAD, 1); 
curl_setopt($ch, CURLOPT_INFILE, $fp); 
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localFileName)); 
//SSL stuff 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //use for development only; unsecure 
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); //use for development only; unsecure 
curl_setopt($ch, CURLOPT_FTP_SSL, CURLOPT_FTPSSLAUTH); 
curl_setopt($ch, CURLOPT_FTPSSLAUTH, CURLFTPAUTH_TLS); 
//curl_setopt($ch, CURLOPT_SSLVERSION, 3); 
//end SSL 
curl_setopt($ch, CURLOPT_VERBOSE, TRUE); 
curl_setopt($ch, CURLOPT_STDERR, $stderr); 
curl_setopt($ch, CURLOPT_TIMEOUT, 10); 

curl_exec ($ch); 

$error_no = curl_errno($ch); 
$error_msg = curl_error($ch); 

curl_close ($ch); 
fclose($fp); 
fclose($stderr); 

if ($error_no == 0) 
{ 
    $status = "Success"; 
} 
else 
{ 
    $status = "Failed"; 

} 

echo "FTP RESULT: <BR/>error_no: ".$error_no . "<br/>msg: " . $error_msg; 
?> 
+1

不建議任何人在不解釋安全後果的情況下使用'CURLOPT_SSL_VERIFYPEER = 0'和'CURLOPT_SSL_VERIFYHOST = 0'。 –