1. 程式人生 > >遠端訪問Mysql?教你為資料傳輸再加把安全鎖!

遠端訪問Mysql?教你為資料傳輸再加把安全鎖!

線上業務為了保證資料安全,一般只允許本地或者內網訪問MySQL。但一些特殊情況下,需要通過外網訪問MySQL。此時為了保證許可權最小化開放,首先要做兩方面措施:

一方面需要配置防火牆白名單

iptables -A INPUT -s 1.2.3.4 -p tcp -m tcp –dport 3306 -j ACCEPT

另一方面建立MySQL使用者時限制訪問IP

mysql> CREATE USER ‘testuser’@’1.2.3.4’ IDENTIFIED BY ‘testpass’;

那麼,做到這一步就可以高枕無憂了嗎?如果是的話,文章到此就可以結束了。但是很遺憾,實際上仍然存在安全隱患。MySQL的訪問預設是明文的,與明文的HTTP的容易受到監聽、劫持類似,暴露在外網的MySQL通訊也有可能受到監聽、中間人攻擊等。下面以一個具體例子進行說明。

1 監聽MySQL主從的明文通訊

實現監聽的方案有多種,我們採用了交換機埠映象的方式進行旁路監聽。

準備監聽的機器為xxx.xxx.xxx.83,發起攻擊的機器為xxx.xxx.xxx.109。

實施MySQL主從通訊的監聽時, 無論是監聽主庫還是從庫效果都類似,這裡測試監聽主庫的情況。

1.1 確定要監聽的埠

如果不知道這兩臺機器對應交換機哪個埠,可以先登入交換機,ping然後通過arp快取檢視。

埠

ping之後就能通過arp快取確定埠

ping

最後,確定xxx.xxx.xxx.83即映象源埠為g0/15,xxx.xxx.xxx.109即映象目標埠為g0/1。

1.2 配置埠映象

登入交換機,開始沒有配置映象

<H3C>dis mir

The monitor port has not been configured! <H3C>sys

Password: ************

Enter system view, return to user view with Ctrl+Z.

分別配置映象目標和映象源埠

[H3C]monitor-port g0/1
Succeed! the monitor port has been specified to be Trunk port  and the pvid
changed.
[H3C]mirroring-port g0/15
[H3C]
[H3C]dis mir
Monitor-port:
        GigabitEthernet0/1 
Mirroring-port:
        GigabitEthernet0/15
[H3C]q
<H3C>save
This will save the configuration in the EEPROM memory
Are you sure?[Y/N]y
Now saving current configuration to EEPROM memory
Please wait for a while...
Current configuration saved to EEPROM memory successfully

1.3 監聽明文的主從通訊

在主動監聽的機器xxx.xxx.xxx.109執行

tcpdump host xxx.xxx.xxx.83 -i eth0 -w hello.dump

xxx.xxx.xxx.83配置了MySQL主庫,另外的一臺外網機器xxx.xxx.xxx.104配置了MySQL從庫。並且該主從並未配置SSL加密。測試中利用xxx.xxx.xxx.109成功監聽到MySQL主從的通訊。

下圖為監聽到的MySQL帳號登入,可以得到使用者名稱和加密後的密碼:

ping

對於不復雜的MySQL密碼,可以很容易通過cmd5等網站解密出明文:

MySQL

下圖為監聽到的主從資料:

資料

可以看到,在MySQL主從明文通訊的情況下,可以實現有效的竊聽。

這裡採用的交換機埠映象需要獲得交換機許可權,有一定的實施難度。但在外網通訊中,實際的網路環境非常複雜且不受我們控制,明文通訊仍然有潛在的安全風險。

2 伺服器間安全訪問

那麼如何在伺服器之間的外網通訊中確保MySQL的安全訪問呢?這裡介紹幾種常用方案。

2.1 加密隧道

加密隧道可以將客戶端的網路資料進行加密,然後安全地傳輸到服務端後進行解密還原。以stunnel為例:

首先在客戶端監聽3306埠,並建立加密通訊,連線到遠端的1.2.4.5:8000

