使用google认证系统生成动态密码

構成図 Google 認証システムの確認コード生成方法に準じたワンタイムパスワードを設定する

通过路由器的时间和事先设置在路由器中的用户信息为基准,每隔30秒进行各L2TP客户端的密码变更。生成的密码等同于用Google身份验证器(iOS终端、安卓终端上的一种APP)生成的验证码。生成后的密码会自动的设置到pp auth username中。

用户需要将密钥设置到Google身份验证器中,Google身份验证器将会生成一个验证码。将此验证码作为密码进行L2TP连接。
Google身份验证器的设置方法请参考:Google账户的帮助页面

路由器的时间和L2TP客户端的时间如果不相同的话,那么Lua脚本生成的密码和Google身份验证器生成的验证码就不一样了。本设置例中,为了使时间一致,设置了每天的23:50进行NTP时间更新。

本设置例需要使用到检查用户名用的Lua脚本、生成动态密码用的模块文件、以及从以下页面(外部页面)中下载的sha1.lua文件。需要将这些文件都复制到路由器中。

模块文件的导入手册

在RTX1200中加入以下的设置

根据L2TP客户端的数量,按照以下格式,用set命令将用户的信息设置到RTX1200中。

set PP(用户编号)=(用户名):(密钥)

用户编号
       从1开始,lua脚本中的「可以使用的PP数」为止的数字
用户名
       不包括":" (冒号)在内的任何字符串(1字符以上64字符以内)
密钥
       半角英文数字中的,从A到Z,以及从2到7的任意16字符
       不区分英文的大小写

用户名和密钥之间用 ":" (冒号)分隔。
如果用户信息发生了变更,请重新运行Lua脚本。

[设置例]
# set PP1=BNR114:7a436biziktj23S3
# set PP2=u77dcI:6u3tkx42hkemc72a
# set PP3=Ixd@216:rx36mwd2jker4csy

构筑网络结构

  1. 构筑和本设置例页面顶部的结构图相同的网络结构。

将模块文件复制到路由器中

  1. 模块文件下载到PC中。

    [解说]
    模块文件中的文件名,关系到Lua脚本是否能正常运行,请不要随意变更。

  2. 将U盘连接至PC,将下载后的模块文件复制到U盘中。
  3. 将U盘连接到路由器上。确认路由器的USB灯点亮。
  4. 打开路由器的控制台页面。

    [解说]
    路由器控制台可以通过串口线或telnet进行连接。
    具体的使用方法请参考使用说明书。

  5. 用管理员权限登陆,用命令将模块文件复制到路由器中。
    使用copy命令。
    从U盘的根目录复制到路由器的根目录时:
    [路由器控制台]

    # copy usb1:/onetimepass.lua /onetimepass.lua
    # copy usb1:/sha1.lua /sha1.lua
    #

    [解说]
    copy命令的具体参数,请参考此处
    模块文件的文件名发生变更时,Lua脚本中的require函数中的参数也要变更。

Lua脚本的导入手册

[解说]
Lua脚本产品能够下载到运行为止的手册请参考Lua脚本的导入步骤

RTX1200的设置例

环境变量的设置

set LUA_PATH="./\?.lua;"# 注释1

路由的设置

ip route default gateway pp 1

LAN接口
的设置

ip lan1 address 192.168.100.1/24
ip lan1 proxyarp on

WAN接口
的设置

pp select 1
pp always-on on
pppoe use lan2
pp auth accept(认证方式)
pp auth myname(连接ISP的ID) (连接ISP的密码)
ppp lcp mru on 1454
ppp ipcp ipaddress on
ppp ipcp msext on
ppp ccp type none
ip pp mtu 1454
ip pp nat descriptor 1
pp enable 1

接受L2TP连接
的设置

pp select anonymous
pp bind tunnel1-tunnel3
pp auth request(认证方式)
pp auth username(用户名1) (动态密码1) # 通过Lua脚本进行变更。
pp auth username(用户名2) (动态密码2) # 通过Lua脚本进行变更。
pp auth username(用户名3) (动态密码3) # 通过Lua脚本进行变更。
ppp ipcp ipaddress on
ppp ipcp msext on
ip pp remote address pool 192.168.100.10-192.168.100.20
ip pp mtu 1258
pp enable anonymous

L2TP连接使用
的隧道设置
(客户端A)

tunnel select 1
tunnel encapsulation l2tp
ipsec tunnel 101
ipsec sa policy 101 1 esp(加密算法) (验证算法)
ipsec ike keepalive use 1 off
ipsec ike local address 1 192.168.100.1
ipsec ike nat-traversal 1 on
ipsec ike pre-shared-key 1 text(预先共享密钥)
ipsec ike remote address 1 any
l2tp tunnel disconnect time off
l2tp keepalive use on 10 3
l2tp keepalive log on
l2tp syslog on
ip tunnel tcp mss limit auto
tunnel enable 1

L2TP连接使用
的隧道设置
(客户端B)

tunnel select 2
tunnel encapsulation l2tp
ipsec tunnel 102
ipsec sa policy 102 2 esp(加密算法) (验证算法ム)
ipsec ike keepalive use 2 off
ipsec ike local address 2 192.168.100.1
ipsec ike nat-traversal 2 on
ipsec ike pre-shared-key 2 text(预先共享密钥)
ipsec ike remote address 2 any
l2tp tunnel disconnect time off
l2tp keepalive use on 10 3
l2tp keepalive log on
l2tp syslog on
ip tunnel tcp mss limit auto
tunnel enable 2

