Per-user traffic monitoring on OpenWRT

By | December 3, 2010

Today I had cause to want to track the per-user (per-MAC address, really) traffic counts on an OpenWRT-based router. There’s nothing I could see that was built in, so I dug around and found wrtbwmon, which is a pretty good script for this sort of thing. However, it doesn’t work with the OpenWRT version I’m running (Backfire (10.03, r20728).)

So here I document what I had to do to make it work.

To start with, grab my version of the script itself from here. I put this into /usr/local/bin on the router, and made it executable (chmod +x /usr/local/bin/wrtbwmon.)

Using crontab -e, add the following (modified as you like) to the crontab:

* * * * * /usr/local/bin/wrtbwmon setup br-lan
*/5 * * * * /usr/local/bin/wrtbwmon update /tmp/usage.db
1,6,11,16,21,26,31,36,41,46,51,56 * * * * /usr/local/bin/wrtbwmon publish /tmp/usage.db /tmp/www/usage.htm /usr/local/lib/macusers.txt
3 0 12 * * rm -f /tmp/usage.db
7 */6 * * * cp /tmp/usage.db /usr/local/lib/usage.db.bak

(the one with all the numbers is actually one long line, it may wrap on this page)

Line 1 sets up iptables to track everything it sees on the network, 2 and 3 save and write out the data every 5 minutes, and 4 resets the database when the monthly transfer quota resets. The last line backs up the database to flash every 6 hours, so that in case of power failure at most 6 hours of data are lost. The script expects the backup to be found in /usr/local/lib/usage.db.bak, so if you alter this, you’ll have to alter the script.

Running /etc/init.d/cron restart may be needed here to make the cron daemon reload the new commands.

Set up /usr/local/lib/macusers.txt to map MAC addresses to users to give a nicer output. For example:

00:aa:bb:cc:dd:ee,Person 1
11:22:33:44:55:66,Person 2

The MAC addresses should be lower case.

In /www/cgi-bin/usage I put:

echo 'Content-Type: text/html'
echo 'X-Dummy: dummy'
cat /tmp/www/usage.htm

The dummy header line is needed to work around a bug in the uhttp version on the router. chmod +x this also.

Now, you can go to http://IP_OF_ROUTER/cgi-bin/usage and it’ll give you an HTML table showing who’s been uploading and downloading what. Good for finding out who hasn’t capped their torrent client’s upload speed.

Update: added the backup cron job, updated the script to restore the backup if needed, also now adds totals to the display.

