為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 optionsTo 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';
綜合考慮,基於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 ljk@178.19.39.2
[kai@git-svn ~]$ ssh -MNf -L 172.18.200.23:33065:192.168.1.5:3306 ljk@178.19.39.2
#實驗過程中發現針對一個“中繼主機”實現兩個“本地埠轉發”,會有如下報錯,但是經驗證不影響使用
ControlSocket /home/kai/.ssh/master-kai@178.19.39.2:22 already exists, disabling multiplexin
如此,相關需求人員的MySQL客戶端軟體就只需要更改下對應庫的ip:port,其他都不需改變,以對使用者最小的改變實現了安全性的需求。
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.