使用 docker 封印 EasyConnect

2020-09-26 创作不易,请勿屏蔽广告🙏 g

EasyConnect 是深信服的一款企业VPN产品,在国内企事业单位中有广泛的应用。在使用 macOS 版的 EasyConnect 过程中,我发现该软件有三个问题。

第一,依赖已经废弃的系统特性。如果你在新版的 macOS 上打开 EasyConnect,你会收到如下提醒:

依赖已经废弃的系统特性EasyConnect 依赖已经废弃的系统特性

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

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

偷偷安装自己的 CA 根证书EasyConnect 安装的 CA 根证书

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

该受信任根证书签发给了本地回环地址 127.0.0.1 一张证书,用于用户使用浏览器登陆 SSLVPN 过程中,浏览器和SSLVPN客户端之间建立安全的https通信时使用。在系统中导入该受信任根证书,是为了消除证书告警,为用户提供更好的使用体验,避免无法正常使用浏览器方式登陆SSLVPN,无其他特殊用途。

并得到如下承诺:

1.该Sangfor Technologies Inc.根证书私钥信息保存在内网,并由专人保管,不会泄露出去。 2.该Sangfor Technologies Inc.根证书只用于颁发给127.0.0.1用于SSLVPN BS登陆使用,不会签发其它证书做其他用途

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

第三,EasyConnect 安装后会配置一个开机自动启动的进程,名叫 EasyMonitor,而且是以 root 帐号启动的,你的一举一动都有能力监听。而且你还不能关掉,关掉就无法使用 VPN 功能了。

开机自启的 EasyMonitor 进程

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


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

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

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

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

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

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

linux 的 x11 系统天生就支持远程显示的。简单来说,机器 A 上的 firefox 进程可以把显示的内容通过网络传给机器 B 并在 B 的屏幕上展示。macOS 可以作为 x11 显示服务器来为 docker 中的程序提供界面绘制能力。

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

开启 XQuartz 的网络支持

你还需要注销当前用户并重新登录才能生效。到此,我们就可以实验一下 XQuartz 的功能了。我们以 firefox 为例:

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

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

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

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

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

https://github.com/Hagb/docker-easyconnect

Hagb 同学还为大家准备好了 docker 镜像,大家可以在他的工作的基础上定制自己的工具。Hagb 同学的镜像为大家解决了包依赖、防火墙规则配置、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)

我写了一个脚本,一键启动 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

好了,到此就介绍的差不多了。欢迎有需要的同学尝试。如果遇到问题,也欢迎留言讨论。