Aug 202016
 

Motivation

Melbourne just won the “most liveable city 2016”, the 5th time in a row.
That’s awesome, but it comes with a price, and the one you’d think of: internet here sucks!

Sounds weird, isn’t it?
Well, one of the reasons Melbourne is such a great city, is it’s size, the amount of people in it and the direct result of very low capita per square meter. In simple words, it means we live very far from each other, which means we live far from the ADSL Exchange and for some of us, even only tens of Kms from the CBD (“downtown”), it’s too expensive and even not available to ADSL connection to their property.
I happen to have such friends.
Their only solution is to use 4G connection. Surprisingly, since it’s a new technology unlike ADSL, it’s quite good. But it has a limit: amount of traffic and the cost of excess usage.

Why am I blabbing about it? Cause I can… Nah, mainly case this is the reason for me to create this little project.
For them, having kids, they need to control their usage and know who of the kids has youtube their 4G to a very expensive invoice.

I was looking at already existing tools, mainly around linux, and could find many real-time cli tools (love cli tools!) like nload, iftop, nethogs, jnettop and more.
But thsoe are real-time tools and I need a long-time tool.
ntop is the next on the list, and it’s even running on RPi. I’ve checked. The problem with it: it’s not keeping old traffic for ever. you cannot see what happened even few hours ago if the stream is gone.

I decided I’ll build one.
In the light of my K.I.S.S philosophy, I made it to suit my needs, made it simple, easy to use and install with no frills.

How to

So, the way it works is very simple. The assumption is you already have a router connected to the internet and provide access to your machines either via Ethernet or Wifi.
Also we assume you have an Ethernet port available on the router (Wifi will probably work, but I didn’t try).
You have a RaspberryPI (aka RPi) or similar linux machine. My instructions below are for RPi, but will work for all distos with some tweaks.

Network Diagram

That’s how you’d hook it up; the RPi is just another machine inside your network, but then router internal DHCP should be disabled, allowing the RPi provide DHCP for the network.
That means it can advertise itself as the default gateway for all the end machines, ensuring all the traffic passing through it.

Installing and setting up your RPi

At the time of this post, the image I’m using for my RPi model 3 is: 2016-05-27-raspbian-jessie-lite.img

Following the first boot, extend the file system, set “pi” password, set Internationalisation Options and reset your root password. Instead of running everything with sudo (the right way to use linux), I’ll just run everything as root (the wrong way to do it. I’m lazy. Sue me!).
When your RPi is back up, login as root and follow this:

If you’d like to get your wifi network up

vi /etc/wpa_supplicant/wpa_supplicant.conf

Add

network={
	ssid="MyWifiNetworkName"
	psk="MyWifiPassword"
}

During the setup, you’ll be asked for MySQL password, set it to “123”

apt-get update
apt-get htop vim install tcpdump nload iftop mysql-server-5.5 python-mysql.connector php5 php5-mysqlnd python-netaddr isc-dhcp-server git

vi /etc/vim/vimrc

Remove comment

syntax on
mysql -p123
mysql> set password for root@'localhost' = password('');
mysql> grant all privileges on *.* to root@'%' with grant option;
mysql> create database network;
mysql> quit

vi /etc/mysql/my.cnf

Add comments and add the line

#query_cache_limit      = 1M
#query_cache_size        = 16M
innodb_buffer_pool_size = 100M
vi /root/.bashrc

Remove comments and add the line

# You may uncomment the following lines if you want `ls' to be colorized:
export LS_OPTIONS='--color=auto'
eval "`dircolors`"
alias ls='ls $LS_OPTIONS'
alias ll='ls $LS_OPTIONS -lha'
alias l='ls $LS_OPTIONS -lA'
#
# Some more alias to avoid making mistakes:
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias killSniffer='pkill -9 -f "python /usr/local/bin/sniffer.py"; killall -9 tcpdump'
. /root/.bashrc

vi /etc/php5/apache2/php.ini

Change

short_open_tag = On

You can use git or download the zip and extract it here

service apache2 restart
cd /var/www/html/
git clone https://github.com/ronenb75/NetworkTrafficAnalyzer.git
mv NetworkTrafficAnalyzer network
ln /var/www/html/network/python/sniffer.py /usr/local/bin/sniffer.py

vi /etc/crontab

Add

*/1 * * * *     root    /usr/local/bin/sniffer.py 2>&1 &> /dev/null

Setting up the network. Adjust to fit your own network, based on your original router settings

interface eth0
	static ip_address=192.168.0.230/24
	static routers=192.168.0.1
	static domain_name_servers=8.8.8.8
rm /etc/dhcp/dhcpd.conf
vi /etc/dhcp/dhcpd.conf

Again, adjust according to your network

authoritative;
ddns-update-style interim;
ignore client-updates;

subnet 192.168.0.0 netmask 255.255.255.0 {
	range 192.168.0.101 192.168.0.200;
	default-lease-time 86400;
	max-lease-time 86400;
	option routers 192.168.0.1;
	option ip-forwarding off;
	option broadcast-address 192.168.1.255;
	option subnet-mask 255.255.255.0;
	option domain-name-servers 8.8.8.8;
}
vi /etc/sysctl.conf

Uncomment

net.ipv4.ip_forward=1

Create a iptables rule for the RPi to act as a router

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
vi /etc/network/if-up.d/iptables
#!/bin/sh
iptables-restore < /etc/firewall.conf
chmod +x /etc/network/if-up.d/iptables
iptables-save > /etc/firewall.conf

That’s it. Reboot your RPi, hook it up to the router (if it’s not already is. Make sure the wifi network is not enabled, otherwise the DHCP will be served on both interfaces. Not good…) and it will start collecting network.

Looking at the stats

Now you access from any browser (I hope) to the RPi http server, in our case: http://192.168.0.230/network

You suppose to see something like:

Well, it’ll take some time to fill, but you get the idea.
Now, I created few nice things here:

  • If you click on an IP, you’ll be able to provide an alias for this IP
    Clicking <enter> or anywhere outside the text box will update the name. Note: the name will not be update in the table until refresh (was too lazy to do that. Maybe in the future).
    <ESC> will close the update box with no update. Deleting the text content, leaving it empty will delete this alias.
    NetworkScreen02
  • Clicking on the DNS resolve area will open a new whois lookup browser window
    NetworkScreen03
  • Click on the expand icon will open a list of the source IPs to this destination IP, and how much traffic each consumed
    NetworkScreen04
    NetworkScreen05
  • Double click on the delete icon will allow to delete ALL the records with the chosen ip as either the source or the destination. This operation cannot be undone!
    NetworkScreen06

Conclusion

I found some interesting information collecting data for few days. Finding out my kids are using much more internet them me.
Bare in mind I am not a PHP or Python professional developer, so I guess my code is far from being elegant.
I’m also graphically and visually challenged, meaning the graphical design is probably even worse the my coding.

But it works for me. And it’s not resource hungry.
I hope you’ll find it useful.
Any comments, please feel free to drop me a line.

Codes are hosted in my newly open github repository: https://github.com/ronenb75/NetworkTrafficAnalyzer

Sorry, the comment form is closed at this time.