MySQL, dünyadaki en popüler özgür yazılım tabanlı ilişkisel veritabanı yönetim sistemidir. Default olarak MySQL sadece lokal bağlantılara izin vermektedir. Eğer uzak bağlantı gereksiniminiz varsa güvenlik bu konudaki en önemli husustur.

Bu dokümanda size Ubuntu 16.04 üzerine MySQL yapılandırılması ve uzak bağlantıları SSL/TLS şifrelemesi ile kabul etme adımlarına değineceğiz.

Gereksinimler

Öncelikle MySQL yapılandırılması ve kullanımına geçmeden önce CloudEOS‘ a kayıt olarak iki adet Ubuntu 16.04 sunucunuzu oluşturmalısınız.

Kuruluma başlamadan önce Ubuntu sunucular için güvenlik açısından sudo yetkilerine sahip bir kullanıcı oluşturmanızı tavsiye ediyoruz.

Yeni Kullanıcı Ekleme

Sisteme size verilen şifre ve root kullanıcısı ile giriş yaptıktan sonra

$ adduser yenikullanici

ile kullanıcı oluşturmuş oluyoruz.

$ usermod -aG sudo yenikullanici

komutu ile de oluşturduğumuz kullanıcıya sudo yetkilerini vermiş olduk. Şimdi MySQL yapılandırma adımlarına bu oluşturduğumuz sudo haklı kullanıcı ile devam edeceğiz.

Oluşturduğunuz ilk makineye ( mysqlSunucu ) sudo haklı kullanıcınız MySQL kurulumu yapmanız gerekmektedir. Bunun ile ilgili Ubuntu 16.04 üzerine MySQL kurulumu makalemizden yararlanabilirsiniz.

Diğer makine client olarak uzak erişim testi için kullanılacaktır.

İkinci makinenize ( mysqlClient ) MySQL client paketlerini kurmalısınız. Bunun için aşağıdaki komutlar size yardımcı olacaktır.

mysqlClient$ sudo apt-get update
mysqlClient$ sudo apt-get install mysql-client

Şuanki SSL/TLS Durumunun Kontrol Edilmesi

Başlamadan önce, şuanki SSL/TLS durumunu MySQL sunucu makinemizde kontrol edeceğiz.

MySQL makinemizde root kullanıcısı ile MySQL alanına giriş yapacağız. Aşağıdaki komutta -h komutu sonrası yazdığımız 127.0.0.1 ile lokal soket dosyası kullanımı yerine TCP ile client bağlantısı yapmaya zorlayacağız. Bu şekilde TCP bağlantıları için SSL durumunu kontrol edebileceğiz.

mysqlSunucusu$ mysql -u root -p -h 127.0.0.1

MySQL kurulumunda belirlediğiniz root şifresi ile karşınıza çıkan şifre adımını geçebilirsiniz.

SSL/TLS değerlerinin durumunu aşağıdaki şekilde görebilirsiniz.

mysql> SHOW VARIABLES LIKE '%ssl%';
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| have_openssl | DISABLED |
| have_ssl | DISABLED |
| ssl_ca | |
| ssl_capath | |
| ssl_cert | |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | |
+---------------+----------+
9 rows in set (0.01 sec)

have_openssl ve have_ssl değerleri gördüğünüz üzere DISABLED olarak işaretlenmiştir. Bunun anlamı SSL işlevi derleniyor ama henüz aktif edilmemiş olduğudur.

Şu anki bağlantı durumumuzu doğrulayalım.

mysql> \s
--------------
mysql Ver 14.14 Distrib 5.7.17, for Linux (x86_64) using EditLine wrapper

Connection id: 30
Current database:
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.7.17-0ubuntu0.16.04.1 (Ubuntu)
Protocol version: 10
Connection: 127.0.0.1 via TCP/IP
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
TCP port: 3306
Uptime: 3 hours 38 min 44 sec

Threads: 1 Questions: 70 Slow queries: 0 Opens: 121 Flush tables: 1 Open tables: 40 Queries per second avg: 0.005
--------------

Yukarıdaki çıktıda belirtildiği gibi SSL bağlantımız için şu an kullanılmamaktadır ve biz TCP üzerinden bağlantı sağladık.

MySQL alanından çıkış yapalım.

mysql> exit

Şimdi güvenli bağlantı için MySQL’ de SSL yapılandırmasına başlayacağız.

