Unable to connect to Google Cloud SQL using PHP PDO and SSL - php

I am trying to connect to my Google Cloud SQL instance using PHP PDO. If I don't enforce SSL, everything works fine. But if I enforce SQL, I am unable to connect.
I have downloaded the server certificate from my Google Cloud SQL instance, as well as the client certificate (and matching key that I created). I know they're OK, because the following line works fine from the command shell:
mysql -h[myHostIp] -uroot -p --ssl-ca=settings/server-ca.pem --ssl-cert=settings/client-cert.pem --ssl-key=settings/client-key.pem [myDatabase]
However, from the same folder in a standalone PHP file run from the command line, the following PHP code does not:
<?php
$myHostIp = '[myHostIp]';
$myDbName = 'qabtk';
$myDbUser = 'root';
$myDbPassword = '[myPassword]';
$db = new PDO("mysql:host=$myHostIp;dbname=$myDbName", $myDbUser, $myDbPassword, [
PDO::MYSQL_ATTR_INIT_COMMAND => "set names 'utf8'",
PDO::MYSQL_ATTR_SSL_KEY =>'settings/client-key.pem',
PDO::MYSQL_ATTR_SSL_CERT=>'settings/client-cert.pem',
PDO::MYSQL_ATTR_SSL_CA =>'settings/server-ca.pem',
]);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = 'show databases';
$stmt = $db->prepare($sql);
$stmt->execute([]);
$answer = $stmt->fetchObject();
$stmt->closeCursor();
var_dump($answer);
exit;
Running that code gives the following error:
Trace/BPT trap: 5
If I remove both the client key and client certificate, leaving in only the server certificate, the error changes to:
Uncaught PDOException: SQLSTATE[HY000] [1045] Access denied for user 'root'#'[client IP address]' (using password: YES)
I've tried the recommendation of adding a PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false, which doesn't make any difference.
Help please!
UPDATE 2022-04-12: I am using this on an Apple silicon Macbook Pro, both directly using MacOS, and inside a Docker container running Ubuntu 18.04. The problem has now disappeared for no apparent reason - there's been much rebooting of many of the components and I didn't track exactly when it went away. However, it requires the line PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false to work which it really shouldn't do. I believe this may be to do with the way Google sets the CN in its certificates for Cloud SQL, but I'm not certain.

Related

Unable to Connect to Mysql Through PDO on Certain Networks

