爲MySQL設置安全的遠程連接

需求:開發、測試部門需要對準生產和生產數據庫進行遠程訪問。

有一陣子,是直MySQL層面接授予最小權限,並限制只允許從公司出口ip訪問;iptables層面也是針對數據庫端口只允許公司出口ip訪問。

但是這個樣子終究覺得不夠放心。後來研究了下MySQL的登錄過程(wireshark抓包和參考官方文檔),雖然說MySQL實現的登錄機制(這裏有機會單獨說)基本不存在泄露密碼的風險(理論上存在被破解的可能,但是也會相當費勁),但是登錄之後的SQL語句和執行結果的傳輸卻都是明文傳輸的。
這對於運維來說是不可容忍的,必須搞加密。

一開始打算通過MySQL原生的ssl來實現:
大致研究了下:
首先檢查服務器是否支持ssl,

mysql> show global variables like '%ssl%';      
+---------------+----------+
| Variable_name | Value    |
+---------------+----------+
| have_openssl  | DISABLED |
| have_ssl      | DISABLED |

## have_openssl is alias of have_ssl

YES if mysqld supports SSL connections, NO if not. DISABLED indicates that the server was compiled with SSL support, but was not started with the appropriate --ssl-xxx options

To use SSL connections between the MySQL server and client programs, your system must support either OpenSSL or yaSSL:

• MySQL Enterprise Edition binary distributions are compiled using OpenSSL. It is not possible to use yaSSL with MySQL Enterprise Edition.
• MySQL Community Edition binary distributions are compiled using yaSSL.
• MySQL Community Edition source distributions can be compiled using either OpenSSL or yaSSL

To determine whether your server was compiled using OpenSSL, test the existence of any of those variables. For example, this statement returns a row if OpenSSL was used and an empty result if yaSSL was used:

SHOW STATUS LIKE 'Rsa_public_key';

如何配置:
參見https://dev.mysql.com/doc/refman/5.6/en/using-secure-connections.html
參見https://dev.mysql.com/doc/refman/5.6/en/creating-ssl-files-using-openssl.html

綜合考慮,基於mysql(5.7之前)原生支持的ssl配置安全連接,需要手動在server和client端生成對應的證書,公鑰、私鑰等文件:一是服務端配置步驟較爲繁瑣;二是客戶端的配置也要增加用戶證書及私鑰等文件,還得算上指導相關修改配置的時間,感覺有些小題大做了。
5.7的ssl配置及性能損失參考


之前就知道ssh能實現端口轉發,正好藉此需求深入研究一番

最終解決方案:
通過ssh的端口轉發,簡單說就是:

  1. 讓一臺本地server和遠程server間建立一個長ssh連接(ssh隧道),該隧道openssh有保活機制,默認300s會發送noop保持存活(抓包觀察到)
  2. 同時openssh會在本地(內網)server監聽一個端口,目標是該本地IP:port的流量通過ssh隧道經由遠程server轉發到對應的目標server的內網IP:port
  3. 這樣,數據庫只需要給遠程賬號授權該中間server的內網ip即可。即在公網上的傳輸是經過ssh隧道保證了安全

配置步驟

  1. [kai@git-svn ~]$ cat .ssh/config 
    ControlPath ~/.ssh/master-%r@%h:%p
    ControlMaster auto

    上述配置詳細信息,參考man ssh_config

  2. 
    [kai@git-svn ~]$ ssh -MNf -L 172.18.200.23:33062:192.168.1.2:3306 [email protected]
    [kai@git-svn ~]$ ssh -MNf -L 172.18.200.23:33065:192.168.1.5:3306 [email protected] 

#實驗過程中發現針對一個“中繼主機”實現兩個“本地端口轉發”,會有如下報錯,但是經驗證不影響使用
ControlSocket /home/kai/.ssh/[email protected]:22 already exists, disabling multiplexin


如此,相關需求人員的MySQL客戶端軟件就只需要更改下對應庫的ip:port,其他都不需改變,以對用戶最小的改變實現了安全性的需求。

[**關於SSH ControlMaster and ControlPath:**](https://ldpreload.com/blog/ssh-control)  
[參考1](https://www.reddit.com/r/git/comments/3h7hbm/can_one_maintain_a_constant_ssh_connection_to_a/#content)

> You want SSH's ControlMaster feature. I wrote a blog post about using it with git a little while back. Briefly, you set a ControlPath so all your SSH processes know how to find each other, and then you make one connection as a "master" that stays around forever. Every other SSH will check for an existing, shared connection before making a new one, which lets them skip authentication.

>You may also want to use -o ServerAliveInterval=30 or something on the master, which sends a keep-alive packet over the SSH connection every 30 seconds. Depending on your network and server configuration, you may need this to prevent the connection from timing out.

---
[全局參考1](http://www.ruanyifeng.com/blog/2011/12/ssh_port_forwarding.html)  
[全局參考2](http://blogs.perl.org/users/smylers/2011/08/ssh-productivity-tips.html)  
[全局參考3 OpenSSH/Cookbook/Multiplexing](https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章