一种自动登录EasyConnect的思路

2020-12-27 ⏳3.2分钟(1.3千字)

我司使用深信服的 VPN 产品 EasyConnect。这个 EasyConnect 在 mac 平台上有诸多问题,有兴趣的同学可以参考我之前的文章使用 docker 封印 EasyConnect (以下简称前文)。可是用了一段时间我发现,VPN 连接以后,每隔一两分钟就会断一次。我司的 VPN 又开启了二次验证,即便 EasyConnect 记住了我的帐号和密码,重连的时候还得输一遍动态口令,极不方便。这个断线重连太影响效率了,那能不能自动输入动态口令呢?今天休假回家,没连上两分钟,又断线了。我忍无可忍,下定决心解决这个问题。

首先,我怀疑是 EasyConnect 的问题。我联系了深信服的技术客服。他们要求提供客户端的日志。我答应了。当收集到日志后我发现有很多我司内网的信息,不能冒然提交给第三方;自己脱敏又怕遗漏;我自己翻了一下日志,也没找到什么明显的线索,只好作罢。

一计不成再生一计。我司在 VPN 主页提供了 EasyConnect 的下载链接。有没有可能是客户端版本不一致导致的问题呢?于是我基于 Hagb 的镜像1重新构建 docker 镜像,并把 EasyConnect 换成了我司订制的版本。试了一下,连接时间比之前长了一丢丢,但还是坚持不了五分钟……

暂时改变不了别人,那能不能改变自己呢?

我想了一下。VPN 的用户名和密码 EasyConnect 已经帮我记住了,会自动登录。每次断线重连的时候,需要我手工介入的输入动态口令,然后按回车,完成连接动作。

我司使用的是标准的二次验证口令(谢天谢地),我早就通过 rsc/2fa2 这个项目实现自动化读取了。一般我会在需要的时候执行2fa|grep -E '[0-9]+' -o|pbcopy将当前的动态口令复制到系统剪贴板。

所以我在连接 VPN 的时候需要执行以下步骤:

  1. 执行 bvpn(我定制的 docker 命令,具体参见「原文」)
  2. 等待 EasyConnect 自动登录(大约一秒钟)
  3. 执行2fa|grep -E '[0-9]+' -o|pbcopy将当前的动态口令复制到系统剪贴板
  4. ctrl+v(对,不是cmd+v)将动态口令粘贴到 EasyConnect 输入框
  5. 按回车键完成连接

显然,第三步可以实现自动化。于是我在 bvpn 脚本中添加了这么一行。

(sleep 1 && 2fa|grep -E '[0-9]+' -o|pbcopy)&

如果把括号看成一个整体,那这一行的意思是(xxx)&即在后台运行 xxx 命令。为什么要在后台运行呢?因为我们同时还要启动 EasyConnect 客户端。又因为 EasyConnect 连接和登录服务器需要一点时间,所以我们最好能等一会再复制动态口令3。所以括号内的部分sleep 1 && yyy表示暂停一秒种,然后再执行 pbcopy 命令。pbcopy 命令就是复制动态口令到剪贴板。

到这里,革命完成一半了,但尚未成功,仍需努力。

如何自动完成第四步和第五步呢?

大家不要忘了 EasyConnect 是运行在 linux 下的 X11 应用。我们能不能找一个办法模拟 X11 的键盘事件呢?一顿谷歌(关键词bash send x11 key event)找到了 xdotool。如何模拟第四、五两步呢?只需执行如下命令:

xdotool key ctrl+v Return

xdotool 会替你先按ctrl+v再按回车键,是不是很方便。

但是如果你使用比较新的 mac 系统,会收到如下报错:

Warning: XTEST extension unavailable on '(null)'. Some functionality may be disa
bled; See 'man xdotool' for more info.
Xlib:  extension "XTEST" missing on display "XXX.XXX.X.XXX:0".
...

这是因为从某个版本开始,XQuartz 默认没有开启 XTEST 扩展导致的。打开也很简单4

defaults write org.xquartz.X11 enable_test_extensions -bool yes

但某些版本的 XQuartz 有 bug,配置后不生效。我使用当前最新的版本 2.8.6_beta1 测试没有问题。如果不行就升级最新版本!

最后我们需要在 docker 容器运行 xdotool。所以,我们得改一下原来的docker-root/usr/local/bin/start-sangfor.sh文件:

diff --git a/docker-root/usr/local/bin/start-sangfor.sh b/docker-root/usr/local/bin/start-sangfor.sh
index bc0cbb0..e483892 100755
--- a/docker-root/usr/local/bin/start-sangfor.sh
+++ b/docker-root/usr/local/bin/start-sangfor.sh
@@ -1,6 +1,7 @@
 #!/bin/bash
 /usr/share/sangfor/EasyConnect/resources/bin/EasyMonitor
 sleep 1
+(sleep 2 && xdotool key ctrl+v Return)&
 while true
 do
        # 在 EasyConnect 前端启动过程中,会出现 cms client connect failed 的报错,此时应该启动 sslservice.sh。但这个脚本启动得太早也会没有作用…

翻译成人话就是在启动 EasyConnect 的同时等待两秒钟5,然后从剪贴板粘贴动态口令,再按回车完成 VPN 连接。

好了,大功告成~ 从此,我只要输入 bvpn 按回车,等待几秒钟(不吹不黑,确实慢),就可以连接公司内网了。如果 VPN 异常断开,那就再连一次。一键连接,你说不香吗


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

  2. https://github.com/rsc/2fa↩︎

  3. 动太口令随时间变化,太早复制可能会过期。↩︎

  4. https://stackoverflow.com/a/35213728↩︎

  5. 等 EasyConnect 完成登录并等待待用户输入动态口令,这一步时间可长可短,大家按需调节↩︎