I am trying to connect to a MySQL database through PHP's PDO. It works fine on my home network and some other networks (coffee shops, public internet). When I try to connect through my phone's personal hotspot or through hotel wifi, it no longer works.
I am using the same login information across all of these with the same machine setup (XAMPP VM - Mac). This is my connection file:
$DBO = "mysql:host=$DB_Servername;dbname=$DB_Name";
try {
$conn = new PDO($DBO, $DB_Username, $DB_Password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo "Connection Failed: " . $e->getMessage();
}
This is the error I am getting:
Connection Failed: SQLSTATE[HY000] [2002] Connection timed out
I've tried the server name with the website address and the ip address. The strange thing is when I'm using the VS code database extension, I am able to connect to the database fine (no matter the network I am on). I can't figure out why that would be working but the PDO wouldn't be.
I read this answer about adding a space after 'mysql: ', and it returns this new message:
Connection Failed: SQLSTATE[HY000] [1045] Access denied for user 'dailyrts_realDB'#'localhost' (using password: YES)
The user account I am logging in with is assigned to the correct database and the new IP's I connect to are being registered.
dns_get_record returns:
dns_get_record(): A temporary server error occurred.
I wasn't able to find a fix using XAMPP-VM however, the same code works perfectly when using the XAMPP Installer version of the app on MacOS. I looked around for a bit to see if anyone else was having this problem and I didn't find anything that matches this issue specifically. Most were referring to connecting to a local database.
This answer about accessing MySQL through the root user is pretty close to the issue I was having and they recommend following this guide to fix the issue. I don't need to have the VM version installed so I haven't tested this myself however, it seems to have worked for him.
I'm not sure why the VM version only works on some networks and not others when connecting to MySQL databases. I'm sure this has something to do with port blocking on the network's end (mobile hotspot providers are notorious for blocking ports) and because the VM version handles network traffic differently from the regular version.
It looks like issues with the VM version are not isolated to this specific issue on MacOS. In my personal experience (and others), I'd recommend going with the installer version if you are able to. It is more developed and has more online support surrounding it.

Connection failed: SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client. Busy ports or source code problem?

I decided to continue an old project that I had abandoned some time ago due to many mistakes. With new strength I started to remove mistakes but I reached a point where I got stuck. I found with great difficulty that my problem came from the PDO connection to my database and half of my code became unusable. I read on the topic and tried many different ways to solve the problem, but without success. For starters I will say that I use XAMPP, Server version: 10.4.8-MariaDB, Apache / 2.4.41 (Win64) OpenSSL / 1.1.1c PHP / 7.3.1, phpMyAdmin Version information: 5.1.1 (up to date). Since I haven't used XAMPP for a long time and I have Workbench, Postgree and others installed, I had to change the ports of Apache and MySQL. I put a password on the root account in phpMyAdmin because I read that this can help, but then there were more problems, I used this request in phpMyAdmin:
ALTER USER 'root'#'localhost' IDENTIFIED WITH mysql_native_password
BY '...';
But in this query it gave me a syntax error and for that I used the one that was successful:
ALTER USER 'root'#'localhost' IDENTIFIED BY '...';
But the problem still exists. I also want to insert the fact that there are 2 connection strings in my project. There is no problem with one, but with the PDO connection string I get this error from the try catch construction:
Connection failed: SQLSTATE [HY000] [2054] The server requested authentication method unknown to the client
I read that the problem may be due to busy ports, but I decided to consult you before I started messing with the XAMPP files. Basically I changed the port to 3308 and the workbench is to 3306 but still when I run XAMPP I get an error message:
Problem detected!
Port 3306 in use by "Unable to open process"!
MySQL WILL NOT start without the configured ports free!
You need to uninstall / disable / reconfigure the blocking application
or reconfigure MySQL and the Control Panel to listen on a different port
However, I still managed to start MySQL.
I decided to write this to get advice and possibly help people with the same problem, because I saw that there are a lot of people who have encountered this.
I found a solution to my problem thanks to #iambpn -> https://github.com/laradock/laradock/issues/1392. I also have a mysql server installed. I changed my connection string in the same way as the post from Aug 23, 2019 by putting the host. my solution looks like this:
$host = "127.0.0.1:3308";
$dbname = "inventory";
$user = "root";
$password = "------";
try {
$dsn = 'mysql:host='.$ host.';dbname ='.$dbname;
$connect = new PDO ($dsn,$user,$password);
$connect->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
return $connect;
} catch (PDOException $e) {
echo 'Connection failed:'.$e->getMessage();
exit;
}
but before that the XAMPP ports must be changed if SQL server is installed!

'Access Denied' when trying to connect to Amazon-RDS instance using SSL from shared hosting (but it works when testing locally)

I'm trying to deploy a web app to a shared hosting provider (Strato), but I have problems establishing a SSL-connection to the Amazon-RDS instance that I'm using.
While testing the web app locally (using XAMPP) it works fine, but on the shared hosting I get a HTTP-500 error response after a 2 minute timeout.
My web app is using the Code Igniter framework (but I think this is not what's causing the issue). The database user was created using the REQUIRE SSL attribute to enforce the use of SSL. The user's "host" value is "%" to allow for remote connections.
At first I checked the apache error logs. They said
"19.09.2019 10:13:23 my-url.de [client XXXX:XXXX:XXXX::] End of script output before headers: index.php"
everytime I tried to access the site.
Then I tried to test a minimal example not even using Code Igniter (code below).
$servername = "XXXXXXXXXX.XXXXXXXXXXX.eu-central-1.rds.amazonaws.com";
$username = "username";
$password = "password";
$dbname = "db_name";
$con = mysqli_init();
if (!$con){
die("mysqli_init failed");
}
$ca_filename = realpath('./../cert/rds-combined-ca-bundle.pem');
echo 'Does the ca file exist? '. (file_exists($ca_filename) ? 'true' : 'false').'<br>';
$con->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, FALSE);
mysqli_ssl_set(
$con,
NULL,
NULL,
realpath('./../cert/rds-combined-ca-bundle.pem'),
NULL,
NULL);
if (!mysqli_real_connect($con,$servername, $username, $password, $dbname, 3306))
{
die("Connect Error: " . mysqli_connect_error());
}
echo "Connected to database.<br>";
$res = $con->query("SHOW STATUS LIKE 'Ssl_cipher'");
$row = $res->fetch_assoc();
if(empty($row['Value'])) {
echo 'No SSL';
} else {
echo $row['Value'].'<br>';
}
mysqli_close($con);
I would expect some output like
Does the ca file exist? true
Connected to database.
DHE-RSA-AES256-SHA
When testing it locally (using XAMPP) I got the following output:
Does the ca file exist? true
Connected to database.
DHE-RSA-AES128-SHA
(this is weird because it says "No SSL" even though the user requires SSL - but the connection is established)
EDIT: This looks like it's working correctly.
Then I was testing it on the shared hosting and got this as an output:
Does the ca file exist? true
Warning: mysqli_real_connect(): (28000/1045): Access denied for user 'username'#'XXX.XXX.XXX.XXX' (using password: YES) in /shared/hosting/path/htdocs/public/dbtest.php on line 25 Connect Error: Access denied for user 'username'#'XXX.XXX.XXX.XXX' (using password: YES)
UPDATE 1
By comparing the phpinfo() of my local server with the one of the shared hosting I found out that my local server uses "mysqlnd" (MySQL Native Driver) while the shared hosting server uses "mysql". The info in "mysqlnd" says "core SSL: supported" while there's absolutely no SQL-related info on SSL in the phpinfo() of the shared hoster. Is it impossible to establish a SSL connection without mysqlnd?
UPDATE 2
I did another run using PDO instead of mysqli. Same problem: Works locally, but not on shared hosting. This time I got the error message Fatal error: Uncaught Error: Undefined class constant 'MYSQL_ATTR_SSL_VERIFY_SERVER_CERT'. I read here that if this happens it means I need to upgrade the PHP version (which is weird because the hosting server is running PHP 7.2.22). Even after changing the PHP version to 7.3.9 (which is newer than the one I use locally), the error still occurs. If I delete the line PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => FALSE from the new script version, I get the Access denied error again.
This sounds a lot like a security group problem. When you are testing locally you are probably entering the RDS with your private IP over a certain port (if SSL 443).
Probably you don't have the security group configured, that the inbound traffic is allowed from other public IPs.
I would double check all the security group rules. If it allows your local connections and what you allow if it is another IP.
Thanks to #Adiii and #benra I found the cause of the problem: Since PHP 5.3.0 it normally uses the MySQL Native Driver, but the shared hoster I use (Strato) has a PHP 7 installation that still uses the legacy MySQL driver. Therefore MYSQLI_OPT_SSL_VERIFY_SERVER_CERT (for mysqli) and MYSQL_ATTR_SSL_VERIFY_SERVER_CERT (for pdo) are not available, which causes the problem when using CA-files of cloud providers like Amazon RDS or Google Cloud.
My solution to this will be to use an own V-Server.

PDO Error “Adaptive Server is unavailable” when connecting to MS SQL Database

I'm trying to connect to a MSSQL database with odbc in php.
My issue is similar to this issue, I can connect with tsql, but not with php.
The answer to the problem not work because I think I don't have SELinux installed (I don't know what it is, but pacman not found this package (or with a similar name) on my computer)
I don't understand why it doesn't work, odbc is installed and detected by php
print_r(PDO::getAvailableDrivers());
Array ( [0] => odbc )
I'm connecting by doing that:
$dsn = 'odbc:Driver=FreeTDS;Server=127.0.0.1;Port:1433;Database=[my base name]';
$pdo = new PDO($dsn, $user, $password);
My base is not in local, I use a ssh tunel because the base in accessible only at my school, and we need an ssh tunnel. And it work, I can connect myself to the base with tsql.
When I was connecting PHP to our MS SQL server, I could never get a connection established using ODBC drivers.
Instead, I downloaded the official PHP > SQL SERVER drivers direct from Microsoft. You can find them here.
Once installed, you must configure your php.ini file to include the new drivers, restart your web server and then use the following to open a new connection:
$conn = new PDO("sqlsrv:Server=SERVER_IP,1433;Database=DATABASE_TO_OPEN;");

