Sunday, 7 April 2019

Getting stats on command line from NetComm NF18ACV modem / router

Background

I recently bought a new VDSL modem / router when I switched NBN Internet providers.

The model I chose was the NetComm NF18ACV, partly because it has an SNMP agent.

The modem itself works great, except that the SNMP support is rubbish! There are no MIBs available for it, and running an snmpwalk against it reveals only basic info - nothing interesting like the line rate or whether the Internet connection is up or down.

So, I had a crack had getting the information available thorough the GUI from a Linux command line.


Setup

This has been developed and tested on the NFC18AV model, running firmware version NF18ACV.NC.AU-R6B016.EN.

Note that there is a newer "NC2" firmware version available now, with a new GUI - so what is described here will need to be reworked if using that version. But, then again, maybe the SNMP support is better in this model?

Commands below have been run from the command line on my Raspberry Pi running Raspbian GNU/Linux 9 (stretch), and also on my Synology NAS box.

How is this going to work?

This is the main screen you get after logging in to the GUI, with red boxes around the interesting bits of info:


What we want to do is get this info from the command line, using the wget command, the "non-interactive network downloader".

First attempt

Note: Examples from here on assume the router has the default IP address of 192.168.20.1

The "-O -" (dash, uppercase letter O, space, dash) here says to send the output to stdout.
pi@rpi3:~ $ wget -O - http://192.168.20.1 --2019-04-06 13:46:52-- http://192.168.20.1/ Connecting to 192.168.20.1:80... connected. HTTP request sent, awaiting response... 401 Unauthorized Username/Password Authentication Failed.

See the authentication failure. That makes sense - to get to the GUI from the browser, I get prompted for a username and password, but I have not given any credentials to wget.

Note (untested) that if you don't have a password set to login, the above command will probably work, and you skip forward a few steps.

You can specify your username and password (in plaintext, so can be a security issue depending on your circumstances) in the URL you pass to wget.

Second attempt

Assuming modem username is admin, and password is password:
pi@rpi3:~ $ wget -O - http://admin:password@192.168.20.1

OK, so now we get some output, however it is only the javascript code to generate the HTML frames for the main page - so not too useful yet.

Back in the modem GUI, if you hover your mouse over Device Info in the menu at left of screen, you see at bottom left of browser it shows you the link it is going to open if you click it - 192.168.20.1/info.html

So let's try doing a wget to that address and see what we get.

Third attempt

Adding "-q" this time, for "quiet" mode, to suppress some output from wget thst we don't need:
pi@rpi3:~ $ wget -q -O - http://admin:password@192.168.20.1/info.html

This is starting to look promising!

All the data seems to be there, but it's all a mess of javascript and html.

Parsing the output

In the middle of all that output is this bit:
  document.write("<tr>");   document.write("<td class='hd' id='wanInfoB0TrafficType'>B0 Traffic Type:</td>");   //document.write("<td>PTM</td>");   displaytracffictype(vartractype0);   document.write("</tr>");   document.write("<tr>");   document.write("<td class='hd' id='wanInfoB0Upstream'>B0 Line Rate - Upstream (Kbps):</td>");   document.write("<td>10809</td>");   document.write("</tr>");   document.write("<tr>");   document.write("<td class='hd' id='wanInfoB0Downstream'>B0 Line Rate - Downstream (Kbps):</td>");   document.write("<td>35323</td>");   document.write("</tr>");

Highlighted are the line rates as displayed in the GUI.

Mine is a VDSL connection on the B0 interface, so that is the section I have shown. Depending on your connection you may need to look in the B1, Bonded or ATM sections.

If you pipe the wget output through grep for "Line Rate", and add "-A1"  (grep -A1 "Line Rate") to also return the line after the matched line you get this:

  document.write("<td class='hd' id='wanInfoUpstream'>Aggregate Line Rate - Upstream (Kbps):</td>");   document.write("<td>10809</td>"); --   document.write("<td class='hd' id='wanInfoDownstream'>Aggregate Line Rate - Downstream (Kbps):</td>");   document.write("<td>35323</td>"); --   document.write("<td class='hd' id='wanInfoB0Upstream'>B0 Line Rate - Upstream (Kbps):</td>");   document.write("<td>10809</td>"); --   document.write("<td class='hd' id='wanInfoB0Downstream'>B0 Line Rate - Downstream (Kbps):</td>");   document.write("<td>35323</td>"); --   document.write("<td class='hd' id='wanInfoB1Upstream'>B1 Line Rate - Upstream (Kbps):</td>");   document.write("<td>0</td>"); --   document.write("<td class='hd' id='wanInfoB1Downstream'>B1 Line Rate - Downstream (Kbps):</td>");   document.write("<td>0</td>"); --   document.write("<td class='hd' id='wanInfoLineRateUp'>Line Rate - Upstream (Kbps):</td>");   document.write("<td>10809</td>"); --   document.write("<td class='hd' id='wanInfoLineRateDown'>Line Rate - Downstream (Kbps):</td>");   document.write("<td>35323</td>");
Looking at that, it appears that the "Aggregate" rate (to do with "bonding" the B0 and B1 interfaces?) gives the same result at B0 (and should match B1 if you were using that). So, for simplicity I will use the "Aggregate" rates.

Conclusion

What we have so far (splitting two pipeline commands over two lines with "\" for readability):
pi@rpi3:~ $ wget -q -O - http://admin:password@192.168.20.1/info.html | \   grep -A1 "Aggregate Line Rate"   document.write("<td class='hd' id='wanInfoUpstream'>Aggregate Line Rate - Upstream (Kbps):</td>");   document.write("<td>10809</td>"); --   document.write("<td class='hd' id='wanInfoDownstream'>Aggregate Line Rate - Downstream (Kbps):</td>");   document.write("<td>35323</td>");

A better way to parse the output, and just return the two line rates:
pi@rpi3 $ wget -q -O - http://admin:password@192.168.20.1/info.html | \ sed -n "/Aggregate Line Rate/{n;s/\(^.*<td>\)\(.*\)\(<\/td>.*$\)/\2/;p}" 10809 35323

This output is easier to manage and write to log files or return to network monitoring software (e.g. Nagios).

Notes on the sed command above:
  • "-n" - don't print input lines by default
  • "/Aggregate Line Rate/" - only interested in lines that contain this text
  • n - skip to the next line after the match
  • s/search expr/replace with/ - extracts the text between the td tags
  • p - print the resulting text

What next

The modem "Uptime" can be retrieved in a similar fashion.

In another post I'll show how to use the "node" command to interpret some of the javascript output and determine whether or not the Internet connection is up.

2 comments:

  1. Be gentle, this is my first ever blog post!

    ReplyDelete
  2. I'm using the current firmware NC2-R6B017 but this does not seem to work. I tried using curl and heaps of auth options but could not get it to auth. I then found your post at https://thebreamblog.blogspot.com/2019/05/netcomm-nf18acv-cli-scripting.html and got that to work.

    ReplyDelete