Setup SSL for PDO-MySQL on Fedora - php

I want to setup SSL for MySQL on Fedora. I am using PDO as MySQL-connector in PHP. But it is not working.
The PHP-version (php -v) is:
PHP 5.6.6 (cli) (built: Feb 19 2015 13:46:39)
When I check php -m I get a long list, including openssl, PDO, pdo_mysql, mysql.
In /etc/my.cnf I added the "ssl" and the three certificates (CA-root, private-key, certificate). I restarted MySQL and Apache.
The pdo-connector is this:
function getDBConn() {
return new PDO(
'mysql:host=localhost; dbname=forum',
user,
pass,
array(
PDO::MYSQL_ATTR_SSL_KEY => path_to_same_as_in_my.cnf.key,
PDO::MYSQL_ATTR_SSL_CERT => path_to_same_as_in_my.cnf.crt,
PDO::MYSQL_ATTR_SSL_CA => path_to_same_as_in_my.cnf.crt
)
}
But on the pages that connect to the database I get the following errors:
Warning: PDO::__construct(): this stream does not support SSL/crypto in /var/www/html/functions.php on line 78
Warning: PDO::__construct(): cannot connect to MySQL by using SSL in /var/www/html/functions.php on line 78
Warning: PDO::__construct(): [2002] (trying to connect via unix:///var/lib/mysql/mysql.sock) in /var/www/html/functions.php on line 78
FATAL ERROR: Uncaught exception 'PDOException' with message 'SQL:STATE[HY000][2002]' in /var/www/html/functions.php:78 Stack trace .....
Anyone who has a solution for this?

All you need is this for PDO MySQL using SSL
<?php
$pdo = new PDO('mysql:host=ip;dbname=db', 'user', 'pass', 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'
)
);
$statement = $pdo->query("SHOW TABLES;");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['_message']);
?>
Another biggest reason you're getting the error is because you might not have openssl installed.

Related

PHP mysqli and SSL

I am trying to configure Galera Cluster over a WAN (VPN is not an option). For obvious reasons I am setting up the connections to require SSL keys, and am having difficulties getting the application to connect. I can successfully connect using PDO, but cannot get mysqli to work. The setup will be:
USA location:
mainWebServer: openSUSE Leap 15.2, Apache 2.4.33 (named virtual host myserver.mycompany.com)
myServer1: Ubuntu 20.04, MySQL Galera Cluster 8.0.19
myDevBox: openSUSE Tumbleweed, running PHP CLI to debug connection issues
China location:
myServer2: Ubuntu 20.04, MySQL Galera Cluster 8.0.19, Apache 2.4 current
myServer3: clone of myServer2
The Galera cluster name is myServer, and the node names are myServerX corresponding to their actual hostname.
PHP version info:
me#mydevbox:~> php --version
PHP 7.4.9 (cli) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.9, Copyright (c), by Zend Technologies
MySQL server version info:
me#myServer1:~$ mysql --version
mysql Ver 8.0.19-26.3 for Linux on x86_64 (MySQL Wsrep Server - GPL)
Code:
<?php
$conn = mysqli_init() or print("init failed\n");
mysqli_ssl_set(
$conn,
'/srv/www/vhosts/myProject/mysql_ssl_certs/client-key.pem',
'/srv/www/vhosts/myProject/mysql_ssl_certs/client-cert.pem',
'/srv/www/vhosts/myProject/mysql_ssl_certs/ca-cert.pem',
NULL,
NULL
);
mysqli_real_connect(
$conn,
'myServer1',
'myUser',
'myPassword',
'myDB',
3306,
MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT
) or print("connect failed to myServer1 [{$conn->connect_errno}: {$conn->connect_error}]\n");
print_r($conn);
Output:
me#mydevbox:~> php sqlssltest.php
PHP Warning: mysqli_real_connect(): Peer certificate CN=`myServer' did not match expected CN=`myServer1' in /home/me/sqlssltest.php on line 21
PHP Warning: mysqli_real_connect(): Cannot connect to MySQL by using SSL in /home/me/sqlssltest.php on line 21
PHP Warning: mysqli_real_connect(): [2002] (trying to connect via (null)) in /home/me/sqlssltest.php on line 21
PHP Warning: mysqli_real_connect(): (HY000/2002): in /home/me/sqlssltest.php on line 21
connect failed to myServer1 [2002: ]
mysqli Object
(
[client_info] => mysqlnd 7.4.9
[client_version] => 70409
[connect_errno] => 2002
[connect_error] =>
[errno] => 2002
[error] =>
)
By the looks of it mysqli is ignoring my MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT flag. I was able to successfully connect with PDO using PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false - is there a way to make mysqli work? Unfortunately this is to support legacy application code that still uses mysqli and there is no way to refactor by the time this needs to go live. I believe creating separate CA certs would break the replication connection as they all have different hostnames.
You are passing MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT as the 7th parameter, however that is the socket parameter, flags is the 8th. Try passing a null for the 7th and bumping MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT to the 8th.