L2TP连接使用
的隧道设置
(客户端C)

tunnel select 3
tunnel encapsulation l2tp
ipsec tunnel 103
ipsec sa policy 103 3 esp(加密算法) (验证算法)
ipsec ike keepalive use 3 off
ipsec ike local address 3 192.168.100.1
ipsec ike nat-traversal 3 on
ipsec ike pre-shared-key 3 text(预先共享密钥)
ipsec ike remote address 3 any
l2tp tunnel disconnect time off
l2tp keepalive use on 10 3
l2tp keepalive log on
l2tp syslog on
ip tunnel tcp mss limit auto
tunnel enable 3

NAT的设置

nat descriptor type 1 masquerade
nat descriptor address outer 1 ipcp
nat descriptor address inner 1 auto
nat descriptor masquerade static 1 1 192.168.100.1 esp
nat descriptor masquerade static 1 2 192.168.100.1 udp 500
nat descriptor masquerade static 1 3 192.168.100.1 udp 4500

IPsec的transport
模式的设置

ipsec transport 1 101 udp 1701
ipsec transport 2 102 udp 1701
ipsec transport 3 103 udp 1701
ipsec auto refresh on

DHCP的设置

dhcp service server
dhcp server rfc2131 compliant except remain-silent
dhcp scope 1 192.168.100.30-192.168.100.191/24

DNS的设置

dns server(ISP指定的DNS服务器地址)
dns private address spoof on

L2TP设置

l2tp service on

Lua脚本的启动的设置

schedule at 1 startup * lua(Lua脚本文件名)

NTP的定期运行的设置

schedule at 2 */* 23:50:00 * ntpdate(NTP服务器地址ス) syslog

Lua脚本例

设置值

-- 用户信息的设置值有误时,输出的SYSLOG的等级 (info, debug, notice)
log_level = "(SYSLOG等级)"
-- 可以使用的PP数
max_pp =(可以使用的PP数)

读取模块文件

require("onetimepass")

常量

-- 30秒
SEC30 = 30
-- 将10年转换成秒
DECADE = 315532800 -- (365日×10年+2日(闰年数)(日) = 3652×24×60×60(秒))
-- 用户名的最大字符数
MAX_USER = 65
-- 密钥的字符数
KEY_LEN = 16

检查用户信息的函数

function user_info_check()
 local user, key, user_key
 local match_ptn = "(.+)%:([a-zA-Z2-7]+)"
 local find_ptn = "(.*)%:(.*)%:(.*)"
 local user_num = 0

 for i = 1, max_pp do
  user_key = os.getenv("PP" .. i)

  if user_key then

   -- 如果用户信息中含有2个以上":" (冒号)的话,报错退出
   if user_key:find(find_ptn) then
    return false
   end

   -- 从用户信息中读取用户名和密钥
   user, key = user_key:match(match_ptn)

   -- 没有发现用户名或密钥时,报错退出
   if not user or not key then
    return false
   end

   -- 用户名超过65个字符或密钥不是16个字符时,报错退出
   if user:len() >= MAX_USER or key:len() ~= KEY_LEN then
    return false
   end

   user_num = user_num + 1
  end
 end

 -- 没有设置任何用户信息时,报错退出
 if user_num < 1 then
  return false
 end
 
 return true
end

在PP中设置auth username的函数

function set_auth_user(t)

 -- 选择PP anonymous
 rt.command("pp select anonymous")

 -- 运行auth username命令
 for i, v in ipairs(t) do
  if v then
   rt.command(v)
  end
 end
end

动态密码用的计数器函数

function create_counter()
 local t = os.time() + DECADE + SEC30

 return onetimepass.hex2bin(string.format("%.16X", t / SEC30))
end

主程序

local id, pass, id_pass
local cnt, cmd
local cmd_tbl = {}
local match_ptn = "(.+)%:(%w+)"
local cmd_ptn = "pp auth username %s %s"

-- 用户信息的检查
if not user_info_check() then
 rt.syslog(log_level, "[OTP] Invalid Parameter.")
 os.exit(1)
end

while true do
 -- 下一个0秒 or 30秒的计时
 rt.sleep(SEC30 - os.time() % SEC30 + 1)

 if cnt then
  set_auth_user(cmd_tbl)
 end

 -- 生成计数器
 cnt = create_counter()

 -- 生成下一个30秒的动态密码
 for i = 1, max_pp do
  cmd = false

  -- 从环境变量中读取用户名和密钥
  id_pass = os.getenv("PP" .. i)
  if id_pass then

   id, pass = id_pass:match(match_ptn)

   if id and pass then
    cmd = string.format(cmd_ptn, id, onetimepass.otp(pass, cnt))
   end
  end

  cmd_tbl[i] = cmd
 end
end

注释的说明

注释1:
为了读取模块文件,而设置的路径。
因为Lua里面要使用模块文件名的置换符号 "?",但是因为路由器控制台中'?'是帮助命令, 所以要在'?'前面加上转义序列符 '\'。

返回顶部