26 thoughts on “Per-user traffic monitoring on OpenWRT

  1. Andrew

    Thanks for updating this to work with recent versions of OpenWRT. Much appreciated.

  2. JACKY

    It worked, thank you. but we still want to add this page in LUCI main page, could you do that?

  3. Robin Post author

    I haven’t meddled with this in a while, but I can’t imagine it’d be too hard, ideally you’d just be able to edit the templates that LUCI uses.

  4. Mr Andreas

    Yay! I got it working once I understood that /www/cgi-bin/usage was a file I had to create, doh!!! 🙂

    Now I must try to figure out how to get totals per row as well as keeping daily summaries for two months… 🙂

    P.S. MAC addresses in macusers.txt must be lower-case, not upper-case as per the example above (or the usage information in the script itself)…

  5. Robin Post author

    Good to know, I’ll update with a note to that effect. Curiously, I don’t remember having that issue, but I was probably cut-and-pasting from elsewhere which was correctly formatted.

  6. Stephen

    Thank you so much, this is exactly what I have been looking for for quite some time.
    Why back it up? Why not just store it directly to flash? Does the script do IO too frequently?

  7. Pingback: OpenWRT and the Bandwidth Monitoring Script « itas171bandwithmonitoring

  8. Achim

    Thank you for this great script!

    This morning I was wondering why the counters didn’t have been reset as it should be because of line four of the cronjobs. The reason for this is the backup/restore functionality you added to the script later:

    # Restore this from a backup if needed
    [ ! -f “${2}” -a -f /usr/local/lib/usage.db.bak ] && cp /usr/local/lib/usage.db.bak ${2}

    So with active backup/restore functionality the script restores the backup if it is missing. To force an intended counter reset we have to create a new blank file, so replace line four of the cronjobs with the following one:

    3 0 12 * * rm -f /tmp/usage.db && touch /tmp/usage.db

  9. Afzal Najam

    Thank you very much for this! 😀

    And for giving me a reason to investigate how crontab works 😀

    A little modification that I made to the crontab is:
    3 0 1 * * mv -f /tmp/usage.db /usr/local/lib/usage_$(date +%b_%Y).db
    7 */2 * * * cp /tmp/usage.db /usr/local/lib/usage.db.bak

    Make a backup of the database instead of deleting it every month, save by month-year.

    And make a backup every other hour instead of every 6 hours 🙂

  10. Alex

    Hi! I noticed if I add more that 1 line MAC,User in macusers.txt then it stops working, if I leave the txt file blank then I see only MACs in statistics table! Can anyone fix it? Thx!

  11. Kyle

    Thank you very much. Was looking for something exactly like this and with a few changes worked perfectly for me. I appreciate it.

  12. Eric

    Thank you for your share, I try the script, but Offpeak download & Offpeak upload doesn’t work, my openwrt version: OpenWrt Backfire 10.03.1 ?thank you !

  13. Gavin

    Thanks so much for posting this. I tried another version of this without success, but this one worked perfectly. Legend…. wait for it…..

  14. Amir Khan

    Hi, the script work fine on my openWrt setup.
    I would like to know how to reset the settings in iptable if I want to uninstall the script. I would be nice to add ‘uninstall’ or ‘remove’ or add a setup to backup the firewall setting that we can revert back to if decided to uninstall it.

  15. Mark

    Got this up and running so we can hopefully work out what is using most of our data allowance. I had a problem with the mac list like Alex above but sorted it out by setting the EOL format in that file to unix type (LF). I think most text editors on windows default to the combined CR/LF format. This can be converted in Notepad++ with Edit -> EOL Conversion -> UNIX/OSX Format.

  16. MikeW

    I found a major flaw in the script – at least for the OpenWRT variant I was using (ROOter FunnelWeb).

    I found that the script would create multiple entries in the FORWARD chain, each for the jump into the RRDIPT chain. And then multiple entries in the RRDIPT chain for individual IP addresses.

    The first causes packets/bytes to be double-counted, triple-counted etc. The second causes problems when taking data to put into the .db file.

    Cause: sometimes the iptables command would fail, because of an “xtables lock”.
    Solution: add the “-w” option to each invocation of iptables

  17. MikeW

    But otherwise a great script – just what I was looking for!

  18. Justyn

    @pb – Could I potentially just copy / paste the wrtbwmon script you made and overwrite the current one from this site, and everything will work? Or will I have to make changes to location lik /usr/lib/ e.t.c?

  19. SomebodyThatIUsedToKnow

    Why are you running the setup command every minute ? It’s sufficient to run it once at boot.
    In /etc/rc.local.

  20. Robin Post author

    It’s a long time since I wrote that, but it was probably to deal with the firewall rules changing or something.

  21. SomebodyThatIUsedToKnow

    Hehe yes I only noticed the date after commenting. Anyway, it should have felt good for you that after 7 years, people still find this post useful.

    And thanks for the clarification.

  22. Chross

    Hey guys,
    i am very new in this field and just installed openWRT on a WRT1200AC. I only have a windows pc available. do i have any chance to install this skript on the router anyway? I apologize for any potential stupid question asked and hope for help. 😀

  23. Robin Post author

    hmm, I’m not sure. It might work, but it’s been many years since I wrote that, and a similar length of time since I needed it. So you might get lucky it it’ll work out, but I promise nothing 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *