使用 Docker 封印 EasyConnect
涛叔深信服的 EasyConnect 客户端非常垃圾,不但会在开机时以 root 自动启动,还会往系统安装自己的 CA 根证书。这给使用者带来极大的安全隐患。今天分享一种方案,将其封印到 Docker 容器里,消除隐患。
安全隐患
我发现该软件有三个问题。
第一,依赖已经废弃的系统特性
如果你在新版的 macOS 上打开 EasyConnect,你会收到如下提醒:
而在最新的 macOS Big Sur 上,该软件已经无法正常工作。
第二,偷偷安装自己的 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 功能了。
反馈给深信服,还不知道什么时候改;所在公司更是不太可能更换 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 的功能。我们以 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,供大家参考。