MySQL - Enable SSL connection between MySQL hosts using self-signed SSL

MySQL - Enable SSL connection between MySQL hosts using self-signed SSL

Disclaimer:
The information provided in this guide is for educational and informational purposes only. It is provided “as is” without any representations or warranties, express or implied. You are using this information at your own risk. The author assumes no responsibility for any loss, damage, or issues arising from the use or misuse of the content provided.


NOTES:

If a CA does not exist and you do not have a CA certificate, choose one of the host to be a CA host, and use that to generate CA keys and certificates.

In this example, we only have 2 host, both are SQL hosts.  So one of them will be configured for self-signed CA host.  Then will be the CA for itself and the other.


Preparing SSL

On each SQL host, create /etc/mysql/certs, this is where you'll store the CA certificate and the host certificates.

1. Create directory for storying certificates
# sudo mkdir -p /etc/mysql/certs


2. Set permissions and ownership

# sudo chown -R mysql:mysql /etc/mysql

# sudo chmod -R ug+rw /etc/mysql/certs

Certificate Authority (CA) - Self-signed.

Select a host to be the CA (this should be your 'master' if you're setting up for replication over SSL. 
Login there and run these commands.

1. Generate CA private key
sudo openssl genrsa -out /etc/mysql/certs/self-ca-key.pem 2048

2. Generate CA certificate (self-signed)
sudo openssl req -new -x509 -nodes -days 3650 -key /etc/mysql/certs/self-ca-key.pem -out  /etc/mysql/certs/self-ca.pem -subj "/CN=MySQL-CA"

Files:
  1. /etc/mysql/certs/self-ca-key.pem is your CA key. You do not need to copy this to any other host.
  2. /etc/mysql/certs/self-ca.pem is your CA certificate.  You'll need to copy this to other host signed by this.

Generate a Certificate for First Host (MASTER)

1. Create san.cf file.

sudo nano /etc/mysql/certs/master-san.cnf 

Add:
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = <hostname>

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = <hostname>
IP.1  = <IP_address>
Example: hostname=debian-a, IPaddress=192.168.100.1:
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = debian-a

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = debian-a
IP.1  = 192.168.100.1
Save the changes to /etc/mysql/certs/master-san.cnf  file.

2. Create MASTER private key

sudo openssl genrsa -out /etc/mysql/certs/self-master-key.pem 2048

3. Create MASTER certificate signing request (CSR)

sudo openssl req -new -key /etc/mysql/certs/self-master-key.pem -out /etc/mysql/certs/self-master-CSR.pem -config /etc/mysql/certs/master-san.cnf 

4. Sign MASTER certificate with our CA

sudo openssl x509 -req -in /etc/mysql/certs/self-master-CSR.pem -days 3650 -CA /etc/mysql/certs/self-ca.pem -CAkey /etc/mysql/certs/self-ca-key.pem -set_serial 03 -out /etc/mysql/certs/self-master-cert.pem -extensions v3_req -extfile /etc/mysql/certs/master-san.cnf 

5. Set proper permissions:

sudo chown mysql:mysql /etc/mysql/certs/*.pem

sudo chmod 600 /etc/mysql/certs/*-key.pem


Configure MASTER my.cnf file:

1. Edit /etc/mysql/my.cnf on Master

sudo nano /etc/mysql/my.cnf

Add to [mysqld]:
[mysqld]
ssl-ca=/etc/mysql/certs/self-ca.pem
ssl-cert=/etc/mysql/certs/self-master-cert.pem
ssl-key=/etc/mysql/certs/self-master-key.pem

2. Restart MYSQL

sudo systemctl restart mysql


3. Check (sql):

mysql> SHOW VARIABLES LIKE 'have_ssl';


Generate a CSR for Second Host (SLAVE):

These steps are done on the second SQL host (that is not the CA host or master).

1. Create san.cf file.

sudo nano /etc/mysql/certs/slave-san.cnf 

Add:
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = <hostname>

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = <hostname>
IP.1  = <IP_address>
Example: hostname=debian-b, IPaddress=192.168.100.2:
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = debian-b

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = debian-b
IP.1  = 192.168.100.2
Save the changes to /etc/mysql/certs/slave-san.cnf file.

2. Create slave private key

sudo openssl genrsa -out /etc/mysql/certs/self-slave-key.pem 2048

3. Create slave certificate signing request (CSR)

sudo openssl req -new -key /etc/mysql/certs/self-slave-key.pem -out /etc/mysql/certs/self-slave-CSR.pem -config /etc/mysql/certs/slave-san.cnf 


4. Transfer a copy of /etc/mysql/certs/self-slave-CSR.pem and /etc/mysql/certs/slave-san.cnf over to the CA/MASTER.

These are the files you need to send to the CA host.
  1. /etc/mysql/certs/self-slave-CSR.pem is the Certificate Signing Request.
  2. /etc/mysql/certs/slave-san.cnf is the SAN.cf for the slave
Both files are needed to sign and create an SSL certificate on the CA host.

Example using SSH/SCP:
sudo scp /etc/mysql/certs/self-slave-CSR.pem /etc/mysql/certs/slave-san.cnf <username>@<MASTER>:/home/</username>

Let's say the master/CA hostname is debian-a, and the local user is 'alice':
scp /etc/mysql/certs/self-slave-CSR.pem /etc/mysql/certs/slave-san.cnf alice@debian-a:/home/alice

GENERATE  SSL Certificate for SLAVE (on MASTER/CA)

1. Go to "Master" SQL host or the CA host to sign and generate the SSL certifcate:

A. Copy CSR and CNF files to /etc/mysql/certs/:
sudo cp /home/<username>/self-slave-CSR.pem /home/<username>/slave-san.cnf /etc/mysql/certs/

Example:  if the username was 'alice', the home directory should be /home/alice/
sudo cp /home/alice/self-slave-CSR.pem /home/alice/slave-san.cnf /etc/mysql/certs/

B. Sign the certificate on the CA host.

sudo openssl x509 -req -in /etc/mysql/certs/self-slave-CSR.pem -days 3650 -CA /etc/mysql/certs/self-ca.pem -CAkey /etc/mysql/certs/self-ca-key.pem -set_serial 03 -out /etc/mysql/certs/self-slave-cert.pem -extensions v3_req -extfile /etc/mysql/certs/slave-san.cnf

This will sign and generate the SSL certificate file: /etc/mysql/certs/self-slave-cert.pem

C. Prepare to copy files back to the SLAVE.

These files are needed on the SLAVE:
  1. self-slave-cert.pem
  2. self-ca.pem
The slave should not be able to read these files from CA/MASTER's /etc/mysql/certs/ location.  So you need to copy them to /home/<username>/
sudo cp /etc/mysql/certs/self-slave-cert.pem /etc/mysql/certs/self-ca.pem /home/<username>/
sudo chown <username>:<username> /home/<username>/self*.pem

We'll use username, alice, as the example again.
sudo cp /etc/mysql/certs/self-slave-cert.pem /etc/mysql/certs/self-ca.pem /home/alice/
sudo chown alice:alice /home/alice/self*.pem

2. Go back to the SLAVE, and copy the self-ca.pem and self-slave-cert.pem over.
sudo scp <username>@<MASTER>:/home/<username>/self-slave-cert.pem /etc/mysql/certs/
sudo scp <username>@<MASTER>:/home/<username>/self-ca.pem /etc/mysql/certs/

Example: Using username, alice, and MASTER's hostname, debian-a
sudo scp alice@debian-a:/home/alice/self-slave-cert.pem /etc/mysql/certs/
sudo scp alice@debian-a:/home/alice/self-ca.pem /etc/mysql/certs/

3. Set proper permissions:

sudo chown mysql:mysql /etc/mysql/certs/*.pem

sudo chmod 600 /etc/mysql/certs/*-key.pem


CONFIGURE SQL SERVER ON SLAVE

1. Edit /etc/mysql/my.cnf on Slave

sudo nano /etc/mysql/my.cnf

Add to [mysqld]:
[mysqld]
ssl-ca=/etc/mysql/certs/self-ca.pem
ssl-cert=/etc/mysql/certs/self-slave-cert.pem
ssl-key=/etc/mysql/certs/self-slave-key.pem

2. Restart MYSQL

sudo systemctl restart mysql


3. Check (sql):

mysql> SHOW VARIABLES LIKE 'have_ssl';

    • Related Articles

    • MySQL - How to Clone All Data from DONOR MySQL server to another using MySQL Clone Plugin

      Disclaimer: The information provided in this guide is for educational and informational purposes only. It is provided “as is” without any representations or warranties, express or implied. You are using this information at your own risk. The author ...
    • MySQL - Setup multi-threaded replication

      Disclaimer: The information provided in this guide is for educational and informational purposes only. It is provided “as is” without any representations or warranties, express or implied. You are using this information at your own risk. The author ...
    • MySQL - Installing Latest Percona mysql on Debian 12

      Disclaimer: The information provided in this guide is for educational and informational purposes only. It is provided “as is” without any representations or warranties, express or implied. You are using this information at your own risk. The author ...
    • MySQL - Common Command Syntaxes

      Disclaimer: The information provided in this guide is for educational and informational purposes only. It is provided “as is” without any representations or warranties, express or implied. You are using this information at your own risk. The author ...
    • MySQL - How to use mysqldump

      Disclaimer: The information provided in this guide is for educational and informational purposes only. It is provided “as is” without any representations or warranties, express or implied. You are using this information at your own risk. The author ...