SSL/TLS Sertifika ve Key’ lerinin Oluşturulması

MySQL için SSL bağlantılarını aktif etmemiz için ilk olarak uygun sertifika ve key dosyalarını oluşturmamız gerekmektedir. Gerekli dosyaları oluşturmak için aşağıdaki komut size yardımcı olacaktır.

mysqlSunucusu$ sudo mysql_ssl_rsa_setup --uid=mysql

Aşağıdaki gibi bir çıktı ile karşılaşacaksınız.

Generating a 2048 bit RSA private key
...................................+++
.....+++
writing new private key to 'ca-key.pem'
-----
Generating a 2048 bit RSA private key
......+++
.................................+++
writing new private key to 'server-key.pem'
-----
Generating a 2048 bit RSA private key
......................................................+++
.................................................................................+++
writing new private key to 'client-key.pem'
-----

Oluşan dosyaları kontrol edelim.

mysqlSunucusu$ sudo find /var/lib/mysql -name '*.pem' -ls
56740 4 -rw-r--r-- 1 mysql mysql 1078 Mar 17 17:24 /var/lib/mysql/server-cert.pem
256735 4 -rw------- 1 mysql mysql 1675 Mar 17 17:24 /var/lib/mysqlsql/ca-key.pem<^>
256739 4 -rw-r--r-- 1 mysql mysql 451 Mar 17 17:24 /var/lib/mysqlsql/public_key.pem<^>
256741 4 -rw------- 1 mysql mysql 1679 Mar 17 17:24 /var/lib/mysqlsql/client-key.pem<^>
256737 4 -rw-r--r-- 1 mysql mysql 1074 Mar 17 17:24 /var/lib/mysqlsql/ca.pem<^>
256743 4 -rw-r--r-- 1 mysql mysql 1078 Mar 17 17:24 /var/lib/mysqlsql/client-cert.pem<^>
256736 4 -rw------- 1 mysql mysql 1675 Mar 17 17:24 /var/lib/mysqlsql/private_key.pem<^>
256738 4 -rw------- 1 mysql mysql 1675 Mar 17 17:24 /var/lib/mysqlsql/server-key.pem<^>

Son sütun oluşturulan dosya isimleridir. Orta sütunlarda belirtilen MySQL ile doğru grup ve kullanıcılara sahiplik verildiğini görmüş oluyoruz.

Bu dosyalar sertifika yetkisi( ca ile başlayanlar ), MySQL sunucu işlemi( server ile başlayanlar ), ve MySQL client ( client ile başlayanlar ) için key ve sertifika çiftleridir. Ek olarak private_key.pem ve public_key.pem dosyaları MySQL tarafından SSL kullanımadığında güvenli şifre transferi için kullanılmaktadır.

MySQL Sunucusunda SSL Bağlantılarını Aktif Etme

Modern MySQL versiyonları uygun sertifika dosyalarına MySQL veri dizininde sunucu başlarken bakmaktadır. Bu yüzden, SSL’ i aktif etmek için MySQL yapılandırmasını düzenleme ihtiyacı duymamaktayız.

Bunun yerine MySQL servisini yeniden başlatarak gerekli değişiklikleri almasını sağlayalım.

mysqlSunucusu$ sudo systemctl restart mysql

Tekrar yukarıdaki komutu çalıştırarak client sunucunuzun otomatik olarak SSL bağlantısı işlemine onay verdiğini görebiliriz.

mysqlSunucusu$ mysql -u root -p -h 127.0.0.1

Tekrar SSL değerlerine göz atalım.

mysql> SHOW VARIABLES LIKE '%ssl%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | ca.pem |
| ssl_capath | |
| ssl_cert | server-cert.pem |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | server-key.pem |
+---------------+-----------------+
9 rows in set (0.00 sec)

have_openssl ve have_ssl değerlerinin DISABLED yerine YES olarak değiştiğini görebilirsiniz. Ayrıca ssl_ca, ssl_cert, ve ssl_key değerlerinin karşısında oluşturulan sertifika isimlerinin gelmiş olduğunu da göreceksiniz.

Tekrar bağlantı durumunu kontrol edelim.

mysql> \s
--------------
. . .
SSL: Cipher in use is DHE-RSA-AES256-SHA
. . .
Connection: 127.0.0.1 via TCP/IP
. . .
--------------

