Only with PHP: unable to connect to APNS gateway.push.apple.com:2195

This is late night. I just spent 10 hours searching and experimenting on google / stackoverflow. And it seems that I hate Apple Push Notifications. I am completely disappointed and would appreciate any help.

Thanks.

Problem:

The PHP code for sending Apple Push Notifications, which worked successfully two weeks ago, stops working and causes the following errors:

PHP Warning: stream_socket_client(): Failed to enable crypto in /home/... PHP Warning: stream_socket_client(): unable to connect to ssl://gateway.push.apple.com:2195 (Unknown error) in /home/... 

He stopped to work on two separate servers that use separate scripts to send APNs.

Environment:

Servers: CentOS 6.5 with PHP 5.4.32 and Ubuntu 14.04.3 with PHP 5.5.9

APN: In Production Mode

Certificates: verified using 700 + push notifications.

One of the servers uses https://github.com/immobiliare/ApnsPHP , the other uses https://github.com/antongorodezkiy/wp-apn , I tested a simple file on localhost without using third-party code.

Study:

For all cases below, I used the same active device token and the same PEM certificate of production.

Php

However, even this simple code does not work on both servers and localhost and returns the same error as above:

 $ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'local_cert', '/absolute/path/to/apn_prod.pem'); // Open a connection to the APNS server $fp = stream_socket_client( 'ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); 

I also tried playing with stream_context_set_option() parameters, including entrust_2048_ca.cer , etc., and even some of the options from this article . Although the provided code worked without any changes until August 2015.

Openssl

The connection is made using openssl ( link ):

 openssl s_client -connect gateway.push.apple.com:2195 -cert /absolute/path/to/apn_prod.pem -debug -showcerts -CAfile /absolute/path/to/server-ca-cert.pem 

And received with CONNECTED(00000003) and Verify return code: 0 ( ok ) .

telnet

The connection works with telnet:

 -sh-4.1$ telnet gateway.push.apple.com 2195 Trying 17.172.233.150... Connected to gateway.push.apple.com. 

pecl apn

He did not send a push notification . I just tried using the sample code , but got an Invalid token error. The token is active and the same token that I used everywhere, as well as for Houston and Ruby.

houston

He worked with Houston.

 apn push "0346a53f...231d9d6abe11" -c /absolute/path/to/apn_prod.pem -m "Hello from the command line!" -e "production" 

ruby

I'm not a Ruby programmer (at least), but after success in Houston, I found and adapted Ruby code without dependency on Houston.

And he worked :

 #!/usr/bin/env ruby require 'openssl' require 'socket' require 'json' token = "0346a53f...231d9d6abe11" cert = File.read("/absolute/path/to/apn_prod.pem") ctx = OpenSSL::SSL::SSLContext.new ctx.key = OpenSSL::PKey::RSA.new(cert, '') #set passphrase here, if any ctx.cert = OpenSSL::X509::Certificate.new(cert) sock = TCPSocket.new('gateway.push.apple.com', 2195) #development gateway ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) ssl.connect payload = {"aps" => {"alert" => "Oh hai!", "badge" => 1, "sound" => 'default'}} json = payload.to_json() token = [token.delete(' ')].pack('H*') #something like 2c0cad 01d1465 346786a9 3a07613f2 b03f0b94b6 8dde3993 d9017224 ad068d36 apnsMessage = "\0\0 #{token}\0#{json.length.chr}#{json}" ssl.write(apnsMessage) ssl.close sock.close puts "End" 

Questions:

  • What is wrong with PHP? Is there any kind of error related to this problem? (I did not find an error report, though)
  • Any ideas how to solve this problem?
  • Any ideas what could be the difference in PHP and Ruby cases (I suppose Python or Perl can work fine too)? I even tried to read PHP sources, but to no avail to understand how stream_socket_client() implemented.

Please, help.

+6
source share
2 answers

I found the problem and fixed it.

Problem was in the .pem certificate. Somehow, in both files there were two certificates for both .pem files. The same .pem file with two certificates has been in the repo for a long time, but APNs stopped working only a few months ago. Something may have been updated / changed on the Apple side.

I am assuming that the Ruby code somehow removes the duplication of the certificate, or that it may have only required the first certificate, so it worked in Ruby.

However, the solution was to remove the second certificate from the .pem file. After that, APNs started working, and now they work (I just received yesterday).

+5
source

If you simply reuse the old certificate signing request (CSR), be sure to delete the expired / old APNs certificate from your Keychain before exporting the new and its private key to the p12 file. If you do not, the PEM file that you created from the exported p12 will still contain the expired / old certificate, which is not suitable for the Apple Push provider. Thus, it turns out unable to connect to ssl...

0
source

All Articles