My dad’s got a computer. Infrequently, it goes wrong and I need to fix it. Slightly more frequently, it doesn’t go wrong but it does something which is confusing, and I need to try to fix it until I realise what the confusing thing was and then either fix that or explain it. So, being able to connect to his machine is useful.
His ADSL router, from TalkTalk1, allows one to set up a port forward2 so that I can connect to his external IP and have that routed to port 22 on his machine, thus allowing me SSH access, and with SSH I can do everything else3. However, that router also controls the DHCP addresses for things on the network, and it does not always give the same address out to the same machine. So, every now and again, it’ll give his machine a different IP, and then the port forward stops working.4
So, after mithering about this a bit, Daviey Walker suggested5 that I use a reverse SSH tunnel. That is to say: I have his machine ssh into one of mine, and then port forward a port on my machine back along the SSH tunnel to port 22 on his machine, meaning that I can ssh into it and don’t have to care about IPs or anything.
This was a dead clever idea. It relies on me having a machine which is sshable from the outside world, but I do, so that’s OK.
Obviously, something needs to set the tunnel up. So, first I set things up so that his machine could ssh into mine with key authentication and without a password needed (see ssh-copy-id or a guide for that), and then I wrote this little script:
ssh -N -o BatchMode=yes -R 9102:localhost:22 mylogin@mysshablemachine
if[[$? -eq 0 ]]; thenecho Tunnel created successfully
elseecho An error occurred creating a tunnel. RC was $?fi}
/bin/pidof ssh > /dev/null
if[[$? -ne 0 ]]; thenecho Creating new tunnel connection
which creates this ssh tunnel connection. There’s a hack there: it assumes that if there’s an ssh process, it’s our ssh process. If you regularly ssh from the box you’re doing this on, you’ll want to do something cleverer. In this case I don’t, so I keep it easy. Couple of little tricks in the script: there’s a date command, so the output mentions when this happened, which is useful for the log file in the next bit (and this is also why the script generates no output if the tunnel is already up). Secondly, -o BatchMode=yes in the ssh options means that it’ll instantly fail if you haven’t got key auth set up right, rather than hanging forever waiting for a password, and it’ll send server keepalives every 300 seconds and kill the connection if they break, which means that if the connection hangs but doesn’t terminate, it’ll get terminated. This is what we want, because we want some monitoring process to restart the tunnel if it dies. There are all sorts of clever ways to do this: upstart, systemd, whatever6, but I just put this line in the crontab7:
which just reruns the above script every minute and sticks any output into a logfile so if it’s not working I can, at a push, ask dad to read the logfile. Inefficient and low-budget, but it works. So once all this is set up, I can, from my sshable machine, do ssh -p 9012 dadlogin@localhost and I then get to log in to his machine. Then I can fix it. And never deal with his horrid router’s horrid web UI ever again.
not /etc/init.d though. This is a user-level process. It should not be being run by system-level stuff. System level belongs to apt. ↩
a file which defines jobs to be run at specific times; it’s like a super-techie Scheduled Tasks wizard, and it usefully will run things even when you’re not logged in. You can edit yours from the command line with crontab -e. ↩