Burada da göreceğiniz üzere SSL cipher gözükecektir ve bu da güvenli bağlantı için SSL kullanımın başladığı anlamına gelmektedir.

MySQL alanında çıkış yapalım.

mysql> exit

Uzak Kullanıcılar için Güvenli Bağlantı Yapılandırılması

Şu an sunucumuz üzerinde SSL değerine sahibiz ve güvenli uzak bağlantılar için yapılandırmaya başlayabiliriz. Bunun için ihtiyacımız olanlar aşağıdaki gibidir.

  • Uzak bağlantılar için SSL
  • bind to a public interface
  • Uzak bağlantılar için MySQL kullanıcısı oluşturulması
  • Dış bağlantılar için güvenlik duvarının ayarlanması
  • Zorunlu SSL ile Uzak Bağlantıların Yapılandırılması

Zorunlu SSL ile Uzak Erişim Yapılandırılması

Şu anda MySQL sunucumuz, kullanıcıların ( clients ) SSL bağlantılarını kabul edecek şekilde yapılandırıldı. Ancak hala kullanıcıların şifrelenmemiş bağlantılarına da izin verilmektedir.

Bu durumu require_secure_transport seçeneğini açarak düzelteceğiz. Tüm bağlantıların SSL veya lokal Unix soketi ile olmasını gerektirmektedir. Unix soketleri sadece sunucu içinden erişilebilir olduğundan uzak kullanıcıların SSL ile bağlanması aktifleştireceğiz.

İlgili ayarı yapabilmek için /etc/mysql/my.cnf dosyasına giriş yapalım.

mysqlSunucusu$ sudo nano /etc/mysql/my.cnf

Dosya içinde iki adet !includedir satırı bulunmaktadır. Aşağıdaki şekilde bu satırların altına ilgili değişiklikleri yapacağız ve böylece herhangi bir çelişen ayar olması durumunda bu yaptığımız baskın gelecektir.

...

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/

[mysqld]
# Require clients to connect either using SSL
# or through a local socket file
require_secure_transport = ON

Bu satır güvenli bağlantılar için gerekli olan tek ayardır.

Default olarak MySQL lokal bilgisayar üzerindeki bağlantıları karşılamaktadır. Uzak bağlantılar için bind-address’ i ayarlayarak farklı arayüzlerden erişime olanak sağlayacağız.

...

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/

[mysqld]
# Require clients to connect either using SSL
# or through a local socket file
require_secure_transport = ON
bind-address = 0.0.0.0

Daha sonra dosyayı kayıt ederek çıkacağız.

Şimdi sunucumuz üzerinde MySQL servisini yeniden başlatarak değişiklikleri almasını sağlayacağız.

mysqlSunucusu$ sudo systemctl restart mysql

127.0.0.1 yerine 0.0.0.0′ ın dinlendiğini kontrol edelim.

mysqlSunucusu$ sudo netstat -plunt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 4330/mysqld
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1874/sshd
tcp6 0 0 :::22 :::* LISTEN 1874/sshd

Yukarıda görüldüğü üzere 0.0.0.0 ile artık tüm uygun arayüzlerden bağlantılar dinlenmektedir.

Şimdi güvenlik duvarımıza MySQL bağlantılarına izin verecek kuralı tanımlayacağız.

mysqlSunucusu$ sudo ufw allow mysql
Rule added
Rule added (v6)

Uzak MySQL Kullanıcısı Yapılandırılması

Şu anda MySQL sunucumuz uzak bağlantıları dinlemektedir. Ancak şu an dış bilgisayarlardan bağlantı yapabilecek bir kullanıcıya sahip değiliz.

MySQL alanına giriş yapalım.

mysqlSunucusu$ mysql -u root -p

Giriş yaptıktan sonra kullanıcı adı, kullanıcı IP adresi ve kullanıcı şifresi değerlerini girerek kullanıcıyı oluşturalım.

mysql> CREATE USER 'uzakKullanici'@'mysqlClientIPAdresi' IDENTIFIED BY 'uzakKullaniciSifre' REQUIRE SSL;

Aşağıdaki şekilde örnek adında bir veritabanı oluşturup ve oluşturduğumuz bu kullanıcıya bu veritabanı üzerinde gerekli izinleri vereceğiz.

mysql> CREATE DATABASE ornek;
mysql> GRANT ALL ON ornek.* TO 'uzakKullanici'@'mysqlClientIPAdresi';

