PHP CURL issue with long post data


#1

Hello all.
I can not do POST requests with PHP CURL with long post data (several kilobytes) from another server to the server with my web application behind of Cloudflare.
PHP-CURL returns following error:
If using HTTPS - SSL read: error:00000000:lib(0):func(0):reason(0), errno 104
If using HTTP - Recv failure: Connection reset by peer

But if I make POST query with short data (ex “name=John&phone=1234567890”) it works fine, and if I disable cloudflare proxy for my domain it also works fine even with long data.


#2

So apart from the length of the data you pass to CURLOPT_POSTFIELDS the code and execution workflow is identical?

Have you tried whitelisting the IP address in question? Even though, if it is the firewall it should return a challenge or error page and not simply bail out like this.


#3

That is example of my code:

<?php $postdata = http_build_query( array( 'name' => 'Test name', 'city' => 'Moscow', 'phone' => '1234567890', // ........................ And more and mode data ) ); $headers = Array( 'Authorization: Basic '.base64_encode('username:password'), 'Content-Type: application/x-www-form-urlencoded', 'Content-Length: '.strlen($postdata), ); // Send request with CURL $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://mydomain.com/api/deal_add'); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //curl_setopt($ch, CURLOPT_TIMEOUT, 10); $raw_response = curl_exec ($ch); echo $headers.$postdata.$raw_response.curl_error($ch); curl_close ($ch); $response = json_decode($raw_response); print_r($response); ?>

P.S. I have also tried to add IP of sending server (client) to white list of Cloudflare’s firewall, and tried to add page rule “https://mydomain.com/api/deal_add” with “security disabled” option. It does not help.


#4

Can you format that code?


#5
<?php	
	$postdata = http_build_query(
		array(
			'name' => 'Test name',
			'city' => 'Moscow',
			'phone' => '1234567890',
			// ........................ And more and mode data
		)
	);
	
	$headers = Array(
		'Authorization: Basic '.base64_encode('username:password'),
		'Content-Type: application/x-www-form-urlencoded',
		'Content-Length: '.strlen($postdata),
	);
		
		
	// Send request with CURL
	$ch = curl_init();

	curl_setopt($ch, CURLOPT_URL, 'https://mydomain.com/api/deal_add');
	curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	//curl_setopt($ch, CURLOPT_TIMEOUT, 10);

	$raw_response = curl_exec ($ch);
	
	echo $headers.$postdata.$raw_response.curl_error($ch);
	
	curl_close ($ch);	
	
	$response = json_decode($raw_response);
	
	print_r($response);
?>

#6

From a quick glance it seems the code should be alright. Could you try if can reproduce the same error from a browser (there are extensions allowing you to post data) or directly from the command line via telnet/netcat (piped through openssl if you want to test HTTPS)?


#7

From command line curl (Ubuntu server):
$ curl -u user:password -d “name=My+name+…” -X POST https://domain.com/api/deal_add
curl: (56) GnuTLS recv error (-54): Error in the pull function.


#8

But the moment you shorten your POST data it works?


#9

An example with short data:

$ curl -u user:password -d "name=My+name" -X POST https://domain.com/api/deal_add
{
    "status": "success",
    "status_code": "200",
    "status_text": "OK",
    "status_description": "Order was added sussessfully",
    "data": {
        "name": "My name",
        "event": "order_add_api",
        "date": "11.09.2018",
        "order_id": "1047"
    }
}

#10

Which works, I presume?!

And you are absolutely sure your domain is behind Cloudflare? If that is the case, I’d open a support ticket.


#11

Yes receiving server is behind of Cloudflare. (Orange cloud in dns setting of the domain)


#12

And if I disable Cloudflare proxy (Gray cloud in dns setting of the domain) POST query works fine even with long data!


#13

As I mentioned earlier I’d open a support ticket.


#14

Disabling cloudflare solves the problem but it is not good solution for security.


#15

How to open support ticket?


#16

Hi @s112, to reach support, login in to Cloudflare and from the upper right corner, select Support -> Help Center or email support AT cloudflare DOT com from the address you used to create your Cloudflare account.


#17

I have just opened the ticket, i am waiting for responce…

And one more test:
If I do POST queries from the browser, using HTML form - it works fine in anyway, even with very large text in the input field


#18

Additional testing shows that POST queries with large data works fine from other DigitalOcean’s host to the target host.
But only queries with large data from RuCenter host to the target host do not work.

I turned to technical support RuCenter and that’s what they answered:

The IP-addresses, in which the domain name mydomain.com is allowed, are in the black lists of Roskomnadzor (Cloudflare’s ip addresses), there may be restrictions on the part of channel Internet providers to access these addresses in different ways (one way or another is determined based on the request itself). Alas, to guarantee a successful connection with such IP-addresses is impossible from the territory of Russia in principle.

So I think to try using curl+socks5 proxy for now. (PHP-curl supports socks5 proxy option)


#19

Any advice?


#20

I solved the problem quite easy.

I found the option CURLOPT_RESOLVE, that allows to set an IP-address directly without DNS query. And I set the IP address of DigitalOcean’s host and this works!

<?php 
curl_setopt($ch, CURLOPT_RESOLVE, array('domain.com:443:10.20.30.40')); 
?>

Close topic!