Tunnelblick自动输入动态密码和自动连接

Oct 28, 2022 • Kael


前言

很多公司为了保证安全,一般内网服务都不允许直接公网访问,员工使用内网服务通常都需要使用VPN接入公司内网,目前企业内网的VPN方便常见的有微软自带的VPN功能,或者开元的OpenVPN协议,或者其他的easy connect等等。

本文主要讨论基于OpenVPN方案的工具。

基于OpenVPN方案的客户端比较常见的有OpenVPN ConnectTunnelblick,这两个都是非常优秀的客户端软件,(Ubuntu系统自带了OpenVPN连接,可以不使用这两个软件)。

出于工作需要,每次打开电脑都要连接VPN,如果使用固定密码的话,可以通过软件的记住密码功能实现不用每次都输入密码,但是有些公司的服务器为了安全,不会使用固定密码,而是使用类似谷歌验证的方式,使用动态密码,这个时候就非常麻烦了,每次连接必须先获取谷歌动态密码,然后再输入到密码框中,一天连接一次可能还好,连接多次的时候,确实是非常烦人的操作。

目前经过笔者研究,OpenVPN Connect还不支持使用脚本动态输入密码,但是Tunnelblick从3.8.3beta02以后的版本就支持通过脚本动态替换密码的能力了,官网文档Using Scripts

本文主要介绍在Mac OS系统下如何基于Tunnelblick的脚本功能实现动态输入密码自动连接VPN。

前期准备

在开始实现动态输入密码的脚本前,我们要先通过正常的安装和配置,确保们的VPN已经可以正常使用,参考官网安装并导入配置即可。

安装配置完成后,可以看到如下vpn详情中有如下配置:

现在我们先配置自动登录:

这里的密码随便输入,后面我们会用脚本自动替换,在这里随便输入密码只是为了自动触发登录的操作。

ok,到这里我们的前期准备已经完成。

编写脚本

根据官网的文档:

password-replace.user.sh is executed to get a string to replace a password before it is passed to OpenVPN.

我们可以使用脚本password-replace.user.sh在登录前对输入的密码进行替换,替换成我们自动计算的动态密码即可,需要实现如下两部:

  • 生成谷歌验证码
  • 使用password-replace.user.sh脚本将谷歌验证码返回给tunnelblick替换前面记住的密码
  • 重新加载配置,使脚本生效

生成谷歌验证码

首选我们需要一个自动生成谷歌验证码的脚本,目前最简单的方式就是使用python脚本,这里给出一个实际可用的例子:

import hmac, base64, struct, hashlib, time
import platform

def get_hotp_token(secret, intervals_no):
    key = base64.b32decode(secret, True)
    msg = struct.pack(">Q", intervals_no)
    h = hmac.new(key, msg, hashlib.sha1).digest()
    o = ord(chr(h[19])) & 15
    h = (struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff) % 1000000
    return h

def get_totp_token(secret, bias):
    return get_hotp_token(secret, intervals_no=int(time.time()+bias)//30)

def get_google_code():
    secret="$SECRET" # 谷歌验证密钥,用于生成谷歌验证码,需要注意的是,验证码的长度需是16的整数倍,比如16,32,64等,如果长度不足,则通过=号补齐长度
    googlecode=get_totp_token(secret, 0)
    return '%06d' % googlecode

print(get_google_code(),end="")

完成上述脚本之后,可以执行一下验证是否成功:

$> python3 tunnelblick.py
303158%

说明脚本已经ok。

注意最后的%,这个是自动添加的,可以不理会,tunnelblick在使用密码的时候会自动将这个结尾去掉,官网原文:

If the output from the "password…" scripts ends in an ASCII LF character (0x0A), it will be removed before the string is used to replace or modify the password.

替换输入密码

password-replace.user.sh脚本要放在对应的VPN设置目录下,默认是:

/Library/Application Support/Tunnelblick/Users/{user}/{config_name}.tblk/Contents/Resources

这个目录必须使用root权限创建和修改脚本,参考官网File Locations

脚本内容如下:

#! /bin/bash
PASSWORD=$(python3 tunnelblick.py)
echo "$PASSWORD"

这里第一行的#! /bin/bash不能少,否则tunnelblick不会执行这个脚本。

echo输出的结果tunnelblick会作为返回值,替换原来记住的密码,可以根据需要处理即可。

  • password-replace.user.sh脚本的权限必须是0755,否则tunnelblick会识别为不安全脚本无法连接
  • google_auth.py的目录建议不要放在自己的目录下,否则权限也必须是0755

重新加载配置

增加这个脚本后,相当于修改了当前vpn连接的配置,Tunnelblick会扫描并发现配置变更了,此时连接会出现警告:

这里有三个选项:

  • Secure the Configuration: 回滚配置,使用最后一次正确的配置
  • Revert to the Last Secured Copy: 应用配置,保存本次变更为最后一次正确配置
  • Cancel: 取消,暂时不处理,也不连接VPN

这里我们选择Revert to the Last Secured Copy保存配置即可。

有可能不会每次都弹出这个提醒,如果没有弹出这个提醒,并且连接一直失败的话,请重启tunnelblick,并检查2.1.2中的脚本权限是否正确

现在已经可以自动填写动态密码并连接VPN了。

设置启动连接【可选】

最后,我们可以在配置中选择启动tunnelblick即自动连接VPN,这样就可以达到重启后也自动连接的目的,最大限度减少我们关注VPN是否连接的问题: