2016-04-08 2 views
9

Я пытаюсь использовать Google Cloud SQL через SSL из экземпляра GCE (Google Compute Engine). Моя проблема в том, что я не могу подключиться к экземпляру Cloud SQL через SSL.PHP MySQL через SSL. Сертификат peer не соответствует

Команда mysql работает нормально. Я могу подключиться к экземпляру Cloud SQL с файлами сертификации.

mysql -uroot -p -h [IP Address] --ssl-ca=/home/user/.cert/server-ca.pem --ssl-cert=/home/user/.cert/client-cert.pem --ssl-key=/home/user/.cert/client-key.pem 

Однако, когда я получаю доступ из программы PHP, у меня возникла предупреждающая и фатальная ошибка.

<?php 
$pdo = new PDO('mysql:host=[IP Address];dbname=testdb', 'root', 'test', array(
    PDO::MYSQL_ATTR_SSL_KEY =>'/home/user/.cert/client-key.pem', 
    PDO::MYSQL_ATTR_SSL_CERT=>'/home/user/.cert/client-cert.pem', 
    PDO::MYSQL_ATTR_SSL_CA =>'/home/user/.cert/server-ca.pem' 
    ) 
); 
$stmt = $pdo->query("SHOW TABLES;"); 
$row = $stmt->fetch(PDO::FETCH_ASSOC); 
print_r($row); 
?>  

PHP Warning: PDO::__construct(): Peer certificate CN=`[GCP project name]:[Cloud SQL instance name]' did not match expected CN=`[IP Address]' in /tmp/mysql.php on line 7 
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [2002] ' in /tmp/mysql.php on line 7 

я получил ту же ошибку, когда я использовал MySQLi.

$mysqli = mysqli_init(); 
mysqli_options($mysqli, MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, true); 

$mysqli->ssl_set('/home/user/.cert/client-key.pem', 
       '/home/user/.cert/client-cert.pem', 
       '/home/user/.cert/server-ca.pem', 
        NULL,NULL); 

$mysqli->real_connect('[IP Address]', 'root', 'test', 'testdb', 3306, NULL, MYSQLI_CLIENT_SSL); 

PHP Warning: mysqli::real_connect(): Peer certificate CN=`[GCP project name]:[Cloud SQL instance name]' did not match expected CN=`[IP Address]' in /tmp/mysql3.php on line 30 
Warning: mysqli::real_connect(): (HY000/2002): in /tmp/mysql3.php on line 30 

Этот вопрос выглядит иметь отношение к моему делу, но нет ответа еще. SSL self-signed certifications to connect with Mysql with PHP

Кто-нибудь знает о решениях?


Update 1

Эта ошибка сообщается. https://bugs.php.net/bug.php?id=71003

Очень похожий вопрос здесь. Google Cloud SQL SSL fails peer certificate validation

Моя версия PHP - 5.6.14. Я буду обновлять до 5.6.16, чтобы использовать MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT.


Update 2

Исправлено, когда я использую MySQLi

То, что я сделал это, как следующие:

1 Я обновил свой РНР 5.6.20

sudo apt-get install php5 

2 Я положил MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT такой вариант.

$mysqli->real_connect('[IP Address]', 'root', 'test', 'testdb', 3306, NULL, MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT); 

Мое приложение использует как mysqli, так и PDO по некоторым причинам. Теперь я ищу решение PDO.


Обновить отчет 3

Эта ошибка показывает о случае ПДО. Звуки еще не исправлены.

https://bugs.php.net/bug.php?id=71845

Это также связано. https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/google-cloud-sql-discuss/4HNvmq7MpU4/kuSjhkS2AwAJ

Насколько я понимаю, для PDO не существует способа разрешения.


Update 4

Некоторые люди обвиняют дизайн компании Google имен CN (я согласен с ними на самом деле ..)

Что худшее это вы, ребята, использовать невозможно CN имен (:). Если бы CN был без двоеточия, возможно, я могу сопоставить ip и CN в файле моих хостов, чтобы при проверке проверки сверстников он мог пройти. С толстой кишкой, php думает, что это хозяин, и находится порт

и персонал Google? понять проблему.

Я понимаю, что текущая ситуация при подключении по IP не идеальна.

Но, похоже, они предоставляют решение под названием «прокси».

https://groups.google.com/forum/#!topic/google-cloud-sql-discuss/gAzsuCzPlaU

Я использую Cloud SQL второго поколения, и мои приложения размещаются GCE. Поэтому я думаю, что могу использовать прокси-путь. Я попробую сейчас.


Update 5

Настройка доступа прокси. Решил как PDO, так и mysqli-доступ.

Установите прокси-сервер на Ubuntu

$ wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 
$ mv cloud_sql_proxy.linux.amd64 cloud_sql_proxy 
$ chmod +x cloud_sql_proxy 
$ sudo mkdir /cloudsql; sudo chmod 777 /cloudsql 
$ ./cloud_sql_proxy -dir=/cloudsql -instances=<project name>:us-central1:mydb 

