Подтвердить что ты не робот

PHP игнорирует сертификаты ssl при подключении к MySql

Используя код из руководства PHP, нашла здесь и здесь

<?php

$mysqli = mysqli_init();
if (!$mysqli) {
    die('mysqli_init failed');
}

$mysqli->ssl_set('/path/to/client-key.pem',   
                 '/path/to/client-cert.pem',
                 '/path/to/ca-cert.pem',
                  NULL,NULL); //<-- Doesn't matter if the paths are right or wrong

if (!$mysqli->options(MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT = 0')) {
    die('Setting MYSQLI_INIT_COMMAND failed');
}

if (!$mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5)) {
    die('Setting MYSQLI_OPT_CONNECT_TIMEOUT failed');
}

if (!$mysqli->real_connect('xx.xx.xx.xx', 'my_user', 'my_password', 'my_db')) {
    die('Connect Error (' . mysqli_connect_errno() . ') '
            . mysqli_connect_error());
}

echo 'Success... ' . $mysqli->host_info . "\n";

$mysqli->close();
?>

Я не могу подключиться к MySql. Он дает следующую ошибку:

Message: SQLSTATE[28000] [1045] Access denied for user 'my_user'@'xx.xx.xx.xx' (using password: YES) <-- the client IP

Я сузил проблему до строки $mysqli->ssl_set(...).

Когда я пропускаю неправильные пути к сертификатам, он должен бросать SSL certificate error в соответствии с этот пост, где пользователь страдал одна и та же проблема вместо этого выдает ту же самую предыдущую ошибку, которая была запрещена доступом.

Мне удалось установить соединение с помощью Navicat на сервере с помощью администратора базы данных, настроив соединение ssl следующим образом: enter image description here

Примечания:

  • Моя версия PHP 5.3.15
  • Версия MySql, используемая на удаленном сервере базы данных, 5.5.13-55
  • Оба Navicat и PHP-код запускаются с одного и того же ПК.
  • Администратор базы данных создал ssl_user специально для тестирования. Этому пользователю запрещен нормальный доступ и он должен подключиться с помощью ssl.
  • Прокси не используются.
  • Я пробовал PDO, и он страдает от той же проблемы.
  • Я пробовал mysql->connect(), но он выдает неправильную ошибку рукопожатия и, согласно некоторым комментариям в manual, он не работа.
  • Открыть ssl можно с phpinfo() enter image description here

Итак, возникает вопрос, почему PHP не жалуется на неправильные пути к сертификатам? Кажется, PHP игнорирует строку, где я устанавливаю пути сертификата!


UPDATE: Я попытался изменить строку, где я установил соединение, чтобы явно установить порт и использовать MYSQLI_CLIENT_SSL:

$mysqli->real_connect('xx.xx.xx.xx', 'my_user', 'my_password', 'my_db','3306',NULL,MYSQLI_CLIENT_SSL)

Однако я получил эту ошибку:

Warning: mysqli::real_connect(): (08S01/1043): Bad handshake in ...

ОБНОВЛЕНИЕ 2:

Это результат tcpdump-ing с сервера базы данных:

