
加密通道
前言
日常工作中,我們經常會有數據傳輸的需求,我相信絕大多數情況下,包括我之前也都是直接使用明文傳輸。如果都是在內網傳輸,安全隱患還算較小,但是有些數據也是需要公網傳輸的,例如多區域多IDC之間的數據傳輸,可能有些許VPN不能打通,但是也有部分數據要互通的情況,此時只能走公網傳輸,如果還走明文傳輸,安全性將大打折扣。那么有沒有軟硬件來支持數據密文傳輸的,答案是有的。
經過調研,我們決定采用Stunnel工具來實現數據的密文傳輸。本文就來簡單介紹下Stunnel工具的使用。
Stunnel介紹

stunnel簡單示意圖
Stunnel是一個自由的跨平台軟件,用於提供全局的TLS/SSL服務。作為一個小巧的跨平台(Unix/Linux和Windows)的開源(GNU)項目,提供了以下2個主要功能:
- 針對本身無法進行TLS或SSL通信的客戶端及服務器,Stunnel可提供安全的加密連接(基於OpenSSL)。
- 針對有訪問限制的局域網,Stunnel提供加密的SSL連接解除防火牆和代理的限制直接和遠端服務器理論上的任何網絡服務連接。我們知道一般局域網都會開放443端口用於加密的HTTP連接,我們可以利用這點用Stunnel和遠程端口443創建一個SSL連接,防火牆和代理會認為這個連接是正常的HTTPS連接而允許通過。
Stunnel配置
Stunnel分為服務端和客戶端,怎么定義服務端和客戶端呢?簡單來說,A要加密訪問B,那么B就是服務端,A是客戶端。stunnel 客戶端不需要證書。stunnel 服務端需要一個證書文件。
以下配置以加密讀取mongo數據為例。
服務端生成證書
Stunnel 在 SSL Http Proxy 服務器是以服務方式運行的,所以需要一個證書文件,unix下可以使用openssl來生成證書。
參考命令:
$ openssl req -new -x509 -days 365 -nodes -config openssl.cnf -out stunnel.pem -keyout stunnel.pem
參數解釋:
- -days 365 #使這個證書的有效期是1年,之后失效,借此可用以來發布許可證書。
- -new #創建一個新的證書
- -x509 #創建一個 X509 證書
- -nodes #這個證書沒有密碼 ,嚴格的情況下就加密了。
- -config openssl.cnf #OpenSSL 使用的配置文件
- -out stunnel.pem #把 SSL 證書寫到哪個文件
- -keyout stunnel.pem #把 SSL key放到這個文件中
Stunnel服務端配置
加密mongo連接。
# more stunnel.conf
setuid = nobody
setgid = nobody
pid = /data/stunnel_server/var/run/stunnel.pid
foreground = yes
debug = 1
output = /data/stunnel_server/var/log/stunnel.log
ciphers = ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256
#只允許使用TLS 1.2
options = NO_SSLv2
options = NO_SSLv3
options = NO_TLSv1
options = NO_TLSv1.1
options = CIPHER_SERVER_PREFERENCE
options = DONT_INSERT_EMPTY_FRAGMENTS
renegotiation = no
cert = /data/stunnel_server/etc/stunnel/stunnel.pem
key = /data/stunnel_server/etc/stunnel/stunnel.pem
client = no
# 下面是要加密的數據庫地址
[mongo01]
accept = 3717
connect = 127.0.0.1:3717
[mongo02]
accept = 3718
connect = 127.0.0.1:3718
Stunnel客戶端配置
# more stunnel.conf
setuid = nobody
setgid = nobody
pid = /data/stunnel_client/var/run/stunnel.pid
foreground = yes
debug = 1
output = /data/stunnel_client/var/log/stunnel.log
cert = /data/stunnel_client/etc/stunnel/stunnel.pem
key = /data/stunnel_client/etc/stunnel/stunnel.pem
client = yes
[mongo01]
accept = 3717
connect = stunnel-serverIP:3717
[mongo02]
accept = 3718
connect =stunnel-serverIP:3718
要注意防火牆策略需要放開3717與3718端口。
Stunnel啟動腳本
以client為例。
# more stunnel_client_proxy.service
[Unit]
Description=SSL tunnel for network daemons
After=network.target
After=syslog.target
[Service]
Type=simple
ExecStart=/data/stunnel_client/bin/stunnel /data/stunnel_client/etc/stunnel/stunnel.conf
ExecStop=/usr/bin/killall -9 stunnel
TimeoutSec=600
Restart=on-failure
PrivateTmp=false
[Install]
WantedBy=multi-user.target
Alias=stunnel_client_proxy.target
加載到系統啟動服務里:
重載系統服務:systemctl daemon-reload
設置開機啟動:systemctl enable *.service
啟動服務:systemctl start *.service
停止服務:systemctl stop *.service
重啟服務:systemctl restart *.service
將server端與client端分別啟動后,就可以在client端加密連接server端的mongo數據庫。
后記

stunnel
加密數據傳輸應該是工作中非常常見的需求,本文也只是拋磚引玉,肯定有更好的辦法,但是選擇適合自己的就可以了,目前筆者所在公司依然是使用的Stunnel方式。