/usr/local/stunnel/etc/stunnelclient.conf

sslVersion = TLSv1

CAfile = /usr/local/stunnel/etc/ca-cert.pem

cert = /usr/local/stunnel/etc/clientcert.pem

key = /usr/local/stunnel/etc/clientkey.pem

[mysql]

accept = 127.0.0.1:3306

connect =1.2.4.5:8000

服務端監聽8000埠,並將資料解密後轉發到本機的3306埠

/usr/local/stunnel/etc/stunnelserver.conf

sslVersion = TLSv1

CAfile = /usr/local/stunnel/etc/ca-cert.pem

cert = /usr/local/stunnel/etc/servercert.pem

key = /usr/local/stunnel/etc/serverkey.pem

[mysql]

accept=8000

connect=127.0.0.1:3306

這樣,客戶端訪問本地3306埠實際會訪問到遠端1.2.4.5機器的3306埠,實現了通過加密隧道訪問遠端的MySQL。

優點:無需單獨建立外網的MySQL帳號,對本地訪問透明。

缺點:只能實現從客戶端到服務端的加密訪問,需要額外維護加密隧道服務。

2.2 VPN

VPN可以將外網通訊轉化為虛擬的內網通訊,直接解決外網訪問的安全問題。以OPENVPN為例:

在其中一邊的伺服器搭建服務端,配置內網網段

/etc/openvpn/server.conf

port 1194

proto tcp-server

dev tap

#證書相關

ca /etc/openvpn/ca-cert.pem

cert /etc/openvpn/server.pem

key /etc/openvpn/server.key

dh /etc/openvpn/dh.pem

#指定Server端使用的地址

ifconfig 192.168.10.1 255.255.255.0

#指定客戶端的IP

client-config-dir /etc/openvpn/ccd

在另一邊的伺服器搭建客戶端,發起VPN連結

/etc/openvpn/client.conf

client

dev tap

proto tcp-client

remote 1.2.3.4 1194

#證書相關

ca /etc/openvpn/ca-cert.pem

cert /etc/openvpn/client1-cert.pem

key /etc/openvpn/client1-key.pem

這樣,兩邊的伺服器就建立起虛擬的內網,可以訪問相互的MySQL或者其他服務。

優點:兩邊都可以相互訪問,且不限於訪問某個埠,特別適合異地機房間的內網互通。

缺點:需要額外維護VPN服務。

2.3 MySQL SSL

除了建立加密隧道、加密虛擬網路,還可以直接使用SSL進行MySQL的訪問加密。

2.3.1 SSL證書的生成

首先檢查MySQL是否支援SSL。

mysql> SHOW VARIABLES LIKE ‘have_ssl’;

+—————+———-+ | Variable_name | Value

| +—————+———-+ | have_ssl      | DISABLED |

+—————+———-+ 1 row in set (0.00 sec)

如果輸出如上,說明MySQL支援SSL但未啟用。

SSL證書分多種型別,實際中要根據不同用途來使用服務端或客戶端的證書。

[mysqld]

# 服務端型別SSL證書,用於服務端,或者主從關係中的主庫

ssl-ca=/home/mysql/certs/ca-cert.pem ssl-cert=/home/mysql/certs/server-cert.pem

ssl-key=/home/mysql/certs/server-key.pem

[client]

# 客戶端型別SSL證書,用於客戶端(如命令列工具),或者主從關係中的從庫

ssl-ca=/home/mysql/certs/ca-cert.pem

ssl-cert=/home/mysql/certs/client-cert.pem

ssl-key=/home/mysql/certs/client-key.pem

此外,為了方便統一管理,在同一臺機器可以使用同時支援服務端和客戶端型別的單一SSL證書。只需要生成SSL證書時指定兩種型別的用法或者直接不指定任一種用法。

配置完畢後,檢查下SSL是否已啟用

mysql> SHOW VARIABLES LIKE ‘%ssl%’;

+—————+———————–+

| Variable_name | Value                 |

+—————+———————–+

| have_openssl  | YES                   |

| have_ssl      | YES                   |

