精悍的工具-Stunnel搭建跨境加密隧道及代理实现

精悍的工具-Stunnel搭建跨境加密隧道及代理实现

2023年10月12日 3489次阅读 4条评论
clawcloud
expressvpn best vpn
privado vpn
surfshark vpn
private vpn
pia vpn
nord vpn

Stunnel历史悠久、精悍通用,是不可多得的跨境加密隧道建立及代理转发工具,支持的应用层协议众多,包括HTTP/1.1 CONNECT over TLS。官网介绍简明扼要:一个设计用于TLS加密的代理。

Stunnel is a proxy designed to add TLS encryption functionality to existing clients and servers without any changes in the programs' code. Its architecture is optimized for security, portability, and scalability (including load-balancing), making it suitable for large deployments.
Stunnel是一个代理,旨在向现有客户端和服务器添加 TLS 加密功能,而无需对程序代码进行任何更改。其体系结构针对安全性、可移植性和可伸缩性(包括负载平衡)进行了优化,使其适用于大型部署。

不管新旧、好用最重要,更何况运营商(不仅国内)对UDP及其上的Wireguard、QUIC等很难有根本性的策略变化,那我们就用Stunnel这个精悍的工具来搭建基于TCP的跨境通道和机场。Stunnel用于加密隧道建立及转发代理,现有的“教程”多半是不对的、误人子弟的。

1.必备条件

首先以及最后,一台境外VPS,可访问受限站点和服务。

Stunnel可以部署在Linux(包括OpenWRT)、Windows、Android等系统上,所以除了具备公网IP的VPS作为服务端外,对客户端没有要求。由于其采用标准化协议,服务端部署上线后,移动端App(ShadowRocket、Clash等)可以直接添加Socks over TLS等标准化协议节点,无需插件、无需顾虑支持问题。同时,作为采用了OpenSSL的“标准化组件”,Stunnel可直接使用apt、apt-get和yum、opkg通过官方源安装即可,无需下载、编译,OpenWRT中luci 也可直接安装,本体大小不足80k。所以,仅仅用精悍来形容stunnel是过于保守了。

2.VPS上部署stunnel服务端

2.1 安装与环境检查

本文以debian/ubuntu为例。首先,使用apt安装stunnel4。

apt install stunnel4 -y  #apt install stunnel -y #与上一命令等效

stunnel4为stunnel的“新版本”,stunnel在系统中仅仅保留为stunnel4的软链接,所有守护进程名称及服务标识均为stunnel4,如stunnel4.service。

安装完成后,需要检查一下/etc/sysctl.conf和/etc/default/stunnel4两个文件。其中,/etc/sysctl.conf为检查ipv4转发是否开启,取消注释并将设为1后,使用sysctl -p命令即时永久生效。

/etc/default/stunnel4则修改ENABLE=0为ENABLE=1,该文件仅Ubuntu 18.04以下需要检查,较新版本无需操作。

# Julien LEMOINE <[email protected]>  # September 2003    FILES="/etc/stunnel/*.conf"  OPTIONS=""    # Change to one to enable ppp restart scripts  PPP_RESTART=0    # Change to enable the setting of limits on the stunnel instances  # For example, to set a large limit on file descriptors (to enable  # more simultaneous client connections), set RLIMITS="-n 4096"  # More than one resource limit may be modified at the same time,  # e.g. RLIMITS="-n 4096 -d unlimited"  RLIMITS=""

2.2 配置stunnel服务端

stunnel配置文件位于/etc/stunnel/目录下(/etc/default/stunnel4文件已有指明),一般采用stunnel.conf以便于记忆管理。配置文件中的选项和值的定义、说明请参阅老E的前文「不再重复。对应于不同的验证方式选择,分别分享两份样例配置文件。

证书验证方式

采用证书验证配置方式,需要使用OpenSSL生成自签名证书和私钥,stunnel支持pem和p12(pkcs12)两种证书格式,一般我们采用PEM格式,ACSII编码方式便于拷贝粘贴、密钥交换。

