今日对我家的网络进行了改造,在 ROS 路由器和核心交换机之间桥接了一个 Panabit 流控系统,用于进行更细粒度的流量控制。偶然发现 Panabit 提供了一个 Web 认证插件,使用该插件可以实现对某个网段的 Web 上网认证,并支持动态密码,防止 WiFi 密码泄露。
但 Panabit 官方提供的动态密码功能,适用于网吧环境,即每一台 PC 允许带一个移动终端上网。

Panabit-动态密码

而我更希望是可以通过一个 APP 或者页面来动态生成密码,访客输入即可完成上网认证。并且,这个临时密码应该是具有有效期的,过期后将不能使用。

整体效果

最后,我选择将产生动态密码的页面集成到了企业微信中,通过企业微信鉴权,使得动态密码生成器可以不被非授权访问。

成果展示

当然是支持移动端的,如图。

密码生成器 - 移动端

用户可以向管理员索要上网密码,自助完成上网认证。

网络规划

这个网络规划并没有太多的借鉴性,因为环境差异,很难说能有多大参考价值。
超级简单的拓扑图:

网络拓扑

设备介绍:

  • 路由器:RouterOS
  • 流控系统:Panabit
  • AC+AP:集客 ACx86,集客 AP
  • 交换机:H3C

无线网 SSID 规划(在集客 AC 上配置):

  • 访客网络:XXXX-Guest
  • 户主网络:XXXX

VLAN 规划(在 ROS 上配置,并在交换机中进行放通):

  • 访客 VLAN:vlan 40
  • 户主无线 VLAN:vlan 42
  • 管理 VLAN:vlan 66

策略(在 ROS 上配置):

  • 访客只允许访问 Web 认证页面,不允许访问局域网其他网段
  • 访客无线租户隔离

安装 Web 认证插件

登录 Panabit,在应用商店中安装“Web 认证”插件。

Web 认证插件安装

完成 Web 认证配置

回到“我的应用”,在“第三方接口”页面,选择“Web 认证”插件,进行配置。

基本配置

一般如图配置即可,在免认证 IP 中,新建一个组,把非访客的 IP 段加进去,表示这些 IP 段不进行认证。提交即可。

改造临时用户生成器

Panabit-动态密码

打开 Web 认证开关后,我们其实就已经可以生成密码,并进行认证了,但如 Panabit 这个功能提示所说,这是为网吧场景开发的一个功能,每一个 PC 的 IP 可以生成一个用于认证的用户,显然,是不太符合我这个使用场景的,所以我开始对这个密码生成脚本进行了改造。

注意
以下操作会修改 Panabit 的底层脚本,建议先对 Panabit 进行备份,以防误操作造成系统损坏。
文件的编码方式均为 gb2312。

打开 Panabit 的 SSH 连接,并进行登录。
打开/usr/system/admin/cgi-bin/Login目录,新建一个脚本文件,例如我这里叫guestoken

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/bin/sh
#This script is created by ssparser automatically. The parser first created by MaoShouyan
#Changed by XiaoTan. 2021-2-25
printf "Content-type: text/html;charset=gb2312
Cache-Control: no-cache

