Probably not an answer yet, but more than I can make readable in comments:
That error code (and string) are about a Diffie-Hellman public key. Unless you are using static DH, which would be very unusual -- I've never even seen a public CA issue a DH cert -- this must be the client's ephemeral DH key for a DHE ciphersuite. For it to be invalid suggests something pretty weird in the client SSL stack, an "attack" (or at least damage)
on the session, or the DH parameters in your server getting clobbered -- all of which shouldn't happen.
If the client claims 'self-signed cert' and you aren't using one, that is a different problem that shouldn't be related,
but might possibly be through some weird bug.
The client appears to be something in PHP, which I'm not familiar with, but I'll guess is likely using openssl
to make client SSL connections (in this case to you) (just as nginx AFAIK uses openssl on the server side).
If you configured your server to provide a full cert chain including root,
and openssl client does not have that root in the truststore it is using (which may be configurable),
it may confusingly report 'self-signed cert' rather than a more exact 'untrusted root'.
If I'm right it's openssl, can (you ask) the client people try a connection to you using commandline openssl s_client
,
with the same truststore their program is using, and the same cipherlist (possibly default) --
and see if that gets any error and if so the (much more verbose) error info s_client gives?
In other words the command would be something like
openssl s_client -connect $yourhost:$yourport -CAfile $file_if_any -CApath $dir_if_any -cipher $string_if_any
(If it does connect, just control-D to exit without sending anything.)
If s_client
says something like verify error: ... self-signed
, they should fix the truststore they are using to include
the root cert of the chain you are using. (That might mean changing to use a different
truststore, if they can't or don't want to modify the one they currently use.)
In the meantime what (if anything) is configured in your server for ssl_dhparam
?
Try openssl dhparam -check -noout
on that file just in case, although anything
wrong there should have failed at an earlier step in the handshake.
When other (client) connnections succeed, can you check if they negotiate DHE or not?
Remeber that an RSA cert, the most common by far, can support plain-RSA DHE-RSA and ECDHE-RSA ciphers.
Some clients can display the selected cipher, in particular most browsers if your server accepts browser https requests.
I don't use nginx myself, but http://osdir.com/ml/nginx/2010-07/msg00033.html indicates it can log this.
s_client
always tells you cipher, along with much other stuff.
If the problem still occurs, can you, or they or someone, get a network capture -- using wireshark/tshark, tcpdump,
or similar -- of a failed connection? That will confirm the ciphersuite and other options used, and show the DHE
exchange up to the failure, which should at least narrow down the problem. Easiest way to look (IMO) is to display
in wireshark (even if you captured with something else), expand the ServerHello and get the CipherSuite,
and expand the ServerKeyExchange and ClientKeyExchange and get all the details.