TLS Session Resumption in php - php

I'm writing a multithreaded php client that makes a https requests to an apache reversed proxy and measures some statistics. I'm writing a bachelor thesis about improving the performance with TLS Session Resumption. Now I need to do a proof of concept that proves/disproves this. At the moment I have this code:
$this->synchronized(function($this){
$this->before = microtime(true);
}, $this);
$url = 'https://192.168.0.171/';
# Some dummy data
$data = array('name' => 'Nicolas', 'bank account' => '123462343');
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
),
"ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
"ciphers" => "HIGH:!SSLv2:!SSLv3"
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$this->synchronized(function($this){
$this->after = microtime(true);
}, $this);
$this->counter_group->write($this->before, $this->after, $result);
This code works to do a full handshake, but I can't seem to figure out how to do an resumed handshake in php?
Any help would be greatly appreciated!

You can try PHP curl and use CURL_LOCK_DATA_SSL_SESSION
from PHP documentation http://php.net/manual/en/function.curl-share-setopt.php
CURL_LOCK_DATA_SSL_SESSION Shares SSL session IDs, reducing the time
spent on the SSL handshake when reconnecting to the same server. Note
that SSL session IDs are reused within the same handle by default
As you can read from the description above, the session id is reused by the same handle. But if you want to share between handles you can use curl_share_init for example
$sh = curl_share_init();
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
then you can reuse $sh between different requests
$ch1 = curl_init('https://192.168.0.171');
curl_setopt($ch1, CURLOPT_SHARE, $sh);
curl_setopt($ch1, CURLOPT_SSLVERSION, 6); // TLSV1.2
curl_setopt($ch1, CURLOPT_SSL_CIPHER_LIST, 'TLSv1');
curl_setopt($ch1, CURLOPT_POST, 1);
curl_setopt($ch1, CURLOPT_POSTFIELDS,
http_build_query( array('name' => 'Nicolas', 'bank account' => '123462343') ));
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch1);
and then reuse ( resumed handshake )
$ch2 = curl_init('https://192.168.0.171');
curl_setopt($ch2, CURLOPT_SHARE, $sh);
curl_setopt($ch2, CURLOPT_SSLVERSION, 6); // TLSV1.2
curl_setopt($ch2, CURLOPT_SSL_CIPHER_LIST, 'TLSv1');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
// ( ... )
curl_exec($ch2);
and close connections
curl_close($ch1);
curl_close($ch2);
But you also need to play with CURLOPT_SSLVERSION and CURLOPT_SSL_CIPHER_LIST . Also, I think you should switch to a different language as PHP has its own quirks, and if you prove or disproves thesis, it's better to use something closer to bare metal so you are sure the extra layer (PHP) doesn't break your benchmarks. I did measure the performance of both requests and it's a bit counter-intuitive but the second one is almost twice slower.

Related

unable to send out voice broadcast with callfire REST API

I'm trying to send out an outbound call with the callfire REST API and am having some difficulty doing so. Here's my code (adapted from https://developers.callfire.com/docs.html#createVoiceBroadcast):
<?php
$username = '...';
$password = '...';
$data = array(
'name' => 'Automation Test',
'fromNumber' => '...',
'recipients' => array(
array('phoneNumber' => '...')
),
'answeringMachineConfig' => 'AM_AND_ALIVE',
'liveSoundText' => 'hello, world!',
'machineSoundText' => 'hello, world!'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'https://api.callfire.com/v2/campaigns/voice-broadcasts');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$result = json_decode(curl_exec($ch));
print_r($result);
The problem is in the response. It's as follows:
stdClass Object
(
[httpStatusCode] => 415
[internalCode] => 0
[message] => Exception in API
)
The 415 status code is for "Unsupported Media Type" per https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error but since I'm not uploading any media that error doesn't really make a lot of sense.
Maybe my value for answeringMachineConfig is invalid. idk what AM_AND_LIVE is supposed to mean but it's in the example so I'm using it. If there's only a small number of possible values the documentation should say so..
You need to set content type to 'application/json'.
Old I know, but just ran across it. Perhaps:
'answeringMachineConfig' => 'AM_AND_ALIVE',
should be:
'answeringMachineConfig' => 'AM_AND_LIVE',
You wrote ALIVE instead of LIVE

Sending an "identify" request to "threads.io" using php

What I want to do is to send an "identify" request to "threads.io" using php, however, I didn't find a way to do it (I couldn't even find a "threads.io" documentation for php). Does anyone know the proper way to do it? (syntax, etc.)
You'll have to use curl. Here's a basic script that will do it.
// You must use UTC timezone
date_default_timezone_set('UTC');
$project_key = 'your project key';
$data = array(
'userId' => '12',
'traits' => array(
'name' => 'Jeff',
'email' => 'jeff#example.com',
),
'timestamp' => date('Y-m-d\TH:i:s') . '.000Z',
);
$data = json_encode($data);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "https://input.threads.io/v1/identify");
curl_setopt($curl, CURLOPT_USERPWD, "$project_key:''");
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_exec($curl);
curl_close($curl);
A good starting place to understanding curl is: http://www.hackingwithphp.com/15/10/2/your-first-curl-scripts
And of course php.net: http://php.net/curl

How to push messages from my server in PHP to Android device?

