Closed mauermann closed 6 years ago
@juanriccio Yess, well, I will sysupgrade to snapshots/trunk to see if this is there.
I found some time to try and play with this idea. After studying @braian87b's suggestions and hints, I came up with a script to be run on the main router. Here it is.
#!/bin/sh
# includes the functions that we need to parse JSON files
. /usr/share/libubox/jshn.sh
case "$1" in
list)
echo '{ "mac2host": { "macaddr": "macaddr" }, "mac2ip": { "macaddr": "macaddr"} }'
;;
call)
case "$2" in
mac2host)
# read the argument
read input
# Load the argument into the json for retrieval
json_load "$input"
json_get_var mac "macaddr"
hostname=$(grep -i "$mac" /var/dhcp.leases \
| head -1 \
| cut -d' ' -f4)
echo "{ \"hostname\":\"$hostname\" }"
;;
mac2ip)
# read the argument
read input
# Load the argument into the json for retrieval
json_load "$input"
json_get_var mac "macaddr"
ipaddr=$(grep -i "$mac" /var/dhcp.leases \
| head -1 \
| cut -d' ' -f3)
echo "{ \"ipaddr\" :\"$ipaddr\" }"
;;
esac
;;
esac
I placed it in the MR's /usr/libexec/rpcd
directory, and it does work locally.
# ubus call mactranslate mac2host '{"macaddr": "00:11:22:33:44:55"}'
{"hostname":"android-123456abcd123456"}
How do I setup things on the AP's side? I need to incorporate the rpc call and resulting data into luci. I also need to set minimal permissions.
Run this only once on Main Router (to enable rpc calling from dumb AP's):
opkg update
opkg install luci-mod-rpc # brings luci-lib-json
/etc/init.d/uhttpd restart
/etc/init.d/rcpd restart
# if not works, then reboot:
ubus list | grep mac # check, should list `mactranslate` or `mac2host`
This too, its needed assing permissions (beware this will add full permissions to rcpd access, you should set as you need (read documentation to learn how)
cat<<'EOF' > /usr/share/rpcd/acl.d/superuser.json
{
"superuser": {
"description": "Super user access role",
"read": {
"ubus": {
"*": [ "*" ]
},
"uci": [ "*" ]
},
"write": {
"ubus": {
"*": [ "*" ]
},
"uci": [ "*" ]
}
}
}
EOF
Run this on some AP and point IP_HOST_MR
and PASSWORD
vars to your main Router
Run this only once:
opkg update
opkg install curl
Copy and paste this to test
rm /tmp/test_output.txt
IP_HOST_MR=192.168.1.1
PASSWORD=toor
. /usr/share/libubox/jshn.sh
JSON=$(curl -s -d '{ "jsonrpc": "2.0", "id": 1, "method": "call", "params": [ "00000000000000000000000000000000", "session", "login", { "username": "root", "password": "'$PASSWORD'" } ] }' http://$IP_HOST_MR/ubus)
json_load "$JSON"
json_select result
json_select 2
json_get_var SESION_ID ubus_rpc_session
JSON=$(curl -s -d '{ "jsonrpc": "2.0", "id": 1, "method": "call", "params": [ "'$SESION_ID'", "mactranslate", "mac2host", { "macaddr": "00:11:22:33:44:55" } ] }' http://$IP_HOST_MR/ubus)
json_load "$JSON"
json_select result
json_select 2
json_get_var FILE_DATA data
echo "$FILE_DATA" > /tmp/test_output.txt
cat /tmp/test_output.txt
/tmp/test_output.txt
contents (should say this if it worked fine):
{"hostname":"android-123456abcd123456"}
Please let me know about how it worked.
PS: With the luci thing I can't help since I do not know much about it.
Thanks, @braian87b! The scripts worked already. My question was mainly about luci integration and about the minimal permission thing. However, I guess I can run this with full permissions on the server (MR) side, so now it's probably just a matter of integrating and packaging.
Here are the scripts. On the MR:
#!/bin/sh
# mactranslate - script for master router
# examines dhcp leases
# and returns hostname and IP addr for a given macaddr
# includes the functions that we need to parse JSON files
. /usr/share/libubox/jshn.sh
case "$1" in
list)
echo '{ "mac2host": { "macaddr": "macaddr" }, "mac2ip": { "macaddr": "macaddr"}, "mac2full": {"macaddr": "macaddr"} }'
;;
call)
case "$2" in
mac2host)
# read the argument
read input
# Load the argument into the json for retrieval
json_load "$input"
json_get_var mac "macaddr"
hostname=$(grep -i "$mac" /var/dhcp.leases \
| head -1 \
| cut -d' ' -f4)
echo "{ \"data\":\"$hostname\" }"
;;
mac2ip)
# read the argument
read input
# Load the argument into the json for retrieval
json_load "$input"
json_get_var mac "macaddr"
ipaddr=$(grep -i "$mac" /var/dhcp.leases \
| head -1 \
| cut -d' ' -f3)
echo "{ \"data\":\"$ipaddr\" }"
;;
mac2full)
# read the argument
read input
# Load the argument into the json for retrieval
json_load "$input"
json_get_var mac "macaddr"
hostname=$(grep -i "$mac" /var/dhcp.leases \
| head -1 \
| cut -d' ' -f4)
ipaddr=$(grep -i "$mac" /var/dhcp.leases \
| head -1 \
| cut -d' ' -f3)
echo "{ \"data\":\"$hostname ($ipaddr)\" }"
;;
esac
;;
esac
On the AP:
# getmacinfo.sh - AP side script
# gets hostname and IP addr for a given macaddr from master router
usage=$(cat <<'END_HEREDOC'
getmacinfo.sh [options] <mac_addr>
options:
-h return hostname
-i return ipaddress
-a return "hostname (ipaddress)"
default: -a
END_HEREDOC
)
IP_HOST_MR=192.168.1.1 # the master router IP address
PASSWORD=toor # root password on master rouer
METHOD="mac2full" # default: "hostname (ipaddress)" string
while getopts ":ahi" opt; do
case $opt in
a)
METHOD="mac2full"
;;
h)
METHOD="mac2host"
;;
i)
METHOD="mac2ip"
;;
\?)
echo "$0 invalid option: -$OPTARG" >&2
;;
esac
done
shift $((OPTIND-1))
if [ $# -ne 1 ]; then
echo "$usage"
exit 1
fi
. /usr/share/libubox/jshn.sh
JSON=$(curl -s -d '{ "jsonrpc": "2.0", "id": 1, "method": "call", "params": [ "00000000000000000000000000000000", "session", "login", { "username": "root", "password": "'$PASSWORD'" } ] }' http://$IP_HOST_MR/ubus)
json_load "$JSON"
json_select result
json_select 2
json_get_var SESSION_ID ubus_rpc_session
JSON=$(curl -s -d '{ "jsonrpc": "2.0", "id": 1, "method": "call", "params": [ "'$SESSION_ID'", "mactranslate", "'$METHOD'", { "macaddr": "'$1'" } ] }' http://$IP_HOST_MR/ubus)
json_load "$JSON"
json_select result
json_select 2
json_get_var FILE_DATA data
echo "$FILE_DATA"
A sample incorrect call (performed on the AP):
# ./getmacinfo.sh
getmacinfo.sh [options] <mac_addr>
options:
-h return hostname
-i return ipaddress
-a return "hostname (ipaddress)"
default: -a
A correct call, again on the AP:
# ./getmacinfo.sh 00:11:22:33:44:55
android-123456abcd123456 (192.168.1.52)
All that's needed now is to get this bit of information in the "Associated Stations" table :smile:
This is amazing, I think now we should gain the atention of a experience developer of Luci to integrate this code and make it work... having this should be really easy to get done, may be this should be added to a package and we could get an experience package dev to help us.
It is really common to need to know and identify the actual device (not just their macaddress) when seeing the Web UI, and more than common to have a Main Router and several dumb AP's... should be great too to get on the Main Router info about in which one of many dumb AP's is connected which device... what do you think? ;)
Thank for improve and properly finish the scripts!
I found this, here is more info about ACL's: https://wiki.openwrt.org/doc/techref/ubus#acls
@braian87b wrote:
should be great too to get on the Main Router info about in which one of many dumb AP's is connected which device... what do you think? ;)
I agree - however, it's not as simple. I can't think of a way to do this efficiently, without lots of querying or automatic, timed notifications. The matter is I don't know the system, in particular all the system hooks that probably are already in place and could make this an easy task.
I found this, here is more info about ACL's: https://wiki.openwrt.org/doc/techref/ubus#acls
Aha, thanks! I'll read that doc. Hopefully, I'll figure out how the ACL business works and possibly update the scripts accordingly.
I think this (MAC -> address translation) would be a useful feature, but getting it work will take some significant time and testing. One issue is that you have to handle the case where main router is not a version with OpenWrt/LEDE that can communicate the addresses to the the AP's, and on networks without IP addresses (i.e. pure bridges) the AP won't have the information most of the time.
Hi, in my opinion its not a problem on "networks without IP addresses / pure bridges"... actually the several test on scripts that @juanriccio and me performed is more than sufficient to gather the information on dumb AP's and send it to (or get if from) the Main Router (the one with dhcp) and save it somewhere (we could have a plaintext tab-delimited or sqlite, is more than enough) and then in luci check if that plaintext or sqlite is available and then show as an extra column or instead of macaddress (the macaddres could remain in a tooltip) or even put it as a tooltip or even in a separate new page.
I think that what just we need is to create a init.d script (to act as a pseudo daemon and update the info when a new host appears, and put a minimal uci config and then put it all together in a new package and make it available, I can promise to try to get some init.d work and publish here the final files, but as we previusly talked about with @juanriccio some messages ago # we need someone who knows both, how to put the info in luci, convert into a package and with access to publish as package in the official repositories.
in the Main Router:
opkg update, opkg install luci-macaddr-to-name macaddr-to-name
(one for adding luci info page, and one for daemon that updates the tab-delimited or sqlite db)
on the Dumb AP's (or in the main router too if it acts as AP too):
opkg update, opkg install macaddr-to-name-ap
What do you think?
@braian87b Unfortunately, I think I may have some rain on this optimism:
1) Assumes both 'dumb' AP and main router are both running on versions or LEDE/OpenWrt with package included. 2) Security & stability: how exactly are you transferring these files, ensuring integrity etc.? 3) Really the transfer part probably belongs in packages feed 4) Need someone with time/resources to put in this who has (or can acquire) the necessary skills.
Thoughts?
Since today it's Friday, and I do not usually be ironic, but yesterday I saw some videos of Linus Torvals and I just started thinking about how, maybe, he would answer this message, I hope do not take this as offense, it's just to add a little incentive, I am already too happy with OpenWrt and do not need more, but as I am happy I just want to give my time to help to improve it my own 'grain of salt'. 👍 :)
if
instructions is too much for this feature@braian87b I'm not entirely sure what you mean by some of what you've said, but:
1) True, but that means it's not a useful as a more general solution 2) Erm, actually there are wireless attacks that work, depending on certain factors, and most users don't know what factors matter. 3) Optional is fine, however see 4) 4) I don't know about others working on LuCI but I am not paid to develop this, nor do I have any obligation except my personal motivations to work on this, and I personally already have plans for working on a number of issues and PRs from the community that I consider higher priority. However, this is opensource, if you can't do it yourself, hire someone with the skills to do it, and submit a PR with an Apache License (v2) and it'll get reviewed and have either requests for appropriate changes, or integrated (assuming there are enough active developers to be able to do that; if not, new blood is needed or the project will die).
2) Oh as for nmap and such, point taken, however that is not my real concern; my concern is how dumb router accesses the data (I haven't read your code, besides I'd like to hear you explain the design), or the main router pushes the data to the dumb router. Also where is the main router storing the file? It'd be bad to write to limited write flash for this, and if it's on e.g. /tmp, how does it get from there to the dumb ap?
@braian87b Sorry missed your ubus calls and script earlier - it's a long thread and I missed parts (only recently started looking at outstanding issues).
@braian87b I have concerns about the implied use of passwords with access to the main router (what permissions and how is that managed) on every dumb router.
Sorry for the misunderstanding...
As I actually misunderstood the main -> ap, ap -> main info sent/get... I think that if someone from luci can create a text file with the info and luci package that shows that then other (me and others) can make what is needed to populate that file...
for starting, can populate that file using /tmp/dhcp.leases and get from there, macaddress, ip, hostname from that file, then we could get static ip/host from dhcp.@host[x], /etc/ethers and later with computers that have actually configured in-place a static ip then will have to use a arp or reverse dns query or nmblookup -A 192.168.1.100
(that returns the hostname using netbios query).. or fill a list or file manually, etc, etc. This is because I insist that we should get this info from a new dedicated file, because will be more easily to fill that file from several places instead of add to too much overload in luci reading data from many sources or reading incomplete data from just one source...
As this info changes from time to time I think that should not be saved on firmware, should be on /tmp and if someone wants to persist it change the path to extroot or another mounted filesystem.
If all of you are keeping interesting in this I could take some time to think more about a proper and better design to get this idea more complete.
@braian87b Sorry for misunderstanding your request as a push for work. I still have concerns about the security aspect and am not a fan of the 'start insecure, we'll figure out the security later'; I like to at least know it's not a permanent hole. The problem with /tmp is that is is not accessible from /www which is where uhttpd accessible files live and I'm not keen on the ubus mechanism you describe. If someone disabled symlinks you can't symlink from /www to /tmp either. I think there are some challenges you haven't yet considered. Even though it's technically gatherable data I'm not convinced that means unauthenticated access is a good idea, or access via plaintext (or obfuscated but plaintext when used) password on devices is wise. At the very least this should easily turned off, and be done using nobody:nogroup for the service providing the informaiton (i.e. unprivileged user).
@cshoredaniel Interesting, I didn't know the /tmp <-> /www limitation I will keep in mind that. I don't want to push people to work, just ask for anyone who wants to contribute, but just if they want to, and they are actually interested in this. The data that will travel now will have a list of ip<>macaddress(<>hostname) that info could be read only by devices actually inside the network, and if some device is already inside the network can actually read and get same data using tools like arp and nmap... as I said, if someone here has knowledge in C programming I think it could easily write a daemon with ssl and problem solved... I think reading the data could not be a problem, the problem is when in a more serious implementation can happen something like bad people faking the data (the data will just be presented to a user in luci) but don't know how important will actually be in that implementation, I think this is worse actually. Is like to have luci using http/80 and have to configure it to use https/443... We first need to get a first version of the idea working and if it works well and the testers of the trunk branch are interested in having the feature probably more people will want to contribute patching and improving the code and even rewrite the entire code to C with security in mind, etc... The ubus mechanism was just a "test", actually that day I was testing that because I wanted to know if it was possible to get info from an OpenWRT box without using ssh, was just a coincidence same day that I found this conversation. We should leave this idea here, hope someone would be capable in the future to improve the idea and describe it better than me. I am not expert on OpenWRT, but since I use it I want to contribute. Thanks for the interest! :) 👍
Hehe, if you read my first message on this topic, that message have my only main concern about this topic (actually the later data interchange thing was just a night experiment playing with a openwrt box at hand) https://github.com/openwrt/luci/issues/540#issuecomment-244476594 I think that is the thing that we need to talk about and decide if is better to have it in separate file, or read from multiple files... What do you think ? I think we should delete our coments and put the relevant info in just simplified in just one message, all these comments just added noise to this conversation.
@braian87b Could you open a separate issue with only the relevant bits for that one topic? That doesn't seem like something you'd be blocked on.
@braian87b actually can you move those bits to #724
this is more useful information, when you can have overview of all interfaces in one screen. rest is just bullshit
@psyborg55 please expland your explanation, which information are you saying that is more useful?
i recently installed OpenWRT on my WDR3600 but i cannot understand why i cannot sees this upgrade, hostnames/ips are still missing in the Associated Stations list
Firmware Version | OpenWrt Chaos Calmer 15.05.1 / LuCI 15.05-149-g0d8bbd2 Release (git-15.363.78009-956be55)
opkg update / opkg list-upgradable show nothing... is there something that i have to do to upgrade LuCI?
@jow- Why did you close this ?
The original request has been solved (additional info is now there). The discussion later seems to be a feature request nobody is working on. I do not plan to implement inter-access-point device queries.
It seems there is a desire to have the hostnames displayed in the "Associated Stations" section. Could this be read from /etc/dnsmasq.conf or /etc/config/dhcp ?
Both those files can contain records for MAC and IP addresses and hostnames.
This already happens. The issue is with dump AP setups which do not act as DHCP server or router themselves. Such devices will never have L3 connectivity with their wireless clients and thus no info about associated IP addresses or host names.
The main problem relies that for humans (the ones that uses Luci Web UI) there is no correlation to mac address, so, I will be useful if we can have some sort of known devices list that Luci can use it to translate the mac address to a user defined name... The hostname translation it could be an initial data fill. But it will be better if user can define each one by itself...
so, if you could have "xx:xx:xx..." -> "Bob iPhone" "xx:xx:xy..." -> "Alice Notebook" "xx:xx:xz..." -> "Alice Samsung Galaxy S9" "xx:xx:yy..." -> "Alice iPad" "xx:xx:yz..." -> "Bob Thinkpad"
in the way:
xx:xx:xx\tBob iPhone\n
xx:xx:xy\tAlice Notebook\n
xx:xx:xz\tAlice Samsung Galaxy S9\n
xx:xx:yy\tAlice iPad\n
xx:xx:yz\tBob Thinkpad\n
We just NEED that some Luci Developer could make the necessary to read some file at /tmp/macaddresses_aliases and do that translation if the macaddress is found on that list (and leave the mac address between parenthesis or in hover tooltip, and do for DHCP leases and for stations at least. If the sysadmin fills that file with whatever script they want...
It is this difficult to do? please It would be REALLY USEFUL!
You can achieve that already by declaring static DHCP leases without IP addresses.
Another possibility is writing a record to /etc/ethers
.
The following line would assign the name example
to the MAC 00:25:9C:2B:58:DE
. LuCI processes this file and will use it for name hints when displaying wireless stations:
root@OpenWrt:~# cat /etc/ethers
00:25:9C:2B:58:DE example
No, sorry but we don't want to get involve in this dnsmasq or other OpenWRT component or even deal with defining hostname that could convert later in problems.
Then just use /etc/ethers
. Simply supply a name instead of an IP address for the MAC.
OK, I will try that. Can that have spaces ? Does it work for the dhcp leases and stations listings?
You wanted a file in the form xx:xx:xx\tBob iPhone\n
this is exactly what /etc/ethers
is. First column mac, second column hostname or IP.
/etc/ethers is a network system file, we want a file that just involves Luci, and nothing else. so we can play with it using scripting, etc.
Then use the workaround to declare a static DHCP lease without IP address in /etc/config/dhcp
:
config host
option name 'fairphone'
option mac '6c:ad:f8:43:40:fb'
Such entries are ignored by dnsmasq and recognized by LuCI as name hints for MAC addresses.
what is a "hint" it wil replace the macaddress by the defined "name" on Luci ?
Luci isn't getting huge amounts of dev at this time--not too many people volunteering to work on it (i.e. people with the skill offering their time and effort for free), and no one seem to wants things badly enough to hire someone to get it done and submit to OpenWrt's LuCI feed.
For volunteers who actually care about the GUI, I think there's little desire to work on old (current) LuCI because the goal is move to luci-ng; but AFAIK luci-ng isn't far enough along for folks to use it as the main GUI, and then build their favourite app on top.
My 2 cents.
@jow - cool hack. I didn't know I could do that. Solves an old problem of mine identifying some old 11b devices on my home network. THANKS
Oh and I do plan on helping the situation by getting to the effort that was on hold while I was ill, of splitting up LuCI and having some sort of LuCI + luci-ng hybrid to smooth the transition. I'm hoping that a) work and b) make it easier to transition instead of having this chicken and egg problem.
@cshoredaniel Thanks for that info, I didn't knew that.
I have records such as this one in /etc/dnsmasq.conf, but they don't work as hints for Luci:
dhcp-host=b8:27:eb:34:cc:2d,192.168.0.40,raspberrypi1
Is it because Luci doesn't read /etc/dnsmasq.conf (only /etc/config/dhcp), or is it because they contain IP addresses?
@braian87b, that's what you want, and the way you want it. I don't mind using /etc/dnsmasq.conf, and as a last resort, I won't mind using /etc/config/dhcp.
And please don't interrupt the thread with your "last time" ultimatum. I would like to receive an answer to my question, and learn from it.
@oavaldezi Luci doesn't read custom dnsmasq.conf. (Lua UCI is where Luci names comes from; dnsmsaq.conf is not uci format and most of Luci revolves around uci configurations (there are exceptions, especially in newer code, and especially for status information). Anyway dnsmasq.conf is not how Luci is built to understand/use dnsmsaq (except by way of generating .conf files from uci configuration, but it's the uci configuration that is understood, not the .conf). HTH.
@jow- @hnyman FYI I've started on the 'low-hanging fruit' for moving things into separate apps instead of all in mod-admin-full and such, and as it happens I picked on the the hostnames definition. Ironically, except for the fact that they live in /etc/config/dhcp there is nothing about the definitions that is specific to dnsmasq (or unbound, or odhcpd, etc), which I found interesting. @EricLuehrsen might be especially interested in this since I thing for unbound the only thing he picks up from /etc/config/dhcp is the hostnames (as DHCP becomes a separately handled entity).
@EricLuehrsen is there anything your unbound work uses besides hostnames from /etc/config/dhcp?
Thank you @cshoredaniel . Your answer made me read about UCI, and I learned that its configuration files are kept in /etc/config/
. That precludes using /etc/dnsmasq.conf
.
I'll try the workaround suggested above by @jow- : to declare a static DHCP lease without IP address in /etc/config/dhcp
@jow I am wondering if there is a way to preserve the translation work when making these changes (it'd not be so good to lose translations because of moving things around).
@cshoredaniel Unbound UCI attempts to mimic dnsmasq UCI features OpenWrt community is accustom to. It uses /etc/config/dhcp
to figure out which interfaces are DHCP (LAN) and which are not (WAN). It optionally will snoop for configured pairing with dnsmasq. It will optionally pull the domain
, mx
, srv
, and cname
records originally intended for dnsmasq. But as for base DHCP, why wouldn't predetermined host names or address assignments be in that file? That would seem to be a natural location.
@EricLuehrsen to clarify: at present my changes shouldn't be 'user-visible'. They are aimed at being 'under-the-hood' AND don't change the underlying UCI configs. The idea is to decouple the various parts of the UI so that one can pick and choose.
It would be nice if the "Associated Stations" table would show more useful information. e.g. with dual band radios getting more common it would be interesting to see the radio a station is associated. Also, instead of remembering MAC addresses, I think it's better to see its hostname or IP address.
Attached screenshot shows my proposed changes with columns for hostname and radio added. Unfortunately because of table width I had to drop the Noise column. However, this is less important for me.
I'm sure it needs some work and discussion, so it's probably too early to submit a pull request... ;-)