php script fails to connect to MySQL with SSL

The script below runs on a Centos server and is trying to connect to a MySQL database on another server which requires SSL parameters. The credentials used in the script work fine using and Microsoft Access DSN connection.
<?php
ini_set ('error_reporting', E_ALL);
ini_set ('display_errors', '1');
error_reporting (E_ALL|E_STRICT);
$pdo = new PDO('mysql:host=99.99.199.199;dbname=dummy1', 'user1', 'pwd1',
array(
PDO::MYSQL_ATTR_SSL_KEY =>'/etc/mysql/ssl/ck.pem',
PDO::MYSQL_ATTR_SSL_CERT=>'/etc/mysql/ssl/cc.pem',
PDO::MYSQL_ATTR_SSL_CA =>'/etc/mysql/ssl/c1.pem'
));
$statement = $pdo->query("SHOW TABLES;");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['_message']);
?>
The code above gives SSL operation failed with code 1 - here is the full message:
Fatal error: Uncaught PDOException: PDO::__construct(): SSL operation
failed with code 1. OpenSSL Error messages: error:14090086:SSL
routines:ssl3_get_server_certificate:certificate verify failed in
/var/www/vhosts/zzzzz.org/httpdocs/zzodbc/dgodbc1.php:10
Stack trace: #0 /var/www/vhosts/zzzzz.org/httpdocs/zzodbc/dgodbc1.php(10): PDO->__construct('mysql:host=99.9...', 'odbc_guil...', 'pwd1',
Array) #1 {main} Next PDOException: SQLSTATE[HY000] [2002] in
/var/www/vhosts/zzzzz.org/httpdocs/zzodbc/dgodbc1.php:10 Stack trace:
#0 /var/www/vhosts/zzzzz.org/httpdocs/zzodbc/dgodbc1.php(10): PDO->__construct('mysql:host=99.9...', 'odbc_guil...', 'pwd1',
Array) #1 {main} thrown in
/var/www/vhosts/zzzzz.org/httpdocs/zzodbc/dgodbc1.php on line 10
I have verified that the credentials, including the SSL parameters with a DSN connection. I have checked that the SSL Keys are correctly located in the /etc/mysql/ssl directory.
Any help to suggest what I'm doing wrong would be good. Thanks.
I may have been going at this in the wrong way....
Since these keys work with ODBC then I think I should be using using odbc_connect and sending the same string as I use with MS access such as
$user = "user";
$pass = "pwd";
$connection = "Driver={MySQL ODBC 5.1 Driver};Server=46.51.178.163;Database=db1;sslca=/etc/mysql/ssl/c1.pem;sslkey=/etc/mysql/ssl/ck.pem;sslcapath=/etc/mysql/ssl/;sslcert=/etc/mysql/ssl/cc.pem";
$con = odbc_connect($connection, $user, $pass);
But to get this to work I need to install a MySQL connector on the server which I'm grappling with at the moment.
I have solved this problem -thanks for all who have helped. This is what I have learned:
SSL keys are connection type specific - so I had keys that worked with ODBC and it was wrong to expect them to work with PDO
ODBC drivers ( php extensions ) need to be installed on the server - they aren't automatically present. Here is an excellent video showing how to do this.
You need command line access to the server to install the driver ( and also to upload the SSL keys to a secure location ) - they are in /etc/mysql/ssl.
I installed the driver in /usr/lib/odbc2/lib rather than in the long folder name in the video. I also installed the in the /usr tree because when I tried the locations in the video I got file not found errors. The two driver files are libmyodbc5a.so and libodbc5w.so. Only the ...5w.so file seems to be required.
Once these files are in place then you need to add an entry to odbcinst.ini in the /etc folder. I used nano so the command line nano odbcinst.ini brings up the file which had a model entry for PostgresSQL. If the server is 64 bit then these are the entries I made in odbcinst.ini:
[mysql537]
Driver64 = /usr/lib/odbc2/lib/libmyodbc5w.so
Setup64 = /usr/lib/odbc2/lib/libmyodbc5w.so
UsageCount = 1
You must have the ...64 paths otherwise the driver isn't found ( i.e Driver64 = NOT Driver= ). I made this mistake first off.
Provided the driver files are found at the paths in odbcinst.ini then things should work. (I thought I needed entries in odbc.ini but I now believe you only need something here if you are using a DSN).
the folder odbc2 was one I created inside /etc/lib which already exists. I did that to avoid any permission issues by creating a new folder.
Here is the code that works ( the connection string is exactly the same as the string used in a Microsoft Access connection ):
<?php
ini_set ('error_reporting', E_ALL);
ini_set ('display_errors', '1');
error_reporting (E_ALL|E_STRICT);
$user = "odbcmmm";
$pass = "999999999";
$connection = "Driver={mysql537};Server=99.99.199.199;Database=db_name;UID=odbc_db_name;PWD=password;sslca=/etc/mysql/ssl/c1.pem;sslkey=/etc/mysql/ssl/ck.pem;sslcapath=/etc/mysql/ssl/;sslcert=/etc/mysql/ssl/cc.pem";
$con = odbc_connect($connection, $user, $pass);
$sql="SELECT Id from stk_item";
$rs=odbc_exec($con,$sql);
if (!$rs) {
exit("Error in SQL");
}
I hope this is useful.