openssl req -nodes -new -days 365 -newkey rsa:2048 -x509 -keyout /etc/stunnel/2048key.pem -out /etc/stunnel/2048cert.pem  cd /etc/stunnel && openssl pkcs12 -export -in 2048cert.pem -inkey 2048key.pem -out 2048pks.p12  base64 2048pks.p12 > 2048pks.base64

生成自签名证书后,配置stunnel.conf文件如下:

syslog = no  debug = 3  output = /var/log/stunnel4/stunnel.log  pid = /var/run/stunnel4.pid    [stproxy]  ;client = no    ;connect = [host:]port  accept = 8443    cert = /etc/stunnel/2048cert.pem  key = /etc/stunnel/2048key.pem    ;requireCert = yes  ;CAfile = /etc/stunnel/ccert.pem    ;CApath = /etc/stunnel/certs    protocol = socks  

Stunnel配置文件中至少应包含一项服务/service,用封号(;)作行注释。这里的“[stproxy]”即指定了一项服务,“[stproxy]”以上的为全局配置选项,以下的为stproxy服务配置选项。client指定了该服务是否为客户端,默认为no,因此服务端可直接忽略或删除该行。accept、connect分别指定服务监听地址和端口、链接上级(代理服务端)的监听地址和端口,省略地址表示在所有接口的指定端口上监听,这里我们不使用connect行,由stunnel直接进行socks代理转发。下面两行,在不使用CApath选项的前提下,cert、key分别采用绝对路径指定了证书和私钥文件。

重要:拷贝2048cert.pem文件或其内容,以供客户端对服务端进行验证。TLS体制下,首先是对服务端的验证以避免身份仿冒,其次服务端对客户端的验证是可选的,默认情况下,stunnel关闭了客户端验证,需要通过显式定义requireCert=yes以开启。

最后一行的protocol指定了采用socks协议,我们的目标是搭建socks VPN,因其工作在应用层之下,标准化且适配广泛。以上配置完成后即可启动stunnel4服务。

systemctl start stunnel4.service  #service stunnel4 start  #systemctl status stunnel4.service

PSK预共享密钥验证方式

stunnel同样支持PSK预共享密钥验证方式,除身份验证外,PSK主要用于密钥生成前的数据加密、密钥生成及密钥交换,对应的配置文件中通过ciphers加以指定。

syslog = no   debug = 3   output = /var/log/stunnel4/stunnel.log   pid = /var/run/stunnel4.pid     [stproxy]   ;client = no   ;connect = [host:]port   accept = 8443     ciphers = PSK  PSKsecrets = /etc/stunnel/pskexample.txt    protocol = socks

和证书验证方式相比较,仅仅是更改了两行,ciphers=PSK指定了验证方式为PSK,PSKsecrets则以绝对路径方式指定了存储验证信息的psk文件。psk文件/etc/stunnel/pskexample.txt内容如下:

useridentity:aaabbb...111fff

psk文件内容为identity:presharedkey格式,预共享密钥不能少于32个16进制字符(0-f),最长不超过64个16进制字符。如果存在非16进制字符,stunnel会自动过滤排除。

2.3 误区

  • 服务端模式下,connect选项不是必要的,stunnel具备socks代理转发功能,因此也无需”tun2socks“类的额外工具;
  • 部分服务配置选项也可以作为全局配置选项,作用范围不同,但不能将connect等仅服务选项写到全局模块中(第一个方括号以上);
  • 默认安全等级为2,因此不可使用2048位以下的RSA/DSA密钥;
  • stunnel默认支持双栈,省略IP/HOST时使用”:::port“即开启双栈监听;
  • verify虽然仍可使用,但官方早已申明弃用,应使用verifyPeer、verifyChain以及requireCert;
  • 新手和小白不要随意修改样例文件中的全局配置,如pid等,除非你熟练掌握linux,老E不回答任何相关问题。

3.安装、配置stunnel windows客户端