Yaptığımız değişikliklerin alınmasını sağlayalım. Daha sonrada MySQL alanından çıkış yapalım.

mysql> FLUSH PRIVILEGES;
mysql> exit

Uzak Bağlantı Testi

Şimdi mysqlClient makinemize giriş yaparak başarılı şekilde bağlantı yapıp yapamadığımızı kontrol edelim.

mysqlClient$ mysql -u uzakKullanici -p -h mysqlSunucuIPAdresi

Daha sonra şifre ekranında bu kullanıcı için belirlediğimiz şifreyi girerek MySQL alanına giriş yapacağız.

Şimdi bağlantıların güvenli olup olmadığını kontrol edelim.

mysql> \s
--------------
. . .
SSL: Cipher in use is DHE-RSA-AES256-SHA
. . .
Connection: mysqlSunucuIPAdresi via TCP/IP
. . .
--------------

Daha sonra MySQL alanından çıkış yapalım.

mysql> exit

Şimdi tekrar mysqlClient makinemizde güvenli olmayan bağlantı ile bağlanmayı deneyelim.

mysqlClient$ mysql -u uzakKullanici -p -h mysqlSunucuIPAdresi --ssl-mode=disabled

Aşağıdaki gibi bir hata ile karşılaşmanız gerekmektedir.

ERROR 1045 (28000): Access denied for user 'remote_user'@'mysql_server_IP' (using password: YES)

Gördüğünüz üzere SSL bağlantıları izinli ancak diğer bağlantılar reddedilmektedir.

Şu an MySQL sunucumuz uzak bağlantıların güvenli yapılabilmesi için yapılandırılmıştır. Ancak güvenliği daha ileri seviyeye çıkarmak için birkaç işlem daha yapacağız.

MySQL Bağlantıları Doğrulanma Ayarları ( İsteğe Bağlı )

Şu anda MySQL sunucumuzu kendi kaynakları ile oluşturduğu CA SSL sertifikası ile giriş yapılabilecek şekilde yapılandırılmış olduk. Sunucunun sertifika ve anahtar çifti gelen bağlantılar için yeterli şifreleme sağlamaktadır.

Ekstraları eklemek ve isteğe bağlı ek koruma için ihtiyacımız olanlar aşağıdaki gibidir.

  • Uygun SSL dosyalarının kullanıcı makinesine ( mysqlClient ) aktarılması.
  • Yeni bir kullanıcı ayar dosyası oluşturulması.
  • Uzak kullanıcımızı gerekli güvenilir sertifika ile güncelleme.

Kullanıcı Makinesine Kullanıcı Sertifikalarının Aktarılması

İlk olarak MySQL CA ve kullanıcı sertifika dosyalarını MySQL sunucusunda ( mysqlSunucusu ) yakalamamız ve MySQL kullanıcısına ( mysqlClient ) eklememiz gerekmektedir.

MySQL kullanıcı makinesinde bağlanmak için kullanacağımız bir dizin oluşturacağız.

mysqlClient$ mkdir ~/client-ssl

Sertifika anahtarı hassas olduğundan sadece şu anki kullanıcı erişimi verecek sahiplik düzenlemesini yapacağız.

mysqlClient$ chmod 700 ~/client-ssl

Şimdi sertifika bilgilerini yeni dizine kopyalayacağız.

mysqlSunucusu$ sudo cat /var/lib/mysql/ca.pem
-----BEGIN CERTIFICATE-----

...
...
...

-----END CERTIFICATE-----

BEGIN CERTIFICATE ve END CERTIFICATE satırları dahil çıktıyı kopyalayalım.

MySQL kullanıcı makinesine geçiş yaparak aynı isimde bir dosya oluşturalım.

mysqlClient$ sudo nano ~/client-ssl/ca.pem

mysqlSunucusu makinemizde kopyaladığımız içeriği bu açtığımız dosya içine yapıştıralım ve daha sonra dosyayı kaydederek çıkalım.

Sırası ile benzer işlemleri /var/lib/mysql/client-cert.pem ve /var/lib/mysql/client-key.pem dosyaları içinde yapalım.

mysqlSunucusu$ sudo cat /var/lib/mysql/client-cert.pem
-----BEGIN CERTIFICATE-----

...
...
...

-----END CERTIFICATE-----

Yukarıdaki çıktıyı kopyalayalım. mysqlClient makinemize geçerek kopyalanan içeriği aşağıdaki dosya içine yapıştıralım.

