Posts Tagged ‘NetworkManager’

Scripting NetworkManager

Sunday, May 2nd, 2010

At home I have a laptop acting as a central mercurial server (from here on referenced as myserver). This is great, being able to synchronize my desktop and netbook through an intermediary gives me three hard drives on which my data is stored. The setup was, however, not especially useful since my netbook goes with me almost everywhere (read: outside the home network).

This presents a problem as when I clone a repository and my .hg/hgrc file now contain a link to the server using at best a name defined in my /etc/hosts file, and at worst a local IP address (192.168.0.xyz).

I had long since done away with the IP address links, replacing them with hostname links (i.e. ssh://hg@myserver/repo instead of ssh://hg@192.168.0.xyz/repo) which was the first step. Now all I needed to do was make myserver accessible through the firewall (forwarding the appropriate port (since we are talking ssh here that would be 22, unless you are paranoid and have switched the port which sshd listen on) in the router, make the server listen on that port, and finally come up with a way to dynamically switch what IP address myserver should point to.

There probably is a better solution for this, configuring the router to make all this would be one way, but I’m not sure that my router has that capability, and even if it did, I’m not sure I would have the skills to configure it. Software and shell scripting on the other hand, those are things I know how to work.

My solution, was simply to create two new hosts-files in /etc :

# touch /etc/hosts-{home,not-home}

and then insert appropriate information into them such as

# echo "myserver    192.168.0.xyz" > hosts-home
# echo "myserver    aaa.bbb.ccc.ddd" > hosts-not-home

(where aaa.bbb.ccc.ddd is my external IP as seen on http://whatismyip.org/).

I also made a backup of my current hosts file just to be on the safe side

# cp /etc/hosts /etc/hosts.bak

So, the overall plan is that once I’ve identified if I am at home, or somewhere else (i.e. not home) I will overwrite (copy) /etc/hosts with the “correct” hosts-file (-home or -not-home).

And this is where NetworkManager comes into play. Every time there is a change in the connection status of any identified network interface, NetworkManager reacts by executing every script found in /etc/NetworkManager/dispatcher.d/.

Every script is called with two parameters, the first being which interface changed (e.g. “eth0″, “wlan0″, etc.) and the second being how it changed (e.g. “up”, “down”). What I wanted to do was, every time a new interface went up, check if it had connected to a device in my home network (wlan or ethernet).

So, how do you distinguish different devices in a simple manner? For me, distinguishing different MAC addresses (two known addresses at home (wlan and ethernet), and every other address was essentially not home) would do nicely.

Enter the “arp” command. From it, using flag “-i” (for interface) I can discover the IP and MAC address  of the device I’m connected to. When I first discovered the example usage used flag “-a” as well which, according to the man-page, outputs results in an alternate BSD style format, using no fixed columns. This had some benefits, but as I read it again now, the “no fixed columns” remark begin to worry me. The fact that it has worked so far isn’t good enough proof that it will always work. Needless to say, ymmv.

Putting it all together:

#!/bin/sh
# filename: /etc/NetworkManager/dispatcher.d/99switchHosts.sh

# Unless the status is "up" I'm not interested
if [ "$2" != "up" ];
then
    exit 0;
fi

# I am interested in two interfaces, eth0 and wlan0
# each connect through different IP addresses and
# these devices have separate MAC addresses
if [ "$1" == "eth0" ];
then
    TARGETIP="192.168.0.1"
    TARGETMAC="aa:bb:cc:dd:ee:ff"
else
    TARGETIP="192.168.1.1"
    TARGETMAC="12:34:56:78:90:ab"
fi

# Sometimes arp hasn't gotten hold of any IP/MAC addresses
# pinging and waiting does wonders for this
ping -c 1 "$TARGETIP" 1>/dev/null 2>&1
sleep 5
CURMAC=$(arp -ai "$1" | grep "$TARGETIP" | awk '{ print $4 }')

while [ -z "$CURMAC" ];
do
    # Again, arp might not have gotten hold of IP/MAC
    sleep 3
    CURMAC=$(arp -ai "$1" | grep "$TARGETIP" | awk '{ print $4 }')
done

# If MACs match, it is a known address, i.e. home
if [ "$TARGETMAC" == "$CURMAC" ];
then
    cp /etc/hosts-home /etc/hosts
else
    cp /etc/hosts-not-home /etc/hosts
fi

exit 0

This should be put in /etc/NetworkManager/dispatcher.d/99switchHosts.sh (and the script should be made execute:able)

# chmod +x /etc/NetworkManager/dispatcher.d/99switchHosts.sh

All done, not too shabby eh?

NetworkManager and password changes

Saturday, March 20th, 2010

Last week I changed passphrases (long overdue, I should really know better) which included the user passphrase on my netbook.

Today I attempted to connect to my encrypted WLAN at home, which prompted me with a cryptic password prompt telling me that “Network Manager Applet (nm-applet) wants access to the default keyring but it is locked”.

To my knowledge, the only two keyrings I’ve ever set any passphrase to is to GPG and SSH, and none of those to passphrases (old or new) worked. I was stumped. What other password/passphrase could they mean? What “default keyring”?

I was fairly certain that this was not a case of me setting a passphrase only to never use it and thus forget it, so I started getting a chilling feeling that I might have corrupted files on the disk.

Luckily my google-fu was with me and I found this post, which made everything clear.

What happened was simply that when I changed the passphrase for my user, this change didn’t propagate to the “default keyring” storing network passphrases, so the password for the default keyring was still set to the old user passphrase (which I didn’t try, since I didn’t even consider them being the same)

Honestly, although it is of course a VERY GOOD idea to encrypt such data, I can’t say that it was smart of the developers to “magically” set the default keyring password to the same as the system users (at least without notifying the user about this), or alternatively, to not have it updated along with the system user password…

If you have magic in one place you need to make sure the magic persists all the way, otherwise you just end up with a confused user.

The reason I did not immediately connect the dots between user passphrase change and default keyring password prompt was simply that almost an entire week had passed before I ran into problems (I guess the only secured network I ever connect to is my own, and I obviously haven’t used it in that time…)

Anyway, what finally worked for me (as outlined in the link above) was:

  1. Start “seahorse”
  2. Goto “Passwords” tab
  3. Right-click on “Passwords: login”, chose “Change password”
  4. Enter old system user password, and (preferably) the new system user password (unless you want to be pestered with the default keyring locked password prompt every time you connect to a secured network)

User-friendly magic is cool, undocumented magic… not so much :(