玩转stunnel:端到端的加密通信
0. 什么是stunnel?
stunnel对不支持TLS/SSL的通信协议进行加密,使得可以在不安全、不可信的网络上实现安全的网络通信。
stunnel主要借助openssl的实现和证书机制。
1. 编译安装
注:stunnel对版本要求比较严格,不同版本的stunnel不能相互通信,强烈建议安装相同版本的stunnel。由于在不同的操作系统上使用包管理安装的stunnel版本也不一致,故而编译安装相同版本的stunnel是最简单的方法。
a. 或下载我编译好的版本(Linux x86_64
):
- stunnel-5.71-x86_64-linux.tar.gz
- sha256sum: e4cb53c6a00c81d3706fbd6a8532c71d4655a0f1fdd7bfaa755be3ca977fc8a2
b. 或手工编译
这是静态编译脚本,参考了stunnel-static:
1
# 1. download stunnel-5.71
2
wget 'https://www.stunnel.org/downloads/stunnel-5.71.tar.gz'
3
4
# 2. decompress
5
tar -xf stunnel-5.71.tar.gz
6
7
# 3. compile
8
cd stunnel-5.71
9
10
# hack
11
sed -i 's/^stunnel_LDFLAGS = /&-all-static /' src/Makefile.in
12
export CFLAGS='-Os -fomit-frame-pointer -pipe'
13
14
./configure \
15
--prefix=/usr/ \
16
--sysconfdir=/etc \
17
--localstatedir=/var \
18
--disable-fips \
19
--disable-shared \
20
--enable-static \
21
--disable-silent-rules
22
23
make
24
25
# 4. make release package: stunnel-5.71-x86_64-linux.tar.gz
26
DIST_NAME="stunnel-5.71-$(uname -m)-linux"
27
mkdir -p "dist/$DIST_NAME"
28
DESTDIR="$PWD/dist/$DIST_NAME" make install
29
cd dist
30
tar -zcvf "${DIST_NAME}.tar.gz" "$DIST_NAME"
2. 安装与配置
2.1 问题假设
局域网A有台计算机提供某种服务xxx,但由于通信协议不支持TLS,不能暴露在互联网上。现在打算从局域网B访问该服务,局域网A和局域网B不能直接连接,而是通过互联网连接。此时需要借助 stunnel的加密通信功能。
a. server stunnel
待保护的网络服务,名叫xxx,在局域网A的IP=192.168.1.10, Port=9000。
stunnel的server端拥有互联网IP是 a.b.c.d,端口是 8000。
b. client stunnel
stunnel的client端可以访问互联网,对局域网A提供转发服务xxx,在局域网B的IP=192.168.1.20,Port=9000
2.2 创建用户stunnel
注:在client/server端同时操作
1
useradd -M -U -s /bin/true -r stunnel
2.3 安装软件
注:在client/server端同时操作
1
tar -xvf stunnel-5.71-x86_64-linux.tar.gz
2
cd stunnel-5.71-x86_64-linux
3
cp -vr * /
2.4 创建自签名证书
a. 在client端操作
1
openssl req -x509 -newkey rsa:4096 -days 7300 -nodes -keyout client.key.pem -out client.crt.pem
拷贝 client.crt.pem
到 server 端的 /etc/stunnel/
b. 在server端操作
1
openssl req -x509 -newkey rsa:4096 -days 7300 -nodes -keyout server.key.pem -out server.crt.pem
拷贝 server.crt.pem
到 client 端的 /etc/stunnel/
2.5 添加配置文件
a. 在client
端操作
创建文件 /etc/stunnel/stunnel.conf
1
; =====================================
2
; Global options
3
; =====================================
4
5
;setuid = stunnel
6
;setgid = stunnel
7
8
foreground = yes
9
10
;debug level: emerg (0), alert (1), crit (2), err (3), warning (4), notice (5), info (6), or debug (7)
11
debug = notice
12
log = append
13
output = /var/log/stunnel/stunnel.log
14
15
cert = /etc/stunnel/client.crt.pem
16
key = /etc/stunnel/client.key.pem
17
18
OCSPrequire = no
19
20
; =====================================
21
; Service
22
; =====================================
23
24
[xxx client]
25
; yes 表示 client端
26
client = yes
27
; 在局域网B的IP=192.168.1.20,Port=9000
28
accept = 192.168.1.20:9000
29
; server端拥有互联网IP是 a.b.c.d,端口是 8000。
30
connect = a.b.c.d:8000
31
sslVersion = TLSv1.3
32
ciphersuites = TLS_AES_256_GCM_SHA384
33
verifyChain = no
34
verifyPeer = yes
35
securityLevel = 3
36
CAfile = /etc/stunnel/server.crt.pem
转化为UTF8 BOM
编码:
1
iconv -t UTF-8 stunnel.conf | sed '1s/^\(\xef\xbb\xbf\)\?/\xef\xbb\xbf/' > stunnel.conf.bom
2
mv stunnel.conf.bom stunnel.conf
设置文件的权限:
1
cd /etc/stunnel/
2
chown stunnel:stunnel *
3
chmod 400 *.pem
4
chmod 644 stunnel.conf
b. 在server
端操作
创建文件 /etc/stunnel/stunnel.conf
1
; =====================================
2
; Global options
3
; =====================================
4
5
;setuid = stunnel
6
;setgid = stunnel
7
8
foreground = yes
9
10
;debug level: emerg (0), alert (1), crit (2), err (3), warning (4), notice (5), info (6), or debug (7)
11
debug = notice
12
log = append
13
output = /var/log/stunnel/stunnel.log
14
15
cert = /etc/stunnel/server.crt.pem
16
key = /etc/stunnel/server.key.pem
17
18
OCSPrequire = no
19
20
; =====================================
21
; Service
22
; =====================================
23
24
[xxx server]
25
; no 表示 server端
26
client = no
27
; server端拥有互联网IP是 a.b.c.d,端口是 8000。
28
accept = a.b.c.d:8000
29
; 在局域网A的服务xxx,IP=192.168.1.10, Port=9000。
30
connect = 192.168.1.10:9000
31
sslVersion = TLSv1.3
32
ciphersuites = TLS_AES_256_GCM_SHA384
33
verifyChain = no
34
verifyPeer = yes
35
securityLevel = 3
36
CAfile = /etc/stunnel/client.crt.pem
转化为UTF8 BOM
编码:
1
iconv -t UTF-8 stunnel.conf | sed '1s/^\(\xef\xbb\xbf\)\?/\xef\xbb\xbf/' > stunnel.conf.bom
2
mv stunnel.conf.bom stunnel.conf
设置文件的权限:
1
cd /etc/stunnel/
2
chown stunnel:stunnel *
3
chmod 400 *.pem
4
chmod 644 stunnel.conf
2.6 配置日志文件
注:在client/server端同时操作
a. 准备日志路径
1
mkdir -p /var/log/stunnel/
2
chown stunnel:stunnel /var/log/stunnel/
3
chmod 644 /var/log/stunnel/
b. 日志轮转
创建文件/etc/logrotate.d/stunnel
1
/var/log/stunnel/*.log {
2
create 0644 stunnel stunnel
3
missingok
4
daily
5
rotate 30
6
compress
7
sharedscripts
8
postrotate
9
pkill --signal SIGUSR1 -f /usr/bin/stunnel
10
endscript
11
}
2.7 添加systemd service文件
注:在client/server端同时操作
创建文件 /etc/systemd/system/stunnel.service
1
[Unit]
2
Description=TLS Tunnel
3
After=network.target
4
After=syslog.target
5
6
[Service]
7
Type=simple
8
User=stunnel
9
Group=stunnel
10
Restart=always
11
RestartSec=30
12
StartLimitInterval=5
13
StartLimitBurst=0
14
ExecStart=/usr/bin/stunnel /etc/stunnel/stunnel.conf
15
16
[Install]
17
WantedBy=multi-user.target
设置开机启动
1
systemctl enable stunnel.service
2
systemctl start stunnel.service
3
systemctl status stunnel.service