背景及需求
我校的有线网络并不会限制路由器的使用。然而,有线网络的认证方式是动态 IP + Web 认证。在每天凌晨会重置,访问任意页面就会被劫持到学校的认证网页,在该网页上输入账号密码后,才能联网。虽说不算太麻烦,但每次都要手动输入账号密码,还是让人有些不爽。之前从网上找了别人类似情况造好的轮子,直接使用:
### 自动登陆内网
#!/bin/sh
logger "开始检测网络认证状态"
KEYWORD=$(curl -s http://baidu.com | grep "Moved")
if [[ ${KEYWORD} != "" ]]; then
logger "检测到尚未认证,尝试自动认证"
LOGIN_STATUS=$(curl -s -X POST "http://10.69.253.12/ac_portal/login.php" -H "Origin: http://10.69.253.12" -H "Accept-Encoding: gzip, deflate" -H "Accept-Language: zh-CN,zh;q=0.9" -H "User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36" -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" -H "Accept: */*" -H "Referer: http://10.69.253.12/ac_portal/20190610083017/pc.html?template=20190610083017&tabs=pwd-sms&vlanid=0&url=http://www.msftconnecttest.com%2fredirect" -H "X-Requested-With: XMLHttpRequest" -H "Connection: keep-alive" --data "opr=pwdLogin&userName=账号&pwd=密码&rememberPwd=0")
SUCCESS=$(echo ${LOGIN_STATUS} | grep success)
if [[ ${SUCCESS} != "" ]]; then
logger "自动认证成功"
else
LOGIN_STATUS=$(echo ${LOGIN_STATUS} | cut -d ',' -f3 | cut -d '"' -f4)
logger "自动认证失败: ${LOGIN_STATUS}"
fi
else
logger "检测到已经认证"
fi
然而,最近学校升级了认证机制,密码需要进行rc4加密后再提交,linux的bash脚本对于加密函数编写不太友好,因此需要另想他法。
网上找到了python对于rc4加密现成的算法,直接拿来使用。
首先在路由器上开启Entware,插入U盘,将U盘挂载到/opt,用来安装Entware。保证U盘为exfat格式。
ejusb #卸载usb
mount -t exfat /dev/sda1 /opt #将usb挂载到/opt
然后,安装entware
wget http://mirrors.bfsu.edu.cn/entware/mipselsf-k3.4/installer/opkg -O /opt/bin/opkg
chmod 755 /opt/bin/opkg
wget http://mirrors.bfsu.edu.cn/entware/mipselsf-k3.4/installer/opkg.conf -O /opt/etc/opkg.conf
sed -i 's|bin.entware.net|mirrors.bfsu.edu.cn/entware|g' /opt/etc/opkg.conf
/opt/bin/opkg update
接着安装python3
opkg install python3 #python3
opkg install python3-pip #pip3
接着将挂载U盘的动作添加到开机启动里
ejusb #卸载usb mount -t exfat /dev/sda1 /opt #将usb挂载到/opt
然后将登录的python脚本拷贝到路由器中,例如/etc/storage/
登录脚本如下:
import time
import urllib.parse
import urllib.request
def do_encrypt_rc4(src, passwd):
src = src.strip()
passwd = str(passwd)
key = [0] * 256
sbox = list(range(256))
output = []
plen = len(passwd)
size = len(src)
for i in range(256):
key[i] = ord(passwd[i % plen])
j = 0
for i in range(256):
j = (j + sbox[i] + key[i]) % 256
sbox[i], sbox[j] = sbox[j], sbox[i]
a = b = c = 0
for i in range(size):
a = (a + 1) % 256
b = (b + sbox[a]) % 256
sbox[a], sbox[b] = sbox[b], sbox[a]
c = (sbox[a] + sbox[b]) % 256
temp = src[i]
temp = ord(temp) ^ sbox[c]
temp = format(temp, '02x')
output.append(temp)
return ''.join(output)
def send_post_request(password):
url = "http://1.1.1.3/ac_portal/login.php"
current_time = str(int(time.time())) # 获取当前时间戳并转换为字符串
# 使用do_encrypt_rc4函数加密密码
encrypted_pwd = do_encrypt_rc4(password, current_time)
# 构建POST请求的数据
data = {
"opr": "pwdLogin",
"userName": "账号",
"pwd": encrypted_pwd,
"auth_tag": current_time,
"rememberPwd": "0"
}
# 将数据进行URL编码
data_encoded = urllib.parse.urlencode(data).encode('utf-8')
# 创建请求对象并发送POST请求
request = urllib.request.Request(url, data=data_encoded, method='POST')
try:
with urllib.request.urlopen(request) as response:
# 读取响应内容
response_data = response.read().decode('utf-8')
print("Response:")
print(response_data)
except urllib.error.HTTPError as e:
# 返回错误状态码
print("HTTP Error:", e.code)
return e.code
except urllib.error.URLError as e:
# 返回URL错误
print("URL Error:", e.reason)
return e.reason
# 如果没有错误,则返回 None 或其他合适的值
return None
# 调用发送POST请求的函数,并传入密码
result = send_post_request("密码")
if result is None:
print("登录成功!")
else:
print("登录失败:", result)
最后,在开机脚本加入:
/opt/bin/python3 /etc/storage/login.py