Mysql connection over SSL with PHP mysqli

I'm trying to setup PHP mysqli connection to MariaDB database for two VPS servers and need to encrypt the communications due to it being over public network.
Currently I can connect from the client server to database server via commandline mysql client normally and I have checked via tcpdump that the connection is encrypted. However for some reason I can't figure out the PHP part. It's relatively basic nginx + php5-fpm + mariadb setup but mysql is working on non default port.
Debian Jessie, Php5 5.6.7, Mariadb 10.0.16, nginx 1.6.2
Here's the test script:
<?php
$DB_NAME = '';
$DB_HOST = '111.111.111.111';
$DB_USER = 'username';
$DB_PASS = 'password';
$mysqli = mysqli_init();
if (!$mysqli) {
die('mysqli_init failed');
}
//have tried witha and without the following with multiple variations
$mysqli->ssl_set(NULL, NULL, NULL,'/etc/mysql/ssl/',NULL);
if (!$mysqli->real_connect($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME, 11111, NULL,MYSQLI_CLIENT_SSL )) {
die('Connect Error (' . mysqli_connect_errno() . ') '
. mysqli_connect_error());
}
$query = "SHOW STATUS LIKE 'ssl_cipher'";
$result = $mysqli->query($query) or die($mysqli->error.__LINE__);
if($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
print_r($row);
}
}
else {
echo 'NO RESULTS';
}
mysqli_close($mysqli);
?>
Main error I'm getting without the ssl_set:
2015/07/11 15:58:34 [error] 2857#0: *374 FastCGI sent in stderr: "PHP message: PHP Warning: mysqli::real_connect(): SSL operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in /srv/www/test.php on line 15
PHP message: PHP Warning: mysqli::real_connect(): Cannot connect to MySQL by using SSL in /srv/www/test.php on line 15
PHP message: PHP Warning: mysqli::real_connect(): [2002] (trying to connect via tcp://192.168.130.123:42139) in /srv/www/test.php on line 15
PHP message: PHP Warning: mysqli::real_connect(): (HY000/2002): in /srv/www/test.php on line 15".....
Any ideas would be appreciated. This is really killing me.
Maybe this problem occurs due to the changes made in PHP 5.6. I guess you are using self-signed certificates? If your DB enables peer_name validation by DEFAULT, there is no way to disable this in PHP. So when generating you certificates you have to use the right "Common Name" for each one:
CA: hostname
Server: FQND, e.g. hostname.example.com
Client: somename
The important part is the server certificate where the Common Name has to be the same as the host you are connecting to.
What it looks like is this
SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
My guess is that you don't have the correct CA set up. Some DB systems (like Amazon Web Services RDS) have their own CA file. You're using the capath argument so make sure the PEM files are in that path. If they are, the next thing I would do is switch to the third argument of ssl_set and specify the PEM file directly
$mysqli->ssl_set(NULL, NULL, '/path/to/ca.pem', NULL, NULL);

mysqli_real_connect() getting SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

We just upgraded to php 5.6 from php 5.4, and everything was working fine with our MySQL connecting using MySQLi and SSL.
Our connection looks like:
mysqli_real_connect($db, $host, $username, $password, $database, $port, $socket, MYSQLI_CLIENT_SSL);
mysqli_set_charset($db, "utf8");
Howerver, now when we try and connect to MySQL over SSL using php 5.6 we are getting:
Warning: mysqli_real_connect(): SSL operation failed with code 1.
OpenSSL Error messages: error:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in
/MySQLConnection.php on line 29
Warning: mysqli_real_connect(): Cannot connect to MySQL by using SSL
in /MySQLConnection.php on line 29
Warning: mysqli_real_connect(): [2002] (trying to connect via
tcp://mysql1.ourdomain.com:3306) in /MySQLConnection.php on line 29
Warning: mysqli_real_connect(): (HY000/2002): in /MySQLConnection.php
on line 29
I tried setting:
mysqli_options($db, MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, false);
But that does not help.
UPDATE
I added:
$mysql_certs_path = "/full/path/to/certs/mysql";
mysqli_ssl_set($db, $mysql_certs_path . "/client-key.pem", $mysql_certs_path . "/client-cert.pem", $mysql_certs_path . "/ca-cert.pem", null, null);
And still getting:
Warning: mysqli_real_connect(): SSL operation failed with code 1.
OpenSSL Error messages: error:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in
/MySQLConnection.php on line 31
Warning: mysqli_real_connect(): Cannot connect to MySQL by using SSL in /MySQLConnection.php on line 31
#jww, I have written a post that shares exactly the problems #Justin is facing here. According to my post, the CN of the certificate issued by Google Cloud SQL has the pattern:
CN=project-name:instance-id
Had something similar to this happen to me. When I upgraded PHP to 5.6, it worked. But when I entered:
sudo apt-get install php5-mysqlnd
On Ubuntu 15.04, the SSL to AWS RDS stopped working, even though it worked with the libmysql driver. Running:
sudo apt-get install php5-mysql
Installed the old drivers and it started working again. Near as I can figure out, it's failing the peer-name validation for connecting to RDS. I do not know how to fix that, and because it uses PHP streams for its connection, the settings don't seem to matter that you pass in.
This is a known bug:
https://bugs.php.net/bug.php?id=68344
So I wrote this method, modified from here: How to know if MySQLnd is the active driver?
public function getMySQLIType()
{
$mysqlType = [
'mysql' => false,
'mysqli' => false,
'mysqlnd' => false,
];
if (function_exists('mysql_connect')) {
$mysqlType['mysql'] = true;
}
if (function_exists('mysqli_connect')) {
$mysqlType['mysqli'] = true;
}
if (function_exists('mysqli_get_client_stats')) {
$mysqlType['mysqlnd'] = true;
}
return $mysqlType;
}
If the array returns true for mysqlnd, I disable SSL. If returns false, then I enable it. Thus far, it works. Yes, this is a hack fix but I do not know how to legitimately fix this issue.

php failed to connect to mongodb socket

just set up a fresh development ubuntu 13.04 server with nginx, php-fpm, and mongodb. The following line of code kills all of my scripts that were running great on a production ubuntu 12.10 server
$m = new MongoClient("mongodb://user:pass#/tmp/mongodb-27017.sock/database");
error
Warning: MongoClient::__construct(): php_network_getaddresses:
getaddrinfo failed: Name or service not known in
/var/www/app/php/db.php on line 4
Fatal error: Uncaught exception 'MongoConnectionException'
with message 'Failed to connect to: /tmp/mongodb-27017.sock:0:
php_network_getaddresses: getaddrinfo failed: Name or service not
known' in /var/www/app/php/db.php:4 Stack trace:
0 /var/www/app/php/db.php(4): MongoClient->__construct('mongodb://app...')
1 /var/www/app/admin/loggedin.php(3): require('/var/www/app...')
2 /var/www/app/admin/index.php(1): require('/var/www/app...')
3 {main} thrown in /var/www/app/php/db.php on line 4
I've been toying with this for a day and half and can't figure it out. It works when I connect to localhost but I'd really prefer sockets. any ideas?
The PHP driver does not support passing in the credentials as part of the URI when connecting over Unix Domain Sockets.
You need to pass in the username and password in the $options array (2nd argument).
Ubuntu 14.04, Php 5.59, MongoDB shell version: 2.4.9
I got mine to work by passing the following:
I had to change my connection from $m = new Mongo(); // connect to $m = new Mongo("mongodb://127.0.0.1"); // connect
For some reason it appears that the /etc/hosts file stopped being called localhost for 127.0.0.1 which was throwing off the default mongodb connector so I had to be explicit. Sigh.

Categories