PDO Error "Adaptive Server is unavailable" when connecting to MS SQL Database

I am trying to connect to a SQL server database that is running on a windows server. I am running this PHP code on a linux server (centos 7).
I am using the following pdo connection string to connect to the database.
$db = new PDO ("dblib:192.168.2.1;dbname=TestDB","username",'pass');
When i run the code i get the following exception. 'PDOException' with message 'SQLSTATE[HY000] Unable to connect: Adaptive Server is unavailable or does not exist (severity 9)'
I have tried to test the connection using tsql and i am able to connect to the database without any error. The following code gave me a list of all the tables in TestDB. It wouldnt work if i didng type use TestDB first.
tsql -S 192.168.2.1 -U username -P 'pass' -L TestDB
use TestDB
GO
select * FROM sys.Tables
GO
My freetds.conf file contains the following
[Server1]
host = 192.168.2.1
port = 1433
tds version = 8.0
I cannot figure out how i am able to connect using tsql, but cannot do the same when connecting with php.
The dblib driver is definitely installed.
print_r(PDO::getAvailableDrivers());
Array ( [0] => dblib [1] => mysql [2] => sqlite )
Answer
Found the cause of the problem. Turned out to be SELinux. The following commands fixed the issue.
setsebool -P httpd_can_network_connect 1
setsebool -P httpd_can_network_connect_db 1
You have the datasource name, you should make use of it:
$db = new PDO ("dblib:host=Server1;dbname=TestDB","username",'pass');
You are running linux right? I recommend giving odbc a shot.
Three things to check for you.
First try your connection using your defined port.
Instead of:
$db = new PDO ("dblib:192.168.2.1;dbname=TestDB","username",'pass');
try using this:
$db = new PDO("dblib:host=192.168.2.1:1433;dbname=TestDB","username",'pass');
Second, you should be sure if your SQL Server is configured to hear on port 1433. You can check this using the SQL Server Configuration Manager.
The third (if you run it on windows) thing you can check is one thing I find in the PHP docs. Inside a comment, another one mentioned the same error. Here is the answer which seems to work:
For PDO MSSQL connection issues, ensure that you have the updated version of ntwdblib.dll (currently 8.00.194 as of this post). Overwrite the existing (old) file or place it in the Windows system32 folder. The version that ships with PHP 5.2.X does not work. This is a well known issue apparently, but I had a really hard time finding information on this issue until I was able to lock in a file name. I hope that this helps someone.
Another possible issue could be SELinux if it's enabled. I've gotten some errors which are something familiar with this on my Ruby on Rails installation. You can give it a try by disabling SELinux and try it again.
When connecting using PDO, if you leave out the host= it uses the Unix domain sockets which could be causing your problem. Putting in the host= will connect to the database via TCP/IP.
So try change your line of code to:
$db = new PDO ("dblib:host=192.168.2.1;dbname=TestDB","username",'pass');
Or with the port aswell:
$db = new PDO ("dblib:host=192.168.2.1:1433;dbname=TestDB","username",'pass');
For me, the problem was using the IP address.
I changed it to "MyServerName/SQL2017DEV" and it connected

Categories