0x0040:  3142 6164 2068 616e 6473 6861 6b65       1Bad.handshake
13:16:18.133282 IP (tos 0x8, ttl  64, id 40823, offset 0, flags [DF], proto: TCP (6), length: 52) xx.xx.xx.202.mysql > xx.xx.xx.130.42766: F, cksum 0xf15f (correct), 112:112(0) ack 79 win 46 <nop,nop,timestamp 19516376 3465907>
        0x0000:  4508 0034 9f77 4000 4006 c8a7 c0a8 28ca  [email protected]@.....(.
        0x0010:  c0a8 2882 0cea a70e b36c 7e8b 7b4d a169  ..(......l~.{M.i
        0x0020:  8011 002e f15f 0000 0101 080a 0129 cbd8  ....._.......)..
        0x0030:  0034 e2b3                                .4..
13:16:18.133433 IP (tos 0x8, ttl  64, id 17337, offset 0, flags [DF], proto: TCP (6), length: 52) xx.xx.xx.130.42766 > xx.xx.xx.202.mysql: F, cksum 0xb695 (correct), 79:79(0) ack 113 win 92 <nop,nop,timestamp 3480910 19516376>
        0x0000:  4508 0034 43b9 4000 4006 2466 c0a8 2882  [email protected]@.$f..(.
        0x0010:  c0a8 28ca a70e 0cea 7b4d a169 b36c 7e8c  ..(.....{M.i.l~.
        0x0020:  8011 005c b695 0000 0101 080a 0035 1d4e  ...\.........5.N
        0x0030:  0129 cbd8                                .)..
13:16:18.133452 IP (tos 0x8, ttl  64, id 40824, offset 0, flags [DF], proto: TCP (6), length: 52) xx.xx.xx.202.mysql > xx.xx.xx.130.42766: ., cksum 0xb6c3 (correct), 113:113(0) ack 80 win 46 <nop,nop,timestamp 19516376 3480910>
        0x0000:  4508 0034 9f78 4000 4006 c8a6 c0a8 28ca  [email protected]@.....(.
        0x0010:  c0a8 2882 0cea a70e b36c 7e8c 7b4d a16a  ..(......l~.{M.j
        0x0020:  8010 002e b6c3 0000 0101 080a 0129 cbd8  .............)..
        0x0030:  0035 1d4e                                .5.N

xx.xx.xx.202 - это сервер базы данных ip.
xx.xx.xx.130 - это мой ПК ip.

ОБНОВЛЕНИЕ 3:

Я проверил длину пароля, используя следующий код:

mysql> select length(Password) from mysql.user where User='youruser'

И длина пароля 41.

ОБНОВЛЕНИЕ 4:

В сообщении об ошибке, возвращаемом при подключении с помощью командной строки через ssh на удаленном сервере, может появиться сообщение (я загрузил весь проект на удаленный сервер):

mysql -u test_ssl -password --ssl-key=/usr/local/apache2/htdocs/certs/client-key.pem --ssl-cert=/usr/local/apache2/htdocs/certs/WRONG-CERTIFICATE.pem

Я получаю следующую ошибку:

SSL error: Unable to get certificate from '/usr/local/apache2/htdocs/certs/WRONG-CERTIFICATE.pem'
ERROR 2026 (HY000): SSL connection error ---> notice the error here

Если я не предоставляю никаких сертификатов, я получаю следующее сообщение:

-bash-3.2$ mysql -u test_ssl -password
ERROR 1045 (28000): Access denied for user 'test_ssl'@'localhost' (using password: YES)

Что такое ошибка, которую я получаю при подключении с помощью PHP с использованием правильных или недействительных путей к сертификатам!

Может, это что-то значит?

4b9b3361

Ответ 1

Ну, мы смогли решить проблему, но я не уверен, что это практическое решение.

Прежде всего нам удалось найти источник проблемы, который был клиентскими библиотеками MySql, которые PHP использует для подключения с использованием SSL. PHP должен был быть совместим с этими библиотеками, чтобы иметь возможность подключаться с использованием SSL.

Кроме того, возник конфликт между клиентскими библиотеками MySql и библиотеками OpenSSL.

Единственным решением нашей проблемы было переустановить все с нуля. Мы использовали новый сервер, новую версию Mysql (последняя сборка) со всеми библиотеками, новейшую сборку PHP и новейший дистрибутив CentOS.

Ответ 2

На первый взгляд вы не установили параметр MYSQLI_CLIENT_SSL для подключения.

if (!$mysqli->real_connect('localhost', 'my_user', 'my_password', 'my_db', null, MYSQLI_CLIENT_SSL)) { ... }

Update:
Вы можете попробовать добавить $mysqli->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, true); до $mysqli->ssl_set().

Кроме того, это работает для меня:

<?php
$pdo = new PDO('mysql:host=ip;dbname=dbname', 'username', 'password', array(
    PDO::MYSQL_ATTR_SSL_KEY    =>'/etc/mysql/ssl/client-key.pem',
    PDO::MYSQL_ATTR_SSL_CERT=>'/etc/mysql/ssl/client-cert.pem',
    PDO::MYSQL_ATTR_SSL_CA    =>'/etc/mysql/ssl/ca-cert.pem'
    )
);
$stmt = $pdo->query("SHOW TABLES;");
$row = $stmt->fetch(PDO::FETCH_ASSOC);
print_r($row);
?>

Обновление 2: Вы можете получить bad handshake, если используете старый mysql-пароль (длиной 16 байт). Чтобы проверить, запустите следующий запрос:

mysql> select length(Password) from mysql.user where User='youruser'

Если вы получили 16:

// disable old_passwords:
mysql> SET @@session.old_passwords = 0;

// update password for user used in PHP скрипт:
mysql> SET PASSWORD FOR 'existinguser'@'localhost' = PASSWORD('existingpass');

// check if we have a 41 bytes long password:
mysql> select length(Password) from mysql.user where User='youruser'

И снова проверьте соединение с PHP script.