"
echo -n "<html xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">
<head><title>访客密码生成器</title>
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=gb2312\">
<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">
<META HTTP-EQUIV=\"Cache-Control\" content=\"no-cache\">
<META name=\"viewport\" content=\"width=device-width,user-scalable=no\"/>
<style>
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 0;
margin: 0;
}
html {overflow: hidden}
body {
font-family: \"微软雅黑\";
font-size: 12px;
color: gray;
margin: 0;
background: #fefefe
}
</style>
<body>
";
# windows=`echo ${HTTP_USER_AGENT} | grep "^Mozilla" | grep "MicroMessenger"`
oauth2=`echo $QUERY_STRING | grep "code="`
if [ "${oauth2}" = "" ]; then
echo "<br><br><br><br><br><center><h2>【请求非法】请在企业微信中打开!</h2><br></center>"
else
# Random Password
guest_pwd=`awk 'BEGIN{srand();print rand()*1000000}'`
varlist=`/usr/ramdisk/bin/floweye pppoeacct add g=tmp name=${guest_pwd} passwd=${guest_pwd} enable=1 maxonline=1`
#varlist=`/usr/ramdisk/bin/floweye pppoeacct config wifitoken=${REMOTE_ADDR}`
if [ "$?" != "0" ]; then
if [ "${varlist}" = "NOT_ONLINE" ]; then
echo "<br><br><br><br><br><center><h2>此机器未经过Panabit或IP超过授权,IP=${REMOTE_ADDR}</h2><br></center>"
else
echo "<br><br><br><br><br><center><h2>出现错误:${varlist}<h2><br></center>"
fi
else
echo "<br><br><br><br><br>"
echo "<center><h2>请将校验码提供给访客</h2></center>"
echo "<br>"
echo "<center><h1 style='letter-spacing:2px;color: #000;'>${guest_pwd}</h1></center>"
echo "<br>"
echo "<center>距校验码过期还有 <b id='timeout'>60</b> 秒</center>"
echo "<br><br>"
echo "<center>由 Panabit & TXisfine.cn 提供技术支持</center>"
# echo "debug:${oauth2}"
echo -n "
<script>
var timer = null;
var count = 60;
timer = setInterval(function () {
count--;
document.getElementById('timeout').innerHTML=count;
if (count <= 0) {
location.reload();
}
}, 1000);
</script>
";
fi
fi

echo -n "
</body>
</html>
";

其实这个脚本是在wifitoken的基础上修改而来的,原来的脚本是通过floweye pppoeacct config wifitoken=${REMOTE_ADDR},来生成临时用户和密码的,如果 REMOTE_ADDR 不在 Panabit 的中在线,则将报错。每个 REMOTE_ADDR 也只能生成一个账号。
这里我通过floweye pppoeacct add g=tmp name=${guest_pwd} passwd=${guest_pwd} enable=1 maxonline=1命令来注册临时用户,用户名和密码都一致,是随机生成的。
好了,别忘了给这个文件一个 755 权限。

1
chmod 755 guestoken

这时候获取动态密码的地址变为了:http://Panabit:8010/cgi-bin/guestoken,但是这时候你访问,必然 404。因为 Panabit 每次启动会建立内存盘,并把系统文件 Copy 一份到内存盘中,所以这个操作,重启系统生效。
下面我们开始修改认证页面。原来的认证页面是带用户名和密码的,略微有点麻烦,那我们也改造一下。
/usr/system/app/webauth/web/user/html/portal.html文件进行编辑。因为文件比较长,我就不贴完整代码了,后续完整代码,我会放在附件里。

编辑/etc/rc.local,末尾追加一个命令cp /usr/system/app/webauth/web/user/html/portal.html /usr/ramdisk/login/webauth/portal.html,将 Portal 文件复制到内存盘中。

当然,Panabit 是支持 SCP 登录的,你也可以直接将两个文件上传上去,注意文件编码即可。

这里是 附件 啊!!!

好了,Panabit 侧的配置就基本完成了,重启,使修改生效。进行配置企业微信。

配置企业微信

因为企业微信侧的可信域名不允许使用 IP,我们在 ROS 上配置一个 DNS A 记录,指向 Panabit 的 IP。
例如,我将 panabit.tt 指向了我的 Panabit 设备。

在企业微信后台,创建一个应用,配置应用主页为这个地址。

https://open.weixin.qq.com/connect/oauth2/authorize?appid=企业ID&redirect_uri=Panabit密码生成器地址&response_type=code&scope=snsapi_base#wechat_redirec

appid 后面跟企业的 ID,应该是一个 ww 开头的字符串,redirect_uri 后面跟刚才 Panabit 的密码生成器地址,记得 urlencode 一下。其他就不用动了。

例如我这里配置成这个地址了。

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wwxx&redirect_uri=http%3a%2f%2fpanabit.tt%3a8010%2fcgi-bin%2fguestoken&response_type=code&scope=snsapi_base#wechat_redirec

配置一下可信域名,如图,把刚才做 A 记录的域名 + 端口号写进去即可。

可信域名配置

好了,可以尝试在企业微信里使用这个应用生成密码啦。整体效果在文章头,可以给大家参考。