mysqlClient$ sudo nano ~/client-ssl/client-cert.pem
mysqlSunucusu$ sudo cat /var/lib/mysql/client-key.pem
-----BEGIN CERTIFICATE-----

...
...
...

-----END CERTIFICATE-----

Yukarıdaki çıktıyı kopyalayalım. mysqlClient makinemize geçerek kopyalanan içeriği aşağıdaki dosya içine yapıştıralım.

mysqlClient$ sudo nano ~/client-ssl/client-key.pem

Client makinesi şimdi tüm yeterliliklere sahip olmuş oldu. Sıra uzak kullanıcımızı güncellemeye geldi.

Uzak Kullanıcı için Güvenilir CA’ dan Sertifika Gereksinimi

Sunucumuz hala güvenilir CA’ dan kullanıcı sertifikası gereksinimi için ayarlanmadı.

Bunu değiştirmek için MySQL sunucumuz içinde MySQL alanına giriş yapacağız.

mysqlSunucusu$ mysql -u root -p

Giriş yaptıktan sonra uzak kullanıcı için gereksinimleri değiştireceğiz. REQUIRE SSL yerine REQUIRE X509 koşulunu uygulayacağız.

mysql> ALTER USER 'uzakKullanici'@'mysqlClientIPAdresi' REQUIRE X509;

Değişikliklerin alınmasını sağlayalım ve sonra MySQL alanından çıkış yapalım.

mysql> FLUSH PRIVILEGES;
mysql> exit

Bağlanırken Sertifika Doğrulaması Testi

Bağlanırken iki taraf içinde doğrulamanın olduğunu test edelim.

mysqlClient makinemizde ilk olarak kullanıcı sertifikaları olmadan bağlantı kurmayı deneyelim.

mysqlClient$ mysql -u root -p
mysql> mysql -u uzakKullanici -p -h mysqlSunucuIPAdresi
ERROR 1045 (28000): Access denied for user 'uzakKullanici'@'mysqlClientIPAdresi' (using password: YES)

Kullanıcı sertifikası olmadan sunucu bağlantıyı reddetmektedir.

Şimdi ~/client-ssl dizini içinde –ssl-ca, –ssl-cert, ve –ssl-key ile ilgili alanları kullanarak bağlanmaya çalışalım.

mysqlClient$ mysql -u uzakKullanici -p -h mysqlSunucuIPAdresi --ssl-ca=~/client-ssl/ca.pem --ssl-cert=~/client-ssl/client-cert.pem --ssl-key=~/client-ssl/client-key.pem

Başarılı şekilde giriş bu sefer yapabildik. MySQL alanında çıkış yapalım.

mysql> exit

MySQL Kullanıcı Ayar Dosyası Oluşturma

Her bağlantıda sertifika dosyalarını belirtmekten kaçınmak için MySQL kullanıcı ayar dosyası oluşturabiliriz.

Home dizininde ~/.my.cnf dosyasını oluşturacağız.

mysqlClient$ sudo nano ~/.my.cnf

Dosyayı aşağıdaki şekilde düzenleyelim daha sonra kaydederek çıkalım.

[client]
ssl-ca = ~/client-ssl/ca.pem
ssl-cert = ~/client-ssl/client-cert.pem
ssl-key = ~/client-ssl/client-key.pem

Burada ilgili dosyaların nerede bulunduğunu belirtmiş olduk.

Şimdi, bir önceki adımdaki gibi –ssl-ca, –ssl-cert, ve –ssl-key seçenekleri olmadan bağlanmayı deneyelim.

mysqlClient$ mysql -u uzakKullanici -p -h mysqlSunucuIPAdresi

Bağlantı olurken kullanıcı ( mysqlClient ) ve sunucu ( mysqlSunucusu ) makineleri sertifikaları birbirlerine sunacaktır. Her iki taraf uzak sertifikayı kendi lokalindeki CA sertifikası ile doğrulayacaktır.

Bu dokümanda, makalede yazan komutları, çözümleri uygulamak tamamen kullanıcının kendi sorumluluğunda ve insiyatifinde olan bir konudur, mevcut komutların uygulanması ile doğabilecek, oluşabilecek her türlü sorumluluk ve sonuçlar kullanıcının kendisine aittir, CloudEOS’ un bu konuda herhangi bir sorumluluğu bulunmamaktadır.