1

I have a growing number of remote machines that ssh home and setup a connection to allow subsequent access via tunnel so I can get into them for maintenance.

Currently, I must manually configure these machines with a unique forward ssh port prior to install at the remote location by editing a script. The rest of the install is automated (PXE). It becomes tiresome (and risks error) setting this port manually, and prevents me confidently handing the full process off to a tech.

Question> Given a clean, debian install is it feasible to write a numeric hash function of (say) the mac address on eth0 that would be deterministic and fall in some range (say 30000-60000) and you could reasonably expect to be unique(++). I guess I've got bash, awk etc to play with. I would prefer to stick to shell related tools if possible but could use python if pushed.

(++) I would amend the tunnelling script to increment the port if it had problems on the first port tried.

Example Suggested Input: ifconfig eth0 | grep HWaddr | awk '{ print $5 }' == 08:00:27:aa:bb:cc

Example Required Output: 34567

Aitch
  • 1,179
  • 8
  • 14

3 Answers3

2

This should also do what is required.

port=$(/sbin/ifconfig eth0 | grep HWaddr | awk '{ print $5 }' | md5sum | cut -d ' ' -f1)
port=${port:25}
let "port = 0x$port"
let "port %= 30000"
let port="$port + 30000"
echo $port
user9517
  • 115,471
  • 20
  • 215
  • 297
  • You live and learn. I'd never really come across RANDOM in bash, nor the pre-seeding – Aitch Mar 28 '11 at 10:26
  • @Aitch: A day without learning is wasted. – user9517 Mar 28 '11 at 10:27
  • I'm marking this one as answered, this is exactly what I was after and elegantly simple using shell. I appreciate you taking the time to post. – Aitch Mar 28 '11 at 10:33
  • On further investigation this method is not deterministic (same result each time) - Debian Squeeze 6.0 root@myserver:/my/bin# ./portgen.sh 31101 root@myserver:/my/bin# ./portgen.sh 43840 root@myserver:/my/bin# ./portgen.sh 32097 – Aitch Mar 30 '11 at 10:54
  • @Aitch: On the 3 systems I tested it on (Ubuntu 9.04, Ubuntu 10.10 and CentOS 5.5) I get consistent results each of which is correctly different to the other 2. – user9517 Mar 30 '11 at 11:09
  • I don't understand it either. I just pasted the exact script above into my Ubuntu 10.10 box and ran multiple times with different results each time. The result from md5sum is always consistent (I checked) which implies the problem is with the RANDOM pre-seed behaviour – Aitch Mar 30 '11 at 11:29
  • This is bugging me as I don't doubt your results. I just reran original script (straight cut'n'paste) on Debian 5.0 (bash 3.2.39/i486) and it works perfectly, repeatedly. Then the identical script on an Ubuntu 10.10 (bash 4.1.5/i686) and it generates multiple different results on each rerun. I can only assume there is some sort of difference present in the arch or bash version but i couldn't find anything relevant. – Aitch Mar 30 '11 at 20:51
  • 1
    @Aitch: I've figured out what's going on. I built a debian 6 system to test it and this system gave changeable results. The problem is a difference in the way that bash v3 and v4 deal with assigning hex values to RANDOM. if it begins with a-f then v4 acts like it was never assigned and prints a random number. – user9517 Mar 30 '11 at 21:52
  • Very nice to get to the bottom of it. Hopefully future google-ers will find it useful – Aitch Mar 31 '11 at 09:24
1

I really like your thinking and I'm curious to see your tunneling script but the cynic in me says someone will mention SSH keys :-)

We just use cssh for lots of small shell windows.

jscott
  • 24,484
  • 8
  • 79
  • 100
Jonathan Ross
  • 2,183
  • 11
  • 14
  • We use ssh keys on each machine as well but they are equally a pain to manage and add to the authorized keys! I may have a look at using a generic key. I had a look at cssh as suggested and it appears to me to be used for concurrent execution on multiple machines; although i wouldn't rule it out, that isn't what we need this for. The port problem is just to make the remote machines more and more commodity like (eg for swap out in the event of problems) – Aitch Mar 28 '11 at 09:10
  • I'm with you. We keep things really simple and have a stock build with about 20 mins worth of tarball-and-drop configs to keep our boxes almost the same for failover. Tempting as it is I wouldn't go for the same key approach even with TCP wrappers. There's always port-knocking ! HTH, JR – Jonathan Ross Mar 28 '11 at 09:14
  • One trick I had in mind (this is slightly OT) is to have the machines email home (or use cfengine or a web API or something like that) their config/public keys when they boot. That way I'd have a copy of the keys. So when they were switched on remotely, they would be knocking on the door, so as to speak, but not allowed in. I could take the config they had sent home, add it to the landing pad machine and then they would be allowed in. Yes I know there are some obvious flaws in this approach! – Aitch Mar 28 '11 at 09:19
  • 1
    Hehe. There's some merit in that approach. If there's web services on the machines then you could have a SSL login on a hidden URL (Or at least a similar login option which (from a service perspective) is easily accessible but secure. Have you seen Google's 2-step auth for example ?) which would effectively open up access to the tunnel/SSH for a specified period. Along the lines of port-knocking. I've heard of a Web-based SSL login adding the user's source IP to hosts.allow for an hour for example. HTH, JR – Jonathan Ross Mar 28 '11 at 09:30
1

Your hwaddr is just a big number, so you could always just take that mod whatever your range is and add the offset.

#!/usr/bin/perl

$iface = $ARGV[0] || "eth0";
open(IFCONFIG, "-|") || exec "/sbin/ifconfig", $iface;
while (<IFCONFIG>) {
    if (/HWaddr ([0-9a-f:]{17})/i) {
        ($hwaddr = $1) =~ s/://g;
        $hwint = hex($hwaddr);
        print $hwint % 30000 + 30000, "\n";
    }
}
close(IFCONFIG);

Here's the Math::BigInt version:

#!/usr/bin/perl -w

use Math::BigInt;

$iface = $ARGV[0] || "eth0";
open(IFCONFIG, "-|") || exec "/sbin/ifconfig", $iface;
while (<IFCONFIG>) {
    if (/HWaddr ([0-9a-f:]{17})/i) {
        ($hwaddr = $1) =~ s/://g;
        $hwint = Math::BigInt->new("0x" . $hwaddr);
        print $hwint % 30000 + 30000, "\n";
    }
}
close(IFCONFIG);
Cakemox
  • 25,209
  • 6
  • 44
  • 67
  • This is pretty much what I imagined, but my perl is appaling :) It works great, I get the number, but I also get a warning message "Integer overflow in hexadecimal number at /tmp/hash.pl line 8, line 1." Can this be eliminated? – Aitch Mar 28 '11 at 09:22
  • You can use Math::BigInt to avoid that. I'll add it! – Cakemox Mar 28 '11 at 09:33
  • This is equally a great answer and works very well, albeit slightly more complicated, but would be ideal if my tunnel script was in perl. Sadly I can only mark one as answered. – Aitch Mar 28 '11 at 10:35
  • With the benefit of hindsight, and further investigation, on the face of it, this is actually the better answer. The answer is deterministic (same each time) and therefore meets what I need. Having this as a separate little script is not that big a deal as I need to generate this number in more than one place, and my "out of the box" minimal Debian 6.0 runs it with no additional software – Aitch Mar 30 '11 at 10:56