MySQL服務器開啓SSL加密功能html
咱們知道,MySQL5.7以前版本,安全性作的並不夠好,好比安裝時生成的root空密碼帳號、存在任何用戶都能鏈接上的test庫等,致使數據庫存在較大的安全隱患。好在5.7版本對以上問題進行了一一修復。與此同時,MySQL 5.7版本還提供了更爲簡單SSL安全訪問配置,且默認鏈接就採用SSL的加密方式,這讓數據庫的安全性提升一個層次。java
IP | 主機名 | 說明 |
---|---|---|
192.168.1.101 | node1 | mysql服務端 |
192.168.1.102 | node2 | mysql客戶端 |
SSL(Secure Socket Layer:安全套接字層)利用數據加密、身份驗證和消息完整性驗證機制,爲基於TCP等可靠鏈接的應用層協議提供安全性保證。node
若是用戶的傳輸不是經過SSL的方式,那麼其在網絡中數據都是以明文進行傳輸的,而這給別有用心的人帶來了可乘之機。因此,如今不少大型網站都開啓了SSL功能。一樣地,在咱們數據庫方面,若是客戶端鏈接服務器獲取數據不是使用SSL鏈接,那麼在傳輸過程當中,數據就有可能被竊取。mysql
官方安裝文檔linux
root@node1 19:58: [(none)]> show global 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) root@node1 19:58: [(none)]> status; -------------- mysql Ver 14.14 Distrib 5.7.22, for linux-glibc2.12 (x86_64) using EditLine wrapper Connection id: 4 Current database: Current user: root@localhost SSL: Not in use Current pager: stdout Using outfile: '' Using delimiter: ; Server version: 5.7.22-log MySQL Community Server (GPL) Protocol version: 10 Connection: Localhost via UNIX socket Server characterset: utf8mb4 Db characterset: utf8mb4 Client characterset: utf8 Conn. characterset: utf8 UNIX socket: /data/mysql/mysql3306.sock Uptime: 6 min 9 sec Threads: 1 Questions: 14 Slow queries: 0 Opens: 109 Flush tables: 1 Open tables: 103 Queries per second avg: 0.037 -------------- root@node1 19:59: [(none)]>
由上可看出:目前MySQL服務沒有開啓SSL功能;算法
yum install openssl -y
systemctl stop mysqld
安裝SSL,開啓SSL鏈接sql
[root@node1 mysql]# ./bin/mysql_ssl_rsa_setup 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' ----- [root@node1 mysql]#
典型的選項是--datadir
指定建立文件的位置,以及--verbose
查看mysql_ssl_rsa_setup
執行的openssl
命令 。shell
當運行完這個命令後,默認會在$datadir
目錄下生成如下pem
文件,這些文件就是用於啓用SSL
功能的:數據庫
[root@node1 data]# ll *.pem -rw------- 1 root root 1675 3月 8 18:34 ca-key.pem # CA私鑰 -rw-r--r-- 1 root root 1107 3月 8 18:34 ca.pem # 自籤的CA證書,客戶端鏈接也須要提供 -rw-r--r-- 1 root root 1107 3月 8 18:34 client-cert.pem # 客戶端鏈接服務器端須要提供的證書文件 -rw------- 1 root root 1675 3月 8 18:34 client-key.pem # 客戶端鏈接服務器端須要提供的私鑰文件 -rw------- 1 root root 1679 3月 8 18:34 private_key.pem # 私鑰/公鑰對的私有成員 -rw-r--r-- 1 root root 451 3月 8 18:34 public_key.pem # 私鑰/公鑰對的共有成員 -rw-r--r-- 1 root root 1107 3月 8 18:34 server-cert.pem # 服務器端證書文件 -rw------- 1 root root 1675 3月 8 18:34 server-key.pem # 服務器端私鑰文件 [root@node1 data]# chown mysql:mysql *.pem # 到data_dir目錄下修改.pem文件的所屬權限用戶爲mysql [root@node1 data]# ll *.pem -rw------- 1 mysql mysql 1675 3月 8 18:34 ca-key.pem -rw-r--r-- 1 mysql mysql 1107 3月 8 18:34 ca.pem -rw-r--r-- 1 mysql mysql 1107 3月 8 18:34 client-cert.pem -rw------- 1 mysql mysql 1675 3月 8 18:34 client-key.pem -rw------- 1 mysql mysql 1679 3月 8 18:34 private_key.pem -rw-r--r-- 1 mysql mysql 451 3月 8 18:34 public_key.pem -rw-r--r-- 1 mysql mysql 1107 3月 8 18:34 server-cert.pem -rw------- 1 mysql mysql 1675 3月 8 18:34 server-key.pem [root@node1 data]#
要爲服務器啓用加密鏈接,請在my.cnf 文件中使用這些行啓動它,根據須要更改文件名:安全
[mysqld] ssl-ca=ca.pem ssl-cert=server-cert.pem ssl-key=server-key.pem
systemctl start mysqld
要查看SSL證書的內容(例如,要檢查其有效的日期範圍),請直接調用 openssl:
openssl x509 -text -in ca.pem openssl x509 -text -in server-cert.pem openssl x509 -text -in client-cert.pem
也可使用如下SQL語句檢查SSL證書過時信息:
root@node1 13:36: [(none)]> SHOW STATUS LIKE 'Ssl_server_not%'; +-----------------------+--------------------------+ | Variable_name | Value | +-----------------------+--------------------------+ | Ssl_server_not_after | Mar 5 12:03:45 2029 GMT | | Ssl_server_not_before | Mar 8 12:03:45 2019 GMT | +-----------------------+--------------------------+ 2 rows in set (0.01 sec) root@node1 13:36: [(none)]>
要爲MySQL賬戶指定SSL/TLS相關選項,請使用REQUIRE指定一個或多個tls_option值的子句 。
REQUIRE選項順序可有可無,但不能指定選項兩次。該AND關鍵字是可選之間REQUIRE選擇。
CREATE USER容許這些 tls_option值:
CREATE USER 'username'@'localhost' REQUIRE NONE;
客戶端默認嘗試創建安全鏈接。對於具備REQUIRE NONE此功能的客戶端,若是沒法創建安全鏈接,則鏈接嘗試將回退到未加密的鏈接。要求加密鏈接,客戶端只需指定 --ssl-mode=REQUIRED 選項; 若是沒法創建安全鏈接,則鏈接嘗試失敗。
NONE若是未REQUIRE指定與SSL相關的選項,則爲默認值 。
SSL
告知服務器僅容許該語句命名的全部賬戶的加密鏈接。
CREATE USER 'username'@'localhost' REQUIRE SSL;
客戶端默認嘗試創建安全鏈接。對於具備的賬戶,REQUIRE SSL若是沒法創建安全鏈接,則鏈接嘗試將失敗。
CREATE USER 'username'@'localhost' REQUIRE X509;
對於賬戶REQUIRE X509,客戶必須指定鏈接--ssl-key 和--ssl-cert選項。(建議但不要求 --ssl-ca也要指定,以即可以驗證服務器提供的公共證書。)這是正確的ISSUER ,SUBJECT由於這些 REQUIRE選項意味着要求X509。
user1
並強制普通用戶必須使用SSL鏈接數據庫root@node1 20:12: [(none)]> grant select,insert,update,delete on *.* to 'user1'@'%' identified by 'rootroot'; Query OK, 0 rows affected, 1 warning (0.01 sec) root@node1 20:14: [(none)]> flush privileges; Query OK, 0 rows affected (0.01 sec) root@node1 20:22: [(none)]> alter user 'user1'@'%' require ssl; Query OK, 0 rows affected (0.00 sec) root@node1 20:14: [(none)]> exit Bye
使用--ssl-mode=VERIFY_CA或 --ssl-mode=VERIFY_IDENTITY,客戶端須要加密鏈接,並對服務器CA證書和(與VERIFY_IDENTITY)證書 中的服務器主機名執行驗證。
對於上面強制使用ssl鏈接的用戶,若是不是使用ssl鏈接的就會報錯,像下面這樣:
[root@node1 mysql]# mysql -h 192.168.1.101 -uuser1 -p --ssl-mode=DISABLED WARNING: --ssl is deprecated and will be removed in a future version. Use --ssl-mode instead. Enter password: ERROR 1045 (28000): Access denied for user 'user1'@'node1' (using password: YES) [root@node1 mysql]# mysql -h 192.168.1.101 -uuser1 -p # 默認開啓SSL Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 13 Server version: 5.7.22-log MySQL Community Server (GPL) Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. user1@node1 20:24: [(none)]> show global variables like '%ssl%'; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | have_openssl | YES | | have_ssl | YES | # 已經開啓了SSL | 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) user1@node1 20:19: [(none)]> status; -------------- mysql Ver 14.14 Distrib 5.7.22, for linux-glibc2.12 (x86_64) using EditLine wrapper Connection id: 6 Current database: Current user: user1@node1 SSL: Cipher in use is DHE-RSA-AES256-SHA # 表示該用戶是採用SSL鏈接到mysql服務器上的,若是不是ssl,那麼會顯示「Not in use「 Current pager: stdout Using outfile: '' Using delimiter: ; Server version: 5.7.22-log MySQL Community Server (GPL) Protocol version: 10 Connection: 192.168.1.101 via TCP/IP Server characterset: utf8mb4 Db characterset: utf8mb4 Client characterset: utf8 Conn. characterset: utf8 TCP port: 3306 Uptime: 11 min 15 sec Threads: 1 Questions: 27 Slow queries: 0 Opens: 118 Flush tables: 1 Open tables: 111 Queries per second avg: 0.040 -------------- user1@node1 20:19: [(none)]>
mysql服務端添加祕鑰登錄:
root@node1 11:52: [(none)]> alter user 'java'@'%' require x509;
把客戶端證書和私鑰:server-cert.pem
和server-key.pem
或者服務端證書和私鑰:client-cert.pem
和client-key.pem
,從mysql服務端服務器複製到客戶端服務器,而後使用ssl+祕鑰登陸:
[root@NUC-9 ~]# mysql -h 192.168.0.148 -ujava -prootroot --ssl-mode=REQUIRED -e "show databases;" mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 1045 (28000): Access denied for user 'java'@'192.168.0.68' (using password: YES) [root@NUC-9 ~]# mysql -h 192.168.0.148 -ujava -prootroot --ssl-mode=REQUIRED --ssl-cert=server-cert.pem --ssl-key=server-key.pem -e "show databases;" mysql: [Warning] Using a password on the command line interface can be insecure. +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | test | +--------------------+ [root@NUC-9 ~]# mysql -h 192.168.0.148 -ujava -prootroot --ssl-mode=REQUIRED --ssl-cert=client-cert.pem --ssl-key=client-key.pem -e "show databases;" mysql: [Warning] Using a password on the command line interface can be insecure. +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | test | +--------------------+ [root@NUC-9 ~]#
直接安裝tshark
[root@node1 ~]# yum install tshark 已加載插件:fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com 沒有可用軟件包 tshark。 錯誤:無須任何處理
[root@node1 ~]# yum whatprovides *tshark* 已加載插件:fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com 1:bash-completion-extras-2.1-11.el7.noarch : Additional programmable completions for Bash 源 :epel 匹配來源: 文件名 :/usr/share/bash-completion/completions/tshark wireshark-1.10.14-16.el7.i686 : Network traffic analyzer 源 :base 匹配來源: 文件名 :/usr/sbin/tshark 文件名 :/usr/share/wireshark/tshark.html 文件名 :/usr/share/man/man1/tshark.1.gz wireshark-1.10.14-16.el7.x86_64 : Network traffic analyzer 源 :base 匹配來源: 文件名 :/usr/sbin/tshark 文件名 :/usr/share/wireshark/tshark.html 文件名 :/usr/share/man/man1/tshark.1.gz wireshark-1.10.14-16.el7.x86_64 : Network traffic analyzer 源 :@base 匹配來源: 文件名 :/usr/sbin/tshark 文件名 :/usr/share/wireshark/tshark.html 文件名 :/usr/share/man/man1/tshark.1.gz
發現wireshark包有tshark命令;
[root@node1 ~]# yum install wireshark -y 已加載插件:fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com 軟件包 wireshark-1.10.14-16.el7.x86_64 已安裝而且是最新版本 無須任何處理 [root@node1 ~]# yum install wireshark -y
user2
不強制使用SSL鏈接數據庫root@node1 20:12: [(none)]> grant select,insert,update,delete on *.* to 'user2'@'%' identified by 'rootroot'; Query OK, 0 rows affected, 1 warning (0.01 sec) root@node1 20:14: [(none)]> flush privileges; Query OK, 0 rows affected (0.01 sec)
在客戶端機器(192.168.1.102)上鍊接數據庫並進行show database
操做,使用--ssl-mode=DISABLED
關閉SSL
[root@node2 ~]# mysql -h 192.168.1.101 -uuser2 -prootroot --ssl-mode=DISABLED -e "show databases;" mysql: [Warning] Using a password on the command line interface can be insecure. +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ [root@node2 ~]#
同時在MySQL服務器端(192.168.1.101)上用tshark進行抓包:
[root@node1 ~]# tshark -i ens33 -Y 'tcp.port == 3306 && mysql.query' -T fields -e frame.time -e 'ip.src' -e 'mysql.query' Running as user "root" and group "root". This could be dangerous. Capturing on 'ens33' "Mar 11, 2019 11:07:20.651700295 CST" 192.168.0.68 select @@version_comment limit 1 "Mar 11, 2019 11:07:20.652402246 CST" 192.168.0.68 show databases
在客戶端機器(192.168.1.102)上鍊接數據庫並進行insert操做,使用--ssl-mode=REQUIRED指定SSL
[root@node2 ~]# mysql -h 192.168.1.101 -uuser2 -prootroot --ssl-mode=REQUIRED -e "show databases;" mysql: [Warning] Using a password on the command line interface can be insecure. +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ [root@node2 ~]#
同時在MySQL服務器端(192.168.1.101)上再次用tshark進行抓包:
[root@node1 ~]# tshark -i ens33 -Y 'tcp.port == 3306 && mysql.query' -T fields -e frame.time -e 'ip.src' -e 'mysql.query' Running as user "root" and group "root". This could be dangerous. Capturing on 'ens33'
服務器配置:CPU:32核心 內存:128G 磁盤:SSD
爲了儘可能準確測試QPS,採用全內存查詢,由於咱們線上熱點數據基本都在內存中;按照併發線程數分類:1線程、4線程、8線程、16線程、24線程、32線程、64線程;
具體數據以下:
從測試數據能夠發現,開啓SSL後,數據庫QPS平均下降了23%左右,相對仍是比較影響性能的。從SSL實現方式來看,創建鏈接時須要進行握手、加密、解密等操做。因此耗時基本都在創建鏈接階段,這對於使用短連接的應用程序可能產生更大的性能損耗,好比採用PHP開發。不過若是使用鏈接池或者長鏈接可能會好許多。
一、MySQL5.7默認是開啓SSL鏈接,若是強制用戶使用SSL鏈接,那麼應用程序的配置也須要明確指定SSL相關參數,不然程序會報錯。
二、雖然SSL方式使得安全性提升了,可是相對地使得QPS也下降23%左右。因此要謹慎選擇:
2.一、對於很是敏感核心的數據,或者QPS原本就不高的核心數據,能夠採用SSL方式保障數據安全性;