我正在尝试从GCE(Google Compute Engine)实例使用SSL连接到Google Cloud SQL。我的问题是无法通过SSL连接到Cloud SQL实例。
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自签名证书用于与PHP连接Mysql
有人知道解决方案吗?
更新1
有人报告了这个错误。 https://bugs.php.net/bug.php?id=71003
在这里也有一个非常相似的问题。 Google Cloud SQL SSL验证对等证书失败
我的PHP版本是5.6.14。 我将升级到5.6.16,以使用MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT。
更新2
当我使用mysqli时已经解决了它。
我所做的如下:
1 我将我的PHP更新到5.6.20
sudo apt-get install php5
我将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:
这个错误报告涉及到PDO的情况,似乎还没有被修复。
https://bugs.php.net/bug.php?id=71845
据我所知,目前没有解决PDO的方法。
更新4:
一些人指责谷歌的CN名称设计(我实际上同意他们的观点...)
最糟糕的是你们使用不可能的CN名称(:)。如果CN没有冒号,也许我可以在我的主机文件中映射ip和CN,这样当进行对等验证时就可以通过了。有了冒号,php认为是主机,是端口。
而且谷歌员工也理解了这个问题。
我理解通过IP连接的当前情况并不理想。
但看起来他们提供了一个叫做“代理”的解决方案。
https://groups.google.com/forum/#!topic/google-cloud-sql-discuss/gAzsuCzPlaU
我正在使用第二代Cloud SQL,并且我的应用程序托管在GCE上。因此,我认为我可以使用代理方式。我现在要尝试一下。
更新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();
参考 (日语)
连接Google Cloud SQL使用MySQL客户端的方法 在Google App Engine上使用Cloud SQL的PHP方法