I want to push messages from my cloud server to Android emulator or Android device with phone number.
Is it possible? Do I need to use any gateway?
Check out this:
https://developer.android.com/google/gcm/index.html
https://developer.android.com/google/gcm/http.html
Basically you would have to make CURL call to
https://android.googleapis.com/gcm/send
Something like this:
$data = array(
'collapse_key' => $msgType,
'data' => array('message' => $news_text,
'title' => $news_title,
'url' => $messageUrl,
'message_id' => $news_id,
'notification_type' => $channel_name),
'registration_ids' => $devices
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://android.googleapis.com/gcm/send");
if ($headers)
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response_json = curl_exec($ch);
$response = json_decode($response_json);
print_r($response_json);
GCM / FCM is the goto solution. If every app which uses push notifications would implement some sort of listening or polling service the battery would drain way to fast. Thats why google and also Apple provide 1 single service for the whole Androidsystem and its apps to use.
This means that it isnt impossible todo, i think there are some third party push notifications-services.
I just dont think its a clever thing todo. Chances are that google build a reliable, fast and efficient service.

PHP - https stream through http proxy

I'm trying to get the content of a stream over HTTPS, but I have to go over an HTTP proxy.
I'd like not to use cURL but rather use fopen with a context argument.
The thing is, I can't make it work over HTTPS (HTTP is working fine though).
This DOES NOT work :
$stream = stream_context_create(Array("http" => Array("method" => "GET",
"timeout" => 20,
"proxy" => "tcp://my-proxy:3128",
'request_fulluri' => True
)));
echo file_get_contents('https://my-stream', false, $context);
This DOES work (cURL) :
$url = 'https://my-stream';
$proxy = 'my-proxy:3128';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
$curl_scraped_page = curl_exec($ch);
curl_close($ch);
echo $curl_scraped_page;
Does somebody know what is wrong with the first piece of code ? if it works with cURL there has to be a way to make it work with a context.
I tried to change the context options to a bunch of different values woth no luck.
Any help would be greatly appreciated !
Thanks.
You did not specifiy the exact error message, try adding ignore_errors => true. But if you are getting a 400 Bad Request from Apache, the problem you are probably hitting, is a Server Name Indication & host header mismatch. There is also a PHP bug related to this: https://bugs.php.net/bug.php?id=63519
Try the following fix until this bug is resolved:
$stream = stream_context_create(array(
'http' => array(
'timeout' => 20,
'proxy' => 'tcp://my-proxy:3128',
'request_fulluri' => true
),
'ssl' => array(
'SNI_enabled' => false // Disable SNI for https over http proxies
)
));
echo file_get_contents('https://my-stream', false, $context);

Php SoapClient stream_context option

I want to use a third party's web service. To use the web service I need to connect with HTTPS. My problem is that for the development process I have a test api with an invalid certificate. I would like to set SoapClient no to verify the server's certificate. Here is the way I tried:
$opts = array(
'ssl' => array(
'verify_peer' => false
),
'https' => array(
'curl_verify_ssl_peer' => false,
'curl_verify_ssl_host' => false
)
);
$streamContext = stream_context_create($opts);
$client = new SoapClient("https://urlToSoapWs",
array(
'login' => 'user',
'password' => 'pwd',
'authentication' => SOAP_AUTHENTICATION_BASIC,
'local_cert' => file_get_contents('C:/somelocation/1.pem'),
'passphrase' => 'passphrase',
'stream_context' => $streamContext
));
I also tried with CURL and worked! But I want to use SoapClient. You can find the code with CURL below:
// create a new cURL resource
$ch = curl_init("https://urlToSoapWs");
// setting the request type to POST:
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
// setting the authorization method to BASIC:
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
// supplying your credentials:
curl_setopt($ch, CURLOPT_USERPWD, "user:pwd");
$body = "<SOAP-ENV:Envelope>somexmlhere</SOAP-ENV:Envelope>";
// filling the request body with your SOAP message:
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
// configuring cURL not to verify the server certificate:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSLCERT, "pathToTheCertificatePemFile");
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, "pwd");
//curl_setopt($ch, CURLOPT_SSLCERTTYPE, "PEM");
curl_setopt($ch, CURLOPT_SSLKEY, "pathTotheKeyFile");
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, "pwd");
// telling cURL to return the HTTP response body as operation result
// value when calling curl_exec:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// calling cURL and saving the SOAP response message in a variable which
// contains a string like "<SOAP-ENV:Envelope ...>...</SOAP-ENV:Envelope>":
$result = curl_exec($ch);
// closing cURL:
curl_close($ch);
If you have found the bug in the code that I provided using the SoapClient please post it.
Thanks.
Maybe not the invalid Certificate is a Problem, more the SSLv2/3 Handshake; can you try manually specifing a Cipher like this:
$stream_opts = array(
// 'ssl'=>array('ciphers'=>"3DES" // also working
// further ciphers on http://www.openssl.org/docs/apps/ciphers.html
'ssl'=>array('ciphers'=>"SHA1"
)
);
$myStreamContext = stream_context_create($stream_opts);
$soapOptions['stream_context'] = $stream_opts;
$soapClient = new SoapAuthClient("https://...", $soapOptions);
Good luck!
It looks like you have hit this authentication plus SSL bug in SoapClient. You can either recompile php with the patch included in that link, or wait until they integrate it in the official build.

Categories