官方网站下载「」,双击安装。stunnel会请求输入信息以生成证书,每一行都直接回车使用提供的默认值,第一行国家代码默认就是PL,表明了stunnel的“国籍”。安装完成并启动后,stunnel会驻守任务栏,点开任务栏图标,选择『Edit Configuration』即可打开配置文件。

Windows下,stunnel配置文件就位于其安装目录下的config目录下,除配置文件外,还有stunnel预置的和生成的证书文件,以及openssl主配置文件。所有可执行exe、动态链接库文件均位于安装目录下,没有系统盘存留。

配置文件中,除预留开启了gmail相关的服务外,其他均作为示例以分号注释。我们只需在文件末尾添加服务块内容即可。首先,需要将服务端证书拷贝至配置文件同目录下,这里使用了4096cert.pem的文件名称。然后,编辑添加以下服务块内容。

[socksproxy]  client = yes  accept = 10088  connect = server_ip_or_name:8443    ;cert = stunnel.pem  ;key = stunnel.pem    verifyPeer = yes  CAfile = 2048cert.pem

其中,client=yes表明这是客户端(默认为no),accept为监听地址和端口,connect指定连接的远程服务端地址和端口。验证模块中,verifyPeer=yes表示需要对服务端(对端)进行验证,CAfile指定了相对路径的对端证书文件。

确保正确编辑、添加配置后,保存配置文件,在任务栏点开stunnel菜单,选择『Reload Configuration』,这是应该就已经连接成功了。还是使用curl -x 请求google网站进行测试,国家码应该是VPS所在地,本例中是ja。

如有问题,可通过stunnel任务栏菜单选择『Show Log Windows』查阅日志进行分析。

4.客户端直连

这里以iOS ShadowRocket为例,在配置好服务端后就可以直连上网。打开小火箭,点击右上角『+』加号添加节点,点击『类型』(默认为shadowsocks),在协议类型中选择『Socks5 over TLS』后自动返回到『添加节点』,填入stunnel服务端的ip地址、端口后,点击『保存』。这时,移动端就可以直连stunnel服务端了。

这,就是标准化。如果你的app不支持,卸了吧。

5.安全增强

我们可以分析得出在使用证书验证方式时存在很大的安全隐患,如果有人知道了服务端的ip和端口,就可以通过任何支持Socks over TLS的客户端连接服务端,况且总有无聊透顶的人不是?问题的根源在于我们没有配置对客户端的验证。因此,我们需要取消服务端配置文件中以下两行的注释,开启服务端对客户端的验证。

;requireCert = yes   ;CAfile = /etc/stunnel/ccert.pem

同时,需要生成客户端证书和私钥,并上传/拷贝客户端证书至服务端服务端配置文件指定的目录下,并保证文件绝对路径、名称与配置文件指定一致。Shadowrocket支持base64编码的PKCS12格式证书以及证书密码,因此,对于移动端尤其是Shadowrocket有需求的,可在第一步服务端部署即直接采用p12证书,stunnel确定是支持的。

对于证书验证方式下的客户端身份验证,不再展开,仅补充三点:

  • Windows下安装Stunnel过程中会创建证书文件stunnel.pem,可直接使用,取消客户端配置样例文件中的注释后重新加载配置即可;
  • Stunnel配置文件中可采用CApath选项指定对端(们)证书目录,将所有对端证书存储于该目录下并以"证书Hash.0"命名,需注意采用的hash算法应与securityLevel要求匹配;
  • Shadowrocket可在『https解密』处生成2048位CA证书/密钥,系统『通用』下对文件描述确认后安装导入,将该base64编码的p12证书导出后可提取公钥pem,当然也可不提取转为p12格式直接完整拷贝使用。

当然,换成PKS预共享密钥也是可以的,32-64个16进制字符在一定时期内足够强壮,如果混杂0-f之外的无效字符(stunnel会自动剔除),可以为家庭和soho用户提供足够的安全保障,但是,老E发现目前SR尚不支持Stunnel socks over TLS的PSK验证,坚持协议和app选择,就需要放弃移动端直连服务端的功能。