早期的网游似乎会让,玩家购买动态令牌绑定账户,提高游戏安全性,在那个木马横飞的年代,这种做法很有必要,不过现在的大数据风控加上手机短信验证,似乎比动态令牌来的安全,并且方便,毕竟手机随时随地都带着。

动态令牌产生一串简单的数字,能不能很好的保证安全,以前的我是挺怀疑的。
工作原理并不显得复杂,过程就是对一串实现预置的密钥Key使用时间加盐,然后计算哈希值,并且保证30s内的哈希值都是一样的,服务端也保留着这个Key,验证的使用取出这个Key以同样的算法计算然后对比,
特点是令牌有时效性,过一会儿就不能用了,为了排除时间不同步带来的偏差,
当前时间产生的令牌的下一个或者上一个都是有效的,这种方法称为TOTP
另外一种是基于使用次数而变化算法,称为HOTP,把时间替换成计数器,每使用一次,计数器就加一,令牌也发生变化。上面QQ令牌就是使用TOTP,但不一定是标准协议。
事实上如果最开始的Key就泄露了,那么根据Key计算出动态令牌也是很简单,之所以比密码安全,是因为将Key托管给了第三方的软件或者硬件,软件有Google 身份验证器,支持HOTP和TOTP,不支持同步不支持导出,也就是说除了在当前手机上面使用,除此之外,只能重新生成密钥。

![Google 身份验证器](../images/2019/winter/Google 身份验证器.webp)

使用SSH密钥登录是最安全的,如果密钥不泄露是不存在暴力破解的。SSH私钥默认存放在用户目录.ssh里面,并且几乎是任何程序都能够读取到里面所有的私钥,稍微好一点的方法是对私钥再次进行加密:

ssh-keygen -f ~/.ssh/id_rsa -p

出于这样的考虑,又不想太麻烦,所以开始使用两步验证来做登录认证,方案有两种:1)动态令牌验证加SSH密钥验证。2)使用动态令牌代替SSH密钥验证。配置过程意外的简单,我本以为需要自己开发软件,通过搜索发现修改PAM配置,添加Google Authenticator模块,最后生成一个密钥就算完成了。

PAM

可插拔身份验证模块(Pluggable authentication module)是Linux系统里面普遍使用的一套用户认证授权框架,通过查看/etc/pam.d/目录里面存在哪些文件,可以知道哪些服务使用或者支持PAM,正常是一些用户管理命令,其中包括sudo,也包括SSH登录认证。

PAM配置文件中流程控制标记有required,requisite,sufficient,optional,include

  1. required,必须通过,失败整个流程验证失败,但是会继续验证。
  2. requisite,必须通过,失败整个流程验证失败,马上停止验证。
  3. sufficient,可选验证,失败不会影响后面验证,成功马上返回。
  4. optional,无关经验的模块,用于记录或者提供提示信息,不会影响结果。
  5. include,包含其他文件同一个堆栈的配置。

安装Google Authenticator

在Debian系统里面是libpam-google-authenticator,在Arch Linux仓库里面是libpam-google-authenticatorqrencode,后者是用来生成二维码,没有安装也能正常使用,查看二维码的方式变化成打开一个链接,在浏览器里面显示。

PAM 配置

Debian/Ubuntu系统是打开配置文/etc/pam.d/sshd,影响登录的认证类型是auth

# 添加下面这一行,在授权之前
auth sufficient pam_google_authenticator.so
# Standard Un*x authentication.
@include common-auth

Arch 系统也是同样的配置文件路径

# 添加下面这一行,在授权之前
auth sufficient pam_google_authenticator.so
auth      include   system-remote-login

sufficient是告诉系统,使用临时生成的密钥验证成功,那么就跳过后面的验证。

SSH 配置

必须打开下面两个配置,同时关闭密码登录。

PasswordAuthentication no
ChallengeResponseAuthentication yes
UsePAM yes

ChallengeResponseAuthentication这个选项是在登录失败之后,SSH服务器并不会直接断开,而是尝试分配一个虚拟的tty,让你可以输入用户名密码或者其他验证模块进行交互,如果关闭,那么密钥或者密码验证错误就直接断开。PasswordAuthentication关闭密码登录。如果单单使用证书登录的话,那么这两个选项都要设置成no,两步验证需要打开。

生成密钥

这是最后一步,使用需要两步验证的账户,执行命令

google-authenticator

中间会询问若干问题,全部y保持默认即可,手机端使用google authenticator扫码保存到手机上面。

问题包括:

是否禁用相同令牌登录,令牌30s更换一次。

令牌保存个数,默认3个,因为是根据时间计算出令牌,那么如果时间不同步,生成的令牌也会不一样,3个表示当前令牌和之前之后两个,可以修改配置文件保存更多个,数量变多安全性会下降。

是否开启防暴力破解,限制30s只能尝试3此。

关于动态令牌

国内BAT都有两步验证,可以设置完全开启或者不开启,即使不开启的时候,也会通过大数据判断是否存在风险,比如异地登录、在新的电脑上面登录都需要验证邮箱或者手机短信,但是对于动态令牌的支持几乎没有。而Google、Facebook、Microsoft对于动态令牌都有支持,这和国内policy有一定的关系,在国内上网使用到的任何网络服务都必须绑定手机号码,如果必须绑定手机再通过手机接收短信完成两步验证,使用动态令牌来登录似乎有些多余了。

排除网上的公共服务,私人服务比如VPS、网盘、博客,这些服务通过动态令牌来认证会比直接使用密码登录安全很多。