Managing OpenWrt remotely with cURL
OpenWrt is a free open source Linux distribution for routers.
One of the main benefits of OpenWrt is the level of access you have over
standard router firmware. This post is going to look at using the
luci-mod-rpc
module to manage OpenWrt over HTTP.
Installing luci-mod-rpc
The luci-mod-rpc
module needs to be install. To do this you can run the
following commands over SSH:
opkg install luci-mod-rpc
/etc/init.d/uhttpd restart
Alternatively you can install the package using the web interface by going to
System -> Software
and restart uhttpd
from the System -> Startup
page.
Requesting an API token
API calls require a session token. To request a new token make a request to the
auth
API endpoint:
$ curl -X POST http://192.168.1.1/cgi-bin/luci/rpc/auth --data '
{
"id": 1,
"method": "login",
"params": ["root", "secret_password"]
}'
This will return JSON with a token similar to the following assuming the authentication details are correct:
{"id":1,"result":"a191c1c171c210def536e5279ed0c67f","error":null}
Note: the authentication details should normally be the same as the details for the LuCI web interface.
Calling the API
At the time of writing there are currently four API end points besides the auth API:
/cgi-bin/luci/rpc/uci
/cgi-bin/luci/rpc/fs
/cgi-bin/luci/rpc/sys
/cgi-bin/luci/rpc/ipkg
The OpenWrt wiki briefly documents the available endpoints, however it's worth referring to the LuCI docs on GitHub for more information on the API calls being exposed.
Universal Configuration Interface
Universal Configuration Interface or UCI for short is an easy way to configure OpenWrt. If you're not already familiar with UCI the OpenWrt docs are a good place to go for further info.
The get
method can be used to check configuration values:
$ curl -X POST http://192.168.1.1/cgi-bin/luci/rpc/uci?auth=a191c1c171c210def536e5279ed0c67f --data '
{
"id": "1",
"method": "get",
"params": ["luci", "sauth", "sessiontime"]
}'
This will return output similar to the following:
{"id":"1","result":"3600","error":null}
You can also set configuration, for example:
$ curl -X POST http://192.168.1.1/cgi-bin/luci/rpc/uci?auth=a191c1c171c210def536e5279ed0c67f --data '
{
"id": "1",
"method": "set",
"params": ["luci", "sauth", "sessiontime", 7200]
}'
File system access
The fs
endpoint calls the nixio.fs
library. This can be used to interact
with files on the file system. For example the metadata associated with a file
can be checked using the stat
method:
$ curl -X POST http://192.168.1.1/cgi-bin/luci/rpc/fs?auth=a191c1c171c210def536e5279ed0c67f --data '
{
"id": "1",
"method": "stat",
"params": ["/etc/hosts"]
}'
It's also possible to read and write files. For example you can use readfile
to get the contents of /etc/hosts
:
$ curl -X POST http://192.168.1.1/cgi-bin/luci/rpc/fs?auth=a191c1c171c210def536e5279ed0c67f --data '
{
"id": "1",
"method": "stat",
"params": ["/etc/hosts"]
}'
The returned JSON should hopefully look similar to the following:
{"id":"1","result":"MTI3LjAuMC4xIGxvY2FsaG9zdAo=","error":null}
The result can then be decoded:
$ echo MTI3LjAuMC4xIGxvY2FsaG9zdAo= | base64 --decode
127.0.0.1 localhost
Note: unless you have the luasocket
module installed you may get an error
similar to the following:
{
"id":"1",
"result":null,
"error":{
"message":"Invalid params.",
"data":"/usr/lib/lua/luci/controller/rpc.lua:110: attempt to call global 'error' (a nil value)",
"code":-32602
}
}
Making system calls
The sys
endpoint exposes methods from several libraries including luci.sys
,
luci.sys.process
, and luci.sys.net
. By default the endpoint will assume
calls are being made to the luci.sys
library. For example the exec
method
could be called with a curl command similar to the following:
$ curl -X POST http://192.168.1.1/cgi-bin/luci/rpc/sys?auth=a191c1c171c210def536e5279ed0c67f --data '
{
"id": "1",
"method": "exec",
"params": ["echo 'hello world'"]
}'
A prefix can be added to the method name to call methods from other sys
libraries. For example if you wanted call the arptable
method from
luci.sys.net
you could use a command similar to the following:
$ curl -X POST http://192.168.1.1/cgi-bin/luci/rpc/sys?auth=a191c1c171c210def536e5279ed0c67f --data '
{
"id": "1",
"method": "net.arptable",
"params": []
}'
Managing packages
The ipkg
end point can be used to managed installed software. For example you
could check if luci-mod-rpc
is installed with a command similar to the
following:
$ curl -X POST http://192.168.1.1/cgi-bin/luci/rpc/ipkg?auth=a191c1c171c210def536e5279ed0c67f --data '
{
"id": "1",
"method": "installed",
"params": ["luci-mod-rpc"]
}'
The command above should return the following JSON:
{"id":"1","result":true,"error":null}
Note: Unfortunately several methods such as list_all
use a call back
function instead of returning data. This makes them fairly tricky to call with
the RPC API.