PDO

<?php 
$pdo = new pdo('mysql:unix_socket=/cloudsql/<project name>:us-central1:mydb;dbname=testdb','root','test'); 
$stmt = $pdo->query("SHOW TABLES;"); 
$row = $stmt->fetch(PDO::FETCH_ASSOC); 
print_r($row); 
?> 

MySQLi

$mysqli = mysqli_connect('localhost', 'root', 'test', 'testdb', 3306, '/cloudsql/<project name>:us-central1'); 
$sql = "SELECT id FROM users"; 
if ($result = $mysqli->query($sql)) { 
    while ($row = $result->fetch_assoc()) { 
     echo $row["id"] . "\n"; 
    } 
    $result->close(); 
} 
$mysqli->close(); 

рефов (японский)

http://blog.hrendoh.com/connecting-to-google-cloud-sql-using-mysql-client/ http://blog.hrendoh.com/google-appengine-php-using-cloud-sql/

+0

вы удивительны. обновление № 5 полностью сработало для меня. Спасибо!!! – ingernet

+0

Я часами стучал головой. Может быть, это поможет кому-то другому. Шаг 5, часть 1, была моей проблемой - я был зарегистрирован как root. Re-run как обычный пользователь, все работало как ожидалось! – webaholik

ответ

4

Вкратце, используйте Cloud Cloud Proxy, если вам нужен доступ как из PDO, так и из mysqli. У вас нет выбора.

https://cloud.google.com/sql/docs/sql-proxy

+0

Примечание для сотрудников GCP: PR не является веской причиной для редактирования ответов. – Sammitch

5

Для соединений PDO, которые не используют Google облако или не могут извлечь выгоду из прокси-решения, они исправили ошибку, и это слито в настоящее время. Существует теперь постоянная для этого (начиная с апреля 2017 года):

PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false, 

http://git.php.net/?p=php-src.git;a=commit;h=247ce052cd0fc7d0d8ea1a0e7ea2075e9601766a

Надеется, что это помогает.

+0

Означает ли это, что соединение защищено? –

+0

Ну, да, это зашифрованное соединение, но учтите, что вы не проверяете сам сертификат. – javi

+0

Я знаю, но я не смог найти решение без использования кода строки выше. Сертификаты отлично работают при использовании терминала или приложения, такого как продолжение. Но с точки зрения php я не нашел никакого решения –

0

Пример в CakePHP 3.5.x + PHP 7.1.x + SQL Google Cloud + SSL

Изменение файла в: конфигурации/приложения.PHP

... 
    ... 

    /** 
    * The test connection is used during the test suite. 
    */ 
    'default' => [ 
     'className' => 'Cake\Database\Connection', 
     'driver' => 'Cake\Database\Driver\Mysql', 
     'persistent' => false, 
     'host' => 'xx.xxx.xxx.xxx', 
     //'port' => 'non_standard_port_number', 
     'username' => 'user_name_x', 
     'password' => 'pass_x', 
     'database' => 'bd_name_x', 
     'encoding' => 'utf8', 
     'timezone' => 'UTC', 
     'cacheMetadata' => true, 
     'quoteIdentifiers' => false, 
     'log' => false, 

     'flags' => [ 
      PDO::MYSQL_ATTR_SSL_KEY => CONFIG.'client-key.pem', 
      PDO::MYSQL_ATTR_SSL_CERT => CONFIG.'client-cert.pem', 
      PDO::MYSQL_ATTR_SSL_CA => CONFIG.'server-ca.pem', 
      PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false 
     ], 

     //'ssl_key' => CONFIG.'client-key.pem', 
     //'ssl_cert' => CONFIG.'client-cert.pem', 
     //'ssl_ca' => CONFIG.'server-ca.pem', 

     //'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'], 
    ], 
], 
... 
... 

Пример PHP Pure + PDO + SSL:

$ssl_key = CONFIG.'client-key.pem'; 
$ssl_cert = CONFIG.'client-cert.pem'; 
$ssl_ca = CONFIG.'server-ca.pem'; 

$pdo = new PDO('mysql:host=xxx.xxx.xxx.xxx;dbname=db_name_x', 'user_name_x', 'pass_x', array(
    PDO::MYSQL_ATTR_SSL_KEY => '/path/full/client-key.pem', 
    PDO::MYSQL_ATTR_SSL_CERT => '/path/full/client-cert.pem', 
    PDO::MYSQL_ATTR_SSL_CA => '/path/full/server-ca.pem', 
    PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false 
    ) 
); 
$statement = $pdo->query("SHOW TABLES;"); 
var_dump($statement); 
$row = $statement->fetch(PDO::FETCH_ASSOC); 
echo json_encode($row); 
exit();