I have to send push notification to iOS devices. My connection has to be enabled through a proxy. I tried everything but without success. I have an error 110 Connection Timed Out. It's working with cURL if I just try to connect to Apple push's address. I don't know where the problem is. Proxy config ? PHP stream_context wrong implementation ?
Here's my code :
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'certificate.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', 'my_passphrase');
stream_context_set_option($ctx, 'ssl', 'verify_peer', false);
stream_context_set_option($ctx, 'http', 'proxy', 'tcp://my-proxy.net:8080');
stream_context_set_option($ctx, 'http', 'request_fulluri', true);
$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err,$errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
var_dump($fp);
var_dump($err);
var_dump($errstr);
exit;
Do you have an idea ?
EDIT:
Can it be directly linked to Squid ? I just figured out the proxy is running with Squid.
I also try with fopen() function instead of stream_socket_client() but it seems it doesn't allow ssl protocol.
Here's my var_dump outputs : bool(false) int(110) string(20) "Connection timed out"
I also have this warning : Warning: stream_socket_client(): unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Connection timed out) in /share/www/website/test.php on line 22
It could simply be your proxy does not allow port 2195 to be opened.
iPhone Push Notification Unable to Connect to the SSL Server
I guess you either:
Need to talk to the people who run the proxy to see if port 2195 is open or not.
or
Setup a test server listening on port 2195 and then try to do a test connection to it through the proxy. That should allow you to test if it is the proxy that is blocking the connection requests.
or
Test whether Curl can open the connection using a proxy.
Which is done by setting the options:
// sets the proxy to go through
curl_setopt($ch, CURLOPT_PROXY, $proxy);
// sets to use a tunnel proxy which most http proxies are
curl_setopt($ch, CURLOPT_HTTPTUNNELPROXY, $proxy);
Full testing code here.
create the SSL context
open a tcp socket to the proxy
send request to the proxy to connect to APNs
once connexion is accepted enable SSL
Have a look at my reply in this post: Send Push Notification to APNS through proxy
Related
I have hosted my PHP code on google cloud.
I want to send push notifications to ios app. I have enabled port 2195 and 2196.
While sending the push notification I got the following error :
Warning: stream_socket_client(): SSL: Connection reset by peer
Warning: stream_socket_client(): Failed to enable crypto
Warning: stream_socket_client(): unable to connect to
ssl://gateway.push.apple.com:2195 (Unknown error)
I am not much familiar with Google Cloud. What should I do to make it working?
Here is code:
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', PEM_FILE_PATH . 'apns-dev.pem');
$fp = stream_socket_client("ssl://gateway.push.apple.com:2195", $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
if (!$fp) {
$data['msgs'] = "Failed to connect $err $errstr \n";
} else {
$payload = json_encode($body);
$msg = chr(0) . pack("n", 32) . pack("H*", str_replace(" ", "", $deviceToken)) . pack("n", strlen($payload)) . $payload;
$result = fwrite($fp, $msg);
if (!$result) {
$data['msgs'] = 'Message not delivered'; //. PHP_EOL;
} else {
$data['msgs'] = 'Success'; //. PHP_EOL;
}
fclose($fp);
}
return $data;
The main problem when we are trying to send data to the APNS (Apple Push Notification Service) servers is the SSL certificates.
APNS uses this technology in order to serve more secure connection to its users.
As it is said at APNS documentation: "Each certificate is limited to a single app and is also limited to one of two development environments, each with its own assigned hostname". So you can use two environments
Development (testing environment): ssl://gateway.sandbox.push.apple.com:2195
Production (once the app is launched): ssl://gateway.push.apple.com:2195
If you want to test if you can connect to APNS server, just try the following command:
$ telnet gateway.sandbox.push.apple.com 2195
Trying 17.172.232.226...
Connected to gateway.sandbox.push-apple.com.akadns.net.
Escape character is '^]'.
If you get an error then make sure your firewall allows outgoing connections on port 2195.
Then you can test if your SSL certificate and private key are working and it can be set up a secure connection:
$ openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert YourDevCert.pem -key YourPrivateKey.pem
Enter pass phrase for YourPrivateKey.pem: ******
If this works it means that your certificates are correctly set up (you should see a whole bunch of output, which is openssl letting you know what is going on under the hood).
Once knowing all of this information, I see that you have one mistake in your code and also you should check something else:
Check if you have a good connection with APNS server.
Check that your $payload variable is a json string.
Check that you have a correct $deviceToken.
Check that you are using the right certificate with the right environtment. In this case, you are setting a apns-dev.pem certificate and you are sending it to the production environment (I interpret that your production certificate is apns-prod.pem so check it).
Check that your PHP file can find your certificate.
One of your problems, you haven't set any password for your private key. You should add the following line once you have added your certificate:
stream_context_set_option($ctx, "ssl", "passphrase", "your_private_key");
If you have some troubles or doubts, I followed this tutorial to send my first APNS Push Notifications.
I'm having issues reopening a TCP socket connection after its remotely closed. Specifically this is for Apple Push Notification service - when Apple encounters a device token from you that pairs with a device that deleted your application they close the secure TCP socket to their push gateway. I need to immediately reopen this connection (or start a new one) when this issue occurs so I can continue sending notification to other users who still do have the app installed. I have some code using which I try to sort this out but it's freezing my entire Apache server and I have to restart manually to get things running again and I have no idea why. Below is the code with which I attempt to reopen a socket with Apple:
if($error_response == "InvalidToken"){
$results .= "\ntried to restart";
fclose($fp);
usleep(20000);
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck_real.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', '****');
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
}
Problem:
I cannot access APNS server. I get a 110 Connection Time Out error.
My situation:
I've contacted my host (hostmonster). They said my port 2195,2196 are already open.
My certificate and passphrase is no problem, for I've tested it from my local Mac.
I use a very simple PHP to test. Here's my code:
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'apn.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', 'aaa');
$fp = stream_socket_client("ssl://gateway.sandbox.push.apple.com:2195", $err,
$errstr,60,STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT,$ctx);
if ($fp)
echo ('aa');
else
echo ($err.$errstr);
I had the same exact problem, but with Bluehost. In my case, it turned out the Bluehost firewall was not properly open. The first line chat support from Bluehost said the ports 2195 & 2196 are open, and the problem was not with them. To demonstrate the problem was on their side, I asked them to run the following telnet command from the Bluehost server:
telnet gateway.push.apple.com 2195
Trying 17.149.36.246...
Trying 17.149.35.166...
Trying 17.149.35.170...
Trying 17.149.35.177...
... Connection timed out
The output should be:
telnet gateway.push.apple.com 2195
Trying 17.149.36.230...
Connected to gateway.push.apple.com.
Escape character is '^]'.
Then i submitted a support ticket to Bluehost with this information. They resolved the issue in 6 hours by properly opening the firewall.
I am trying to upgrade my PHP WebSocket library to SSL, using the wss://-protocol on the client-side. However, I find myself at a loss trying to figure out a) how to set up the server socket, and b) how to decode the incoming messages. Here is my current attempt at the former:
$context = stream_context_create();
// local_cert must be in PEM format
stream_context_set_option($context, 'ssl', 'local_cert', $pemFilePath);
// Pass Phrase (password) of private key
stream_context_set_option($context, 'ssl', 'passphrase', $pemPassPhrase);
stream_context_set_option($context, 'ssl', 'allow_self_signed', true);
stream_context_set_option($context, 'ssl', 'verify_peer', false);
$serverSocket = stream_socket_server('ssl://'.$host.':'.$port, $errNo, $errStr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context);
However, when using SSL as the server protocol, the client does not seem to be sending any messages, and when using tcp, I get weird, encrypted data, although it was my guess that it would be magically decrypted due to my providing the options to the stream context.
What am I doing wrong?
I ran into the same problem with our implementation, and found a good workaround. Put your websocket server on any firewalled port, and tunnel connections from a secure port port. You can use stunnel with a configuration like this:
[websockets]
accept = 8443
connect = 8080
This way, stunnel does all the security, and your websocket server does all the websockets. Win!
I am using the certificate, and the private key
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $certfile);
stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);
$fp = stream_socket_client('ssl://gateway.xyz.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
Its running in my local XAMPP Server, but its not working in the external server:
Warning: stream_socket_client() [function.stream-socket-client]: unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Connection timed out) in /home/biranchi/public_html/push.php on line 42
Failed to connect 110
What is the error? Do i need to change some setting in the server?
I had fixed the issue by opening the port 2195 on the production server. You can verify by following command $telnet gateway.push.apple.com 2195
-bash-3.2# telnet gateway.push.apple.com 2195
Trying 17.149.38.141...
Connected to gateway.push.apple.com (17.149.38.141).
Escape character is '^]'.
Connection closed by foreign host.
Check your personal firewall settings and make sure you're not blocking this out. Try disabling the firewall.
Also, some APIs like requests to come from an actual domain rather than a desktop. I don't have reason to believe Apple works this way, but that's something to check also.
Also make sure and ping gateway.sandbox.push.apple.com and make sure you have a good connection.
You have to set your firewall to allow all the 17.0.0.0/8 block (it all belongs to Apple!). Check THIS ANSWER
And according to Apple:
The APNs servers use load balancing, so your devices won't always connect to the same public IP address for notifications. It's best to allow access to these ports on the entire 17.0.0.0/8 address block, which is assigned to Apple.
If you are using CSF firewall (like me), I'd recommend to add this line to csf.allow file:
tcp|out|d=2195|d=17.0.0.0/8
Then restart CSF. Using the above instead of just "17.0.0.0/8" will allow only outbond connections to Apple and specifically to port 2195. NSA won't like it but this is much more precise and safe! ;)