使用 Docker 封印 EasyConnect

2020-09-26 ⏳3.6分钟(1.5千字) 🕸️

深信服的 EasyConnect 客户端非常垃圾,不但会在开机时以 root 自动启动,还会往系统安装自己的 CA 根证书。这给使用者带来极大的安全隐患。今天分享一种方案,将其封印到 Docker 容器里,消除隐患。

安全隐患

我发现该软件有三个问题。

第一,依赖已经废弃的系统特性

如果你在新版的 macOS 上打开 EasyConnect,你会收到如下提醒:

依赖已经废弃的系统特性

而在最新的 macOS Big Sur 上,该软件已经无法正常工作。

第二,偷偷安装自己的 CA 根证书

偷偷安装自己的 CA 根证书

跟深信服沟通后我们得到如下达复:

该受信任根证书签发给了本地回环地址 127.0.0.1 一张证书,用于用户使用浏览器登陆 SSLVPN 过程中, 浏览器和SSLVPN客户端之间建立安全的https通信时使用。

在系统中导入该受信任根证书,是为了消除证书告警,为用户提供更好的使用体验

避免无法正常使用浏览器方式登陆SSLVPN,无其他特殊用途。

并得到如下承诺:

1.该Sangfor Technologies Inc.根证书私钥信息保存在内网,并由专人保管,不会泄露出去

2.该Sangfor Technologies Inc.根证书只用于颁发给127.0.0.1 用于SSLVPN BS登陆使用,不会签发其它证书做其他用途

不管你信不信,反正我是不信的。请务必删除此 CA 证书

第三,配置开机自动启动的进程

进程名叫 EasyMonitor,以 root 帐号启动,你的一举一动它都有能力监听。你还不能关掉,关掉就无法使用 VPN 功能了。

开机自启的 EasyMonitor 进程

反馈给深信服,还不知道什么时候改;所在公司更是不太可能更换 VPN 服务商。怎么办?只有自己动手了。

Docker 运行 X11 程序

方案也是非常简单,在 Docker 容器里同时运行 EasyConnect 和 Socks5 代理。然后配置宿主机的工具,在需要访问公司内网的时候走 Socks5 代理就行。

这样就可以把 EasyConnect 隔离到一个受控的容器环境,再也不用担心它做恶了。

实现这个目标,需要克服一个问题——如何在 Docker 中运行 X11 程序。

我们知道,macOS 并非原生支持 Docker。我们所用的 Docker 也是一台 Linux 虚拟机。在 Docker 中运行 mysql/redis/nginx 这类的命令行程序是没有问题的;但 Firefox/EasyConnect 这样依赖 X11 图形系统的程序能不能在 Docker 中运行呢?答案是肯定的。

简单 Google 了一下,我找到了一篇文章1

X11 系统天生就支持远程显示。简单来说,机器 A 上的 Firefox 进程可以把显示的内容通过网络传给机器 B 并在 B 的屏幕上展示。macOS 可以运行 X11 显示服务器为 docker 中的程序绘制 GUI 界面。

为此,需要安装 XQuartz2,这是苹果官方的 X11 显示服务。安装后还得开启网络服务支持。

开启 XQuartz 的网络支持

最后需要注销当前用户并重新登录才能生效。我们先实验一下 XQuartz 的功能。我们以 Firefox 为例:

# 让 XQuartz 接受来自本机 IP 的网络请求
xhost + ${你的本机IP}

# 在 docker 中运行 Firefox 并将显示请求转发给 XQuartz
docker run -e DISPLAY=${你的本机IP}:0 jess/firefox

不出意外的话,你会看到 Firefox 的界面。但是,这个 Firefox 界面比较粗糙,没有适配 macOS 的高清屏。苹果已经不再为 XQuartz 开发新功能。要啥自行车。

Docker 运行 EasyConnect

调通 docker + XQuartz 组合后,我们就要处理 EasyConnect 的问题了。

在这里我要特别感谢 Hagb 同学,他慷慨地跟大家分享了自己在 EasyConnect 容器化的实战经验,并开放了源码3

Hagb 同学还为大家准备好了 docker 镜像,大家可以在其基础上定制自己的工具。该镜像为大家解决了包依赖、防火墙规则配置、Socks5服务配置等几乎所有的问题,基本达到了开箱即用的效果。

执行如下命令

# 预先创建一个会话记录文件,
# 不然启动 EasyConnect 的时候会报错
mkdir -p ~/.config/bvpn
echo '{}' > ~/.config/bvpn/easy_connect.json

# 启动容器
docker run --rm \
	--device /dev/net/tun \
	--cap-add NET_ADMIN \
	-v ~/.config/bvpn:/root \
	-e DISPLAY=$IP:0 \
	-e TYPE=x11 \
	-e EXIT=1 \
	-p $SOCK5_HOST:$SOCK5_PORT:$SOCK5_PORT \
	hagb/docker-easyconnect:vncless

其中$IP是你本机的IP,$SOCK5_HOST$SOCK5_PORT是 Socks5 服务配置。稍等片刻,就能看到 EasyConnect 的登录界面了。

特别需要注意的是-v ~/.config/bvpn:/root参数, 其含义是将~/.config/bvpn目录映射到容器的/root目录。EasyConnect 会把登录信息记录到/root/.config/bvpn/easy_connect.json,下次再登录的时候就不用重复填写了。(这也是 Hagb 同学为大家提供的便利)

如果一切顺利,你会在本机的$SOCK5_PORT端口上获取一个 Socks5 代理服务。

访问公司 web 服务,可以使用 SwitchyOmega 等工具设置一个 Socks5 代理。访问公司内网的 git/ssh 服务,则需要在你的~/.ssh/config添加如下配置

Host git.corp.example.com
ProxyCommand=nc -X 5 -x localhost:1080 %h %p

更多细节请参考 Proxy SSH Over SOCKS (the easy way)4

一键脚本

我写了一个脚本,一键启动 EasyConnect 并配好各项配置,在退出的时候自动清理配置,非常方便。

#!/usr/bin/env bash

SOCK5_PORT=1080
SOCK5_HOST=127.0.0.1
IP=`ifconfig |grep "inet "|grep broadcast|awk '{print $2}'|cut -d/ -f1`

xhost + $IP

cat << EOF >> ~/.ssh/config
# bvpn begin
Host git.corp.example.com
  ProxyCommand=nc -X 5 -x $SOCK5_HOST:$SOCK5_PORT %h %p
# bvpn end
EOF

docker run --rm \
	--device /dev/net/tun \
	--cap-add NET_ADMIN \
	-v ~/.config/bvpn:/root \
	-e DISPLAY=$IP:0 \
	-e TYPE=x11 \
	-e EXIT=1 \
	-p $SOCK5_HOST:$SOCK5_PORT:$SOCK5_PORT \
	hagb/docker-easyconnect:vncless

sed -i'' -e '/# bvpn begin/,/# bvpn end/ d' ~/.ssh/config

xhost - $IP

好了,到此就介绍的差不多了。欢迎有需要的同学尝试。我还写了一篇自动登录EasyConnect的文章5,供大家参考。


  1. https://medium.com/@mreichelt/how-to-show-x11-windows-within-docker-on-mac-50759f4b65cb↩︎

  2. https://www.xquartz.org/↩︎

  3. https://github.com/Hagb/docker-easyconnect↩︎

  4. https://www.mikeheijmans.com/sysadmin/2014/08/12/proxy-ssh-over-socks/↩︎

  5. ./auto-login-easyconnect-in-docker.html↩︎