Pages

Thursday, 29 November 2018

使用LuCI的RPC接口修改openwrt的配置

简单来说,本文整理了一些openwrt的RPC接口,用来自动修改pppoe的密码,并重启网络。为什么要弄这些玩意呢,因为浙江高校中普遍使用的蛋疼的闪讯——两三天换个动态密码,时不时给你断个网!使用这些API的是一个Android应用,它在用户按下一个按键后自动向电信发送一条获取密码的短信,然后获取返回的短信,解析其中的闪讯动态密码,通过openwrt的RPC接口修改密码并重启网络,这样,只需要一次按按钮的操作,就能恢复网络,又可以愉快的玩耍啦。
openwrt 我就不多介绍了,玩路由器的都知道;UCIopenwrt提供的一套统一的配置接口,可以用以配置整台openwrt设备;而LuCI是一个基于Lua语言开发的、包装了底层UCI接口的易于使用的Web用户接口。LuCI也提供了一种基于JSON格式的RPC机制来访问其内部的库。
LuCI的RPC接口的地址为 /cgi-bin/luci/rpc/LIBRARY,其中LIBRARY代表按功能区分的几个库,分别为:
  • auth - 基于token的认证库
  • uci - UCI统一配置接口的映射
  • fs - 文件操作
  • sys - 提供了一些系统通用功能
  • ipkg - ipk包的管理
下面以具体的操作演示其中一些库的使用,文中未用到的库可自行查询API文档 。

修改pppoe密码流程

下面的请求都使用curl作为HTTP客户端。

获取token

$ curl -i -X POST -d '{"method":"login","params":["root","admin"]}' http://192.168.1.1/cgi-bin/luci/rpc/auth

HTTP/1.1 200 OK
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json
Set-Cookie: sysauth=f807d8dc25e82d2d457c0d2f1ee27ce7; path=/
Cache-Control: no-cache
Expires: 0

{"id":null,"result":"f807d8dc25e82d2d457c0d2f1ee27ce7","error":null}%   
以POST形式向/cgi-bin/luci/rpc/auth地址发送格式为{"method":"login","params":["root","admin"]}的登录请求,其中参数params为路由器的帐号密码,路由器返回json,其中result的值就是token,在这里是f807d8dc25e82d2d457c0d2f1ee27ce7。

设置pppoe密码

$ curl -i -X POST -d '{"method":"set", "params":["network", "wan", "password", "123456"]}' http://192.168.1.1/cgi-bin/luci/rpc/uci\?auth\=f807d8dc25e82d2d457c0d2f1ee27ce7

HTTP/1.1 200 OK
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json
Cache-Control: no-cache
Expires: 0

{"id":null,"result":true,"error":null}%    
上面的POST请求向cgi-bin/luci/rpc/uci这个地址发送set方法,参数格式如下所示:
  • config: UCI config
  • section: UCI section name
  • option: UCI option or UCI section type
  • value: UCI value or nothing if you want to create a section
这里 params":["network", "wan", "password", "123456"]的参数即代表修改network->wan->password的值为123456。注意带上你的token,不然请求将返回403错误码。

获取pppoe密码

$ curl -i -X POST -d '{"method":"get", "params":["network", "wan", "password"]}' http://192.168.1.1/cgi-bin/luci/rpc/uci\?auth\=f807d8dc25e82d2d457c0d2f1ee27ce7

HTTP/1.1 200 OK
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json
Cache-Control: no-cache
Expires: 0

{"id":null,"result":"123456","error":null}%   
set方式,当然也有get方法,可以用以取得配置的值。

提交修改

$ curl -i -X POST -d '{"method":"commit", "params":["network"]}' http://192.168.1.1/cgi-bin/luci/rpc/uci\?auth\=f807d8dc25e82d2d457c0d2f1ee27ce7  

HTTP/1.1 200 OK
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json
Cache-Control: no-cache
Expires: 0

{"id":null,"result":true,"error":null}%   
注意,前面的set方法只改变了内存中配置的值,而 uci库中的commit即相当于把更改写入到配置文件。想让配置生效,这一步是不缺少的。

重启网络

$ curl -i -X POST -d '{"method":"exec", "params":["/etc/init.d/network restart"]}' http://192.168.1.1/cgi-bin/luci/rpc/sys\?auth\=f807d8dc25e82d2d457c0d2f1ee27ce7

HTTP/1.1 200 OK
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json
Cache-Control: no-cache
Expires: 0

{"id":null,"result":"","error":null}%  
访问/cgi-bin/luci/rpc/sys地址可以使用sys库各种方法。大致有以下几种:
call (...) Execute a given shell command and return the error code
dmesg () Retrieves the output of the "dmesg" command.
exec (command) Execute a given shell command and capture its standard output
getenv (var) Retrieve environment variables.
hostname (String) Get or set the current hostname.
httpget (url, stream, target) Returns the contents of a documented referred by an URL.
mounts () Retrieve information about currently mounted file systems.
reboot () Initiate a system reboot.
syslog () Retrieves the output of the "logread" command.
uniqueid (bytes) Generates a random id with specified length.
uptime () Returns the current system uptime stats.
sys库中exec方法可以执行系统命令,这里我们通过/etc/init.d/network restart命令重启网络,让配置生效。

Android端

需要RPC接口基本都介绍完了,接下来就是使用接口了,Android需要完成以下任务:
  • 界面显示
  • 给电信发送请求密码的短信
  • 获取电信返回的电信
  • 解析出短信中的密码
  • 调用openwrt的RPC接口修改密码
Android端目前基本已经可以用了,相关代码后续会开源出来。

参考


No comments:

Post a Comment