Skip to content

Instantly share code, notes, and snippets.

@thislight
Last active April 5, 2023 08:06
Show Gist options
  • Save thislight/c8aaafc063d4f797e6d6310db2869d63 to your computer and use it in GitHub Desktop.
Save thislight/c8aaafc063d4f797e6d6310db2869d63 to your computer and use it in GitHub Desktop.
OpenWRT自动登录BBGU网络
#!/bin/sh
WAN_IF="wan"
if [ "$INTERFACE" = "$WAN_IF" ]; then
if [ "$ACTION" = "ifup" ]; then
if [ "$(bbgu_netlogin loginp)" = "0" ]; then
IFACE="$INTERFACE" bbgu_netlogin login
fi
fi
fi

前置要求

  • 你需要一台运行OpenWRT的设备(仅在OpenWRT 21上测试过),这台机器需要连接上BBGU内网。
  • 安装curl(opkg install curl)。
  • 确保你有libubox这个包,bbgu_netlogin需要这个包里的jshn来解析JSON。

安装指南

  • 把下文两个文件复制到相应路径:bbgu_netlogin复制为/usr/bin/bbgu_netlogin50-bbgu-netlogin复制为/etc/hotplug.d/iface/50-bbgu-netlogin
  • 修改/usr/bin/bbgu_netlogin,填写ACCOUNTPASSISP等信息。给/usr/bin/bbgu_netlogin可执行属性(chmod +x /usr/bin/bbgu_netlogin)。
  • 修改/etc/hotplug.d/iface/50-bbgu-netlogin,把WAN_IF修改为你的WAN接口名。
  • 要手动测试自动登录,重启你的虚拟wan接口。

工作原理

  • 主要负担登录工作的是/usr/bin/bbgu_netlogin。虽然也是用了DrCom的服务,但是BBGU的验证比较宽松,直接访问抓出来的API即可。
  • /etc/hotplug.d/iface/50-bbgu-netlogin负责在指定物理接口对应的虚拟接口上线后调用/usr/bin/bbgu_netlogin登录。

使用Watchcat自动重启接口