| ssl_ca        | /home/mysql/certs/ca-cert.pem  |

| ssl_capath    |                       |

| ssl_cert      | /home/mysql/certs/mysql-cert.pem |

| ssl_cipher    |                       |

| ssl_key       | /home/mysql/certs/mysql-key.pem |

+—————+———————–+

5 rows in set (0.00 sec)

如果輸出如上,說明SSL已正常啟用

2.3.2 require SSL與require X509

為了確保外網訪問的MySQL使用者使用了SSL加密,在生成使用者時可以強制要求REQUIRE SSL或REQUIRE X509:

mysql> CREATE USER ‘testuser’@’1.2.3.4’ IDENTIFIED BY ‘testpass’ REQUIRE SSL;

mysql> CREATE USER ‘testuser’@’1.2.3.4’ IDENTIFIED BY ‘testpass’ REQUIRE X509;

兩者的區別在於,REQUIRE SSL只要求客戶端使用指定ca證書對服務端證書進行驗證,而REQUIRE X509還要求服務端對客戶端證書進行驗證。為了避免中間人攻擊,確保更安全的通訊,一般建議使用REQUIRE X509。

2.3.3 OpenSSL與yaSSL

MySQL可以使用自帶的yaSSL庫進行加密通訊,也可以使用OpenSSL進行加密通訊。具體使用哪種,需要在編譯時指定WITH_SSL:STRING的引數:

bundled (use yassl), yes (prefer os library if present, otherwise use bundled), system

(use os library), </path/to/custom/installation>

為了更好的安全性,可以使用系統自帶的OpenSSL,並及時做好yum/apt更新。

如果考慮不同版本的相容性,那麼建議使用自帶的yaSSL。

比如OpenSSL曾針對CVE-2015-4000的漏洞將DH key的最小值提高到768 bits,而一些舊版本MySQL的DH key使用了512 bits。因為MySQL的預設SSL加密演算法是DHE-RSA-AES256-SHA,如果使用了OpenSSL的MySQL,在不同版本間的訪問可能會出現ERROR 2026的錯誤提示。

2.3.4 監聽基於SSL的主從通訊

配置了SSL加密之後,我們再次嘗試抓取MySQL主從通訊。

發現無法獲取到MySQL主從的登入帳號:

MySQL

此外擷取到的MySQL主從資料也是亂碼:

可以看到,在MySQL主從經過SSL加密的情況下,無法實現有效竊聽。

3 本地安全訪問

3.1 SSH隧道

一般我們都需要SSH方式從本地訪問遠端伺服器,這時可以建立SSH隧道來訪問遠端伺服器的特定埠。

如使用SecureCRT的埠轉發功能(Putty也類似),將本地3306埠轉發到伺服器的3306埠:

SSH

如果習慣使用navicat這類工具,可以使用自帶的SSH隧道功能(注意舊版可能要將私鑰轉換成ppk格式):

navicat

3.2 phpmyadmin+HTTPS

如果習慣使用phpmyadmin的web方式訪問MySQL,那麼只需要將訪問方式統一為HTTPS:

server
{
listen 80;
server_name phpmyadmin.example.com;
#使用HSTS強制把HTTP跳轉到HTTPS
add_header Strict-Transport-Security “max-age=31536000 “;
……
}

server
{
listen 443 ssl http2;
server_name phpmyadmin.example.com;
#配置服務端SSL證書
ssl on;
ssl_certificate /etc/letsencrypt/live/phpmyadmin.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ phpmyadmin.example.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
……
}

4 總結

MySQL的資料安全是一個非常大的課題,其中外網間的安全通訊往往容易被忽略。而當前隨著HTTPS /SMTPS/POP3S/IMAPS的逐步流行,各種基於TCP、UDP的加密通訊方案也會越來越多地應用到線上業務中。本文針對伺服器間/本地到伺服器的一些訪問MySQL的場景介紹了幾種加密通訊方案,希望能給到大家一些思路,並結合自己實際需要來使用MySQL的加密訪問。

文章來自微信公眾號:運維軍團