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.
2
Answers
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) andMYSQL_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.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.