en fr

MindYourNeighbors

Posted on mar. 07 mars 2017 in admin sys

I wrote, packaged and just finished testing MindYourNeighbors, a piece of software which allows you to run scripts depending on your network neighborhood.

Why ?

Several years ago, I used transmission on a machine at home; it was running constantly. Transmission has a turtle mode which reduce its network bandwith consumption when it’s activated. I triggered that mode which two cron lines. I set them so they would trigger the “turtle” mode when I knew they were people at home. For various reasons, it becomed uneasy to anticipate the period when there was nobody’s home and so, in the end, transmission was always in its turtle mode.

And so, why ?

So, instead of using cron, I wrote a small script that watches the neighbors table and decide if it can run or not a script that’ll set or unset the transmission turtle mode. After that I just made it so that any script could be triggered that way following a simple configuration file.

After I left it ran on my home linuxbox and saw it was working fine, I cleaned it up, added some tests, build a python egg on pipy and did some nice integration on github.

How ?

The principle of the script is fairly simple. It’ll run ip neigh show and will analyse its output line by line. If a line has the REACHABLE or PERMANENT mark, it’s considered that we have a neighbor. It’ll then pass through some filters which will exclude it or not.

Filters are defined in a configuration file where all section inherit from the default section. Here is a commented and edited version of my configuration file:

[DEFAULT]
threshold = 4
# by default, only my pc will be considered as a neighbor
filter_on_machines = my_pc
# you can also do some broader filter
# filter_on_regex = .*192\.168\.0\..*  # for example this will allow you to consider as neighbor all the IPv4 address of the class B

# this section allows you to register device by their mac addresses
# if you want to filter them by name in the
# filter_on_machines and filter_out_machines paramters
[known_machines]
my_pc = <mac>
my_tel = <mac>

[transmission]
# activate the "turtle" mode when there is neighbors
command_neighbor = /my/scripts/transmission-turtle true
# desactivate it when there is none
command_no_neighbor = /my/scripts/transmission-turtle false

[bitcoind]
# you can desactivate a section without having to delete it
# from the configuration file
enabled = false
command_neighbor = killall bitcoind
command_no_neighbor = /opt/bitcoind -server -daemon

# for both section above, filters are inherited from the default section

[wake_computer]
# but here, I override that default value to only filter on my_tel
filter_on_machines = my_tel
# again, we override the default value as we don't want to wait 4 cycles
threshold = 2
# we restrict time period during which this section is activated
# with a cron like syntax
cron = * 18-23 * * 1-5
command_neighbor = wake my machine

The package also provides a script that you can run from anywere: myn. This script, run with the --output and --verbose verbose options allows you to easily run through a buggy configuration file and analyse what you would want to match and what doesn’t match.

# myn -o -v
MindYourNeighbors: INFO - MindYourNeighbors initialized
MindYourNeighbors: DEBUG - 'transmission' - processing section
MindYourNeighbors: DEBUG - EXCLUDED - <mac> - MACHINE: a_random_device
MindYourNeighbors: DEBUG - MATCH - <mac> - MACHINE: my_pc
MindYourNeighbors: DEBUG - NO_MATCH - <mac> - MACHINE: my_tel
MindYourNeighbors: DEBUG - cache/transmission/neighbor 2 => 2
MindYourNeighbors: INFO - 'transmission' - cache state: {'results': ['neighbor', 'no_neighbor', 'no_neighbor', 'neighbor'], 'last_command': '/home/jaes/bin/transmission-turtle false'}
MindYourNeighbors: INFO - 'transmission' - cache count hasn't reached threshold yet (2/4)
MindYourNeighbors: DEBUG - section <Section: bitcoind> not enabled
MindYourNeighbors: DEBUG - section <Section: wake_if> disabled for now

SystemD

It’s possible to make SystemD daemonize MindYourNeighbors. For that, you’ll have to put this file in /etc/systemd/system/ and run systemctl daemon-reload and service mind-your-neighbors start.

Sadly, I did not find how to package this in the correct way into the python egg. Indeed, put that file and it’s destination in the setup.py won’t allow a none superuser to install the egg (since they can’t write in /etc/systemd/system). (Yes, it is kind of a cry for help :D)

What’s to come

Some enhancements should be coming soon like the neighbors probing, some dry run options or juste add enough test to reach a descent coverage.