Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to connect SSL server using fsockopen()

I'm running the next script from my local host and the production server, and Im getting different outputs. Anyone knows why am I getting that false from my localhost?

<?php
$host = 'ssl://mail.companyname.org';
$port = 993;
$error = 0;
$errorString = "";

var_dump(fsockopen($host, $port, $error, $errorString, 30));
var_dump($errorString);
var_dump($error);

Local host output:

bool(false)

Production server output:

resource(4) of type (stream)

UPDATE: after the comments/answer I have modified the code and now Im getting this output on my local host:

PHP Warning: fsockopen(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed in /tmp/test.php on line 7 PHP Warning: fsockopen(): Failed to enable crypto in /tmp/test.php on line 7 PHP Warning: fsockopen(): unable to connect to ssl://mail.twmdata.org:993 (Unknown error) in /tmp/test.php on line 7 bool(false) string(0) "" int(0)

like image 854
ziiweb Avatar asked Dec 22 '22 16:12

ziiweb


2 Answers

it seems this is problem with server certificate :

first you can check if your server certificate and its chains are valid by this:

https://www.sslshopper.com/ssl-checker.htm

if somethings were wrong in ssl-checker?

  • you can try to correct SSL certificate configs in companyname.org

    if you succeed and error was persists ?

    1. you have to add Certificate files manually.

if you have a self-signed certificate:

  1. you have to add Certificate files manually.

if you dont have certificate nor you dont care about man-in-the-middle attack, you can still use SSL without Certificate.

  1. turn off php fsock Certificate check (not recommended)

its recommended to have a certificate at least a self-signed. if you have a self-signed try 1 solution.

I have found the Problem

You have exposed your Domain name in your PHP Warning Log, so i have checked your domain SSL.

after i check your company`s domain certificate using this tool:

https://www.sslshopper.com/ssl-checker.html#hostname=twmdata.org

it had 2 errors with your certificates:

  • This certificate has expired (0 days ago). Renew now.

  • None of the common names in the certificate match the name that was entered (twmdata.org). You may receive an error when accessing this site in a web browser.

so it seems you have to renew your certificate first

certificate error

Update:

i have found this answer maybe helpful

https://stackoverflow.com/a/40962061/9287628

it suggested to use

stream_context_create(['ssl' => [
   'ciphers' => 'RC4-MD5'
]])

as @ChrisHaas suggested connecting with stream_context_create and stream_socket_client brings you a lot of option if you want to dictate the cert directory or you want to turn off certificate check.

like image 168
Abilogos Avatar answered Jan 04 '23 04:01

Abilogos


Per the documentation for fsockopen

The function stream_socket_client() is similar but provides a richer set of options, including non-blocking connection and the ability to provide a stream context.

Basically, fsockopen is very low-level but without many options, or, arguably, "sane defaults".

Instead, you can switch to stream_socket_client which will allow you to specify a context as the last parameter, and that object has many options, including a dedicated one with over a dozen options specific to SSL. The object created from this function is compatible with fwrite and other functions, so it should do everything you are hoping for.

$context = stream_context_create([/*Options here*/]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);

Now, what options should you use?

The worst option that might work is probably verify_peer. I say "worst" because you are throwing away the verifiability part of SSL/TLS and only using it for encryption, and doing this will make you susceptible to MitM attacks. However, there's a place and time for this, so you could try it if the other options are too complicated.

$context = stream_context_create(['ssl' => ['verify_peer' => false]]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);

Instead, I'd recommend using either cafile or capath which do the same thing except the former is for a file while the latter is for a directory.

$context = stream_context_create(['ssl' => ['verify_peer' => true, 'cafile' => '/path/to/file']]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);

What certs should you use? We use this library to pull in recent CA files on a periodic basis, very convenient. There's a little bit of setup that's per-project but once you get it it goes pretty fast. See this for pulling in a CA file at a well-known location.

One other last option is local_cert which you can use with a PEM file that holds the certificate and private key from the server, if you have access to that.

EDIT

The cert on mail.twmdata.org:993 is different than the web server's cert that other people are talking about, which is generally a best practice. You can inspect that cert using:

openssl s_client -connect mail.twmdata.org:993 -servername mail.twmdata.org

If you do that, you'll see that the server has a self-signed cert which you can get around by setting the verify_peer option to false.

like image 35
Chris Haas Avatar answered Jan 04 '23 02:01

Chris Haas