基于hotplug.d的自动登录脚本只在接口上线时生效。要按照BBGU的断网时间自动连接有不同的方法,除了本节要介绍的使用Watchcat监视网络连接状态,你还可以用cron之类的功能实现。要使用Watchcat自动重启接口,你需要:

  • 安装watchcat(opkg install watchcat
  • (可选)安装luci-app-watchcat,watchcat的Web界面(opkg install luci-app-watchcat

你可以自行配置你想要的参数,以下是我的配置:

config watchcat
	option mode 'restart_iface'
	option period '7h'
	option pinghosts 'connect.rom.miui.com'
	option pingsize 'small'
	option interface '@wan'
	option pingperiod '2m'

使用cron自动登录

最简单的方法是直接用cron在7点(网络能用之后)自动执行登录。在你的crontab中写入下面这一行(你可以在LuCI中的系统>计划任务里编辑它):

1 7 * * * /usr/bin/bbgu_netlogin login

意思是在每天的7点01分时运行/usr/bin/bbgu_netlogin login

API说明

BBGU应该是使用了大康的网络管理软件,涉及到两个不同的服务:

  • http://10.0.9.35提供前端页面和检查网络状态API
  • http://10.0.9.35:801提供登入登出API

所有API都以jsonp的形式返回数据,不知道是否支持返回json。Cookie对登录似乎有影响,最好提供Cookie。

检查登录状态

GET http://10.0.9.35/drcom/chkstatus

查询参数:

  • callback:jsonp函数名
  • v:暂时不知道是什么意思,使用4-5位随机十进制整数即可。

返回主体:JSONP,里面的result代表登录状态。

例子: curl -XGET http://10.0.9.35/drcom/chkstatus?callback=dr1002&v=2938 -c /tmp/bbgu-cookie.jar

登录网络

GET http://10.0.9.35/eportal/

查询参数:

  • c:似乎是组件的意思。必须使用Portal
  • a:应该是Action的简写,必须使用login
  • login_method:必须为1
  • user_account:以,0,<account>@<isp>形式组成。如账户为1910000000,运营商为联通,就为,0,1910000000@unicomunicom=联通,telecom=电信,mobile=移动。
  • user_password:密码。
  • wlan_user_ip:不知道是否有影响,目前脚本里用的是相应接口的IP地址。
  • wlan_user_ipv6:似乎BBGU不给IPv6,空值就行。
  • wlan_user_mac:BBGU不需要,全零就可以,比如000000000000
  • wlan_ac_ip:空值就行。
  • wlan_ac_name:空值就行。
  • jsVersion3.3.3
  • v:不知道有什么影响,4-5位随机十进制整数即可。

返回主体:JSONP,里面的result代表是否成功,1代表成功。如果失败,可以读取ret_code2代表已经登入过了。

例子: curl -XGET http://10.0.9.35:801/eportal/?c=Portal&a=login&callback=dr1004&login_method=1&user_account=,0,1910000000@$telecom&user_password=123456&wlan_user_ip=10.0.32.44&wlan_user_ipv6=&wlan_user_mac=000000000000&wlan_ac_ip=&wlan_ac_name=&jsVersion=3.3.3&v=33242 -c /tmp/bbgu-cookie.jar

更新日志

5 April 2023

  • 增加EPORTAL_APIBASE变量
  • hotplug脚本现在识别接口而不是物理设备
  • 文档增加了API端点的简单说明

10 March 2022

  • 支持使用特定接口登录

8 March 2022

  • 自动生成我还不知道有什么用的v参数,不用再手动填写了。
  • 解析JSONP(2022年了兄弟们)获取更详细的操作结果(这就导致bbgu_netlogin现在开始需要libubox这个包,这个包在OpenWRT 21上是内置的)。
  • bbgu_netlogin增加了子命令loginp检查登录状态。这个子命令跟之前的实现不一样,之前的实现错了:原来用来检查是否登录的那句话是用JS插入的(这个网站实现真的令人窒息),永远都会返回1。现在已经换成一个API,应该能用了。
  • 把hotplug.d脚本的前缀改成了50。应该会有人需要在联网之后执行一些脚本吧。
#!/bin/sh
. /lib/functions/network.sh
. /usr/share/libubox/jshn.sh
LOGNAME="bbgu_netlogin"
CURL=$(which curl)
COOKIE_PATH="/tmp/bbgu_cookie.jar"
ACCOUNT="<you account>"
PASS="<your password>"
ISP="<your isp>" # choices: unicom, telecom, mobile
EPORTAL_APIBASE="http://10.0.9.35:801"
if [ "$CURL" = "" ]; then
logger -p err -s -t "$LOGNAME" "curl not found."
exit 1
fi
get_v () {
awk 'BEGIN{srand();print int(rand()*8999+1000)}'
}
# $1: jsonp
# $2: leading function name
# output: json
unwrap_jsonp () {
content=$(echo "$1" | awk '{$1=$1};1')
total_len=${#content}
last_pos=$((total_len - 1))
name_len=${#2}
start_pos=$((name_len + 2))
echo "$content" | cut -c"$start_pos-$last_pos"
}
get_wan_if () {
if [ "$IFACE" = "" ]; then
network_flush_cache
network_find_wan NET_IF
echo "$NET_IF"
else
echo "$IFACE"
fi
}
login () {
NET_IF=$(get_wan_if)
network_get_ipaddr NET_ADDR "${NET_IF}"
network_get_physdev NET_L2D "$NET_IF"
if $CURL -X GET --interface "$NET_L2D"\
"$EPORTAL_APIBASE/eportal/?c=GetQzMsg&a=loadUserInfo&callback=dr1003&account=${ACCOUNT}&v=$(get_v)"\
-c $COOKIE_PATH --silent -v; then
logger -p notice -s -t "$LOGNAME" "loadUserInfo complete."
else
logger -p err -s -t "$LOGNAME" "loadUserInfo failed."
exit 1
fi
login_result=$($CURL -X GET --interface "$NET_L2D"\
"$EPORTAL_APIBASE/eportal/?c=Portal&a=login&callback=dr1004&login_method=1&user_account=,0,${ACCOUNT}@${ISP}&user_password=${PASS}&wlan_user_ip=${NET_ADDR}&wlan_user_ipv6=&wlan_user_mac=000000000000&wlan_ac_ip=&wlan_ac_name=&jsVersion=3.3.3&v=$(get_v)"\
-c $COOKIE_PATH --fail --silent -v)
if [ "$login_result" = "" ]; then
logger -p err -s -t "$LOGNAME" "login failed: remote http error"
exit 1
else
json=$(unwrap_jsonp "$login_result" "dr1004")
json_load "$json"
json_get_var stat result
if [ "$stat" = "1" ]; then
logger -p notice -s -t "$LOGNAME" "signed in."
else
json_get_var errcode ret_code
if [ "$errcode" = "2" ]; then
logger -p err -s -t "$LOGNAME" "you have signed in."
else
logger -p err -s -t "$LOGNAME" "unkown error: '$json'."
fi
fi
fi
}
loginp () {
NET_IF=$(get_wan_if)
network_get_physdev NET_L2D "$NET_IF"
remote_result=$($CURL -X GET --interface "$NET_L2D"\
"http://10.0.9.35/drcom/chkstatus?callback=dr1002&v=$(get_v)"\
-c $COOKIE_PATH --fail --silent -v)
if [ "$remote_result" = "" ]; then
logger -p err -s -t "$LOGNAME" "remote http error."
exit 1
fi
# unwrap jsonp
real_json=$(unwrap_jsonp "$remote_result" "dr1002")
json_load "$real_json"
json_get_var stat result # stat=json_get_var result
if [ "$stat" = "1" ]; then
echo "1"
else
echo "0"
fi
}
if [ "$1" = "loginp" ]; then
loginp
elif [ "$1" = "login" ]; then
login
else
login
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment