使用 stunnel 加密原本不支持加密的连接

之前在国内的 TX 云主机上安装了 cow 作为连接国外 ss 的跳板。最近由于 Wifi 安全问题被各种关注,就想到 cow 本身是只支持 http 协议的。也就是说,我跟这个代理的任何通信理论上都能被同一 AP 下的其它机器截获。

为了解决这个问题,同时也作为某些公众 Wifi 禁止连接 VPN 的解决方案,我使用了 stunnel 来将 cow 变为支持 https 的代理服务器。

PS:之所以使用 cow 而不是其它的专业代理服务器,是因为在使用 cow 的时候可以无缝连上国外网站,无痛上 Google ,所以。。。

下面说说配置过程:

因为 stunnel 已经发布到了 epel 源中,所以如果你的 CentOS 添加了 epel 源的话,可以直接 yum install stunnel. 如果想自己编译也不困难,下载源码 ./configure && make && make install 即可。下面主要说说配置:

如果你是用的 epel 源的 stunnel ,你会发现安装包已经自动建立了 /etc/stunnel/ 目录,只不过里面啥都没有。所以我们要先创建配置文件:

vim /etc/stunnel/stunnel.conf

写入如下内容:

cert = /etc/stunnel/stunnel.pem
chroot = /var/run/stunnel
setuid = nobody
setgid = nobody
pid = /stunnel.pid
debug = 7
options = NO_SSLv2
fips = no
compression = zlib

[cow]
accept = 8080
connect = 127.0.0.1:7777

其中[cow]段可以多次重复,这样的话可以一个配置文件加密多个程序,使用端口号区分。
注意,fips = no 如果不加上的话会出现这个错误:

FIPS_mode_set: 2D06C06E: error:2D06C06E:FIPS routines:FIPS_module_mode_set:fingerprint does not match

接下来写一个启动脚本放到 /etc/init.d/ 中:

vim /etc/init.d/stunnel
#!/bin/bash
#
# Script to run stunnel in daemon mode at boot time.
#
# Check http://www.gaztronics.net/ for the
# most up-to-date version of this script.
#
# This script is realeased under the terms of the GPL.
# You can source a copy at:
# http://www.fsf.org/copyleft/copyleft.html
#
# Please feel free to modify the script to suite your own needs.
# I always welcome email feedback with suggestions for improvements.
# Please do not email for general support. I do not have time to answer
# personal help requests.

# Author: Gary Myers MIIE MBCS
# email: http://www.gaztronics.net/webform/
# Revision 1.0 - 4th March 2005

#====================================================================
# Run level information:
#
# chkconfig: 2345 99 99
# description: Secure Tunnel
# processname: stunnel
#
# Run "/sbin/chkconfig --add stunnel" to add the Run levels.
# This will setup the symlinks and set the process to run at boot.
#====================================================================

#====================================================================
# Paths and variables and system checks.

# Source function library (It's a Red Hat thing!)
. /etc/rc.d/init.d/functions

# Check that networking is up.
#
[ ${NETWORKING} ="yes" ] || exit 0

# Path to the executable.
#
SEXE=`which stunnel`

# Path to the configuration file.
#
CONF=/etc/stunnel/stunnel.conf

# Check the configuration file exists.
#
if [ ! -f $CONF ] ; then
  echo "The configuration file cannot be found!"
exit 0
fi

CHROOT=`grep '^chroot' /etc/stunnel/stunnel.conf | head -n 1 | sed 's/ //g' | awk -F= '{ print $2 }'`
PIDFILE=`grep '^pid' /etc/stunnel/stunnel.conf | head -n 1 | sed 's/ //g' | awk -F= '{ print $2 }'`
if [ -n "$CHROOT" ]; then
    PIDFILE=$CHROOT/$PIDFILE
fi

# Path to the lock file.
#
LOCK_FILE=/var/lock/subsys/stunnel

#====================================================================

#====================================================================
# Run controls:

prog=$"stunnel"

RETVAL=0

# Start stunnel as daemon.
#
start() {
  if [ -f $LOCK_FILE ]; then
    echo "stunnel is already running!"
    exit 0
  else
    echo -n $"Starting $prog: "
    $SEXE $CONF
  fi

  RETVAL=$?
  [ $RETVAL -eq 0 ] && success
  echo
  [ $RETVAL -eq 0 ] && touch $LOCK_FILE
  return $RETVAL
}


# Stop stunnel.
#
stop() {
  if [ ! -f $LOCK_FILE ]; then
    echo "stunnel is not running!"
    exit 0

  else

    echo -n $"Shutting down $prog: "
    killproc -p $PIDFILE stunnel
    RETVAL=$?
    [ $RETVAL -eq 0 ]
     rm -f $LOCK_FILE
    echo
    return $RETVAL

  fi
}

# See how we were called.
case "$1" in
   start)
  start
  ;;
   stop)
  stop
  ;;
   restart)
  stop
  start
  ;;
   condrestart)
  if [ -f $LOCK_FILE ]; then
     stop
     start
     RETVAL=$?
  fi
  ;;
   status)
  status -p $PIDFILE stunnel
  RETVAL=$?
  ;;
   *)
    echo $"Usage: $0 {start|stop|restart|condrestart|status}"
    RETVAL=1
esac

exit $RETVAL

保存之后不要忘了给执行权限。
接下来就要配置证书了。将你的证书、私钥、CA证书按照如下顺序合并:

cat server.crt server.key ca.crt >/etc/stunnel/stunnel.pem

然后因为大部分人的私钥都是明文的,所以要注意这个文件的权限。如果文件权限比较危险的话 stunnel 会有提示。

chmod 600 /etc/stunnel/stunnel.pem

最后就是创建 stunnel 需要的临时文件夹并赋予权限了。

mkdir -p /var/run/stunnel/
chown nobody:nobody /var/run/stunnel

这个用户和组按照 stunnel.conf 中所写的来授权。
大功告成!来运行一下吧:

service stunnel start

使用 netstat -ntlp 来看看是否正常开始监听端口。如果监听正常就没有问题啦~