Background
At my work I was recently asked to investigate whether Computrace was available for Linux, specifically Ubuntu, and if so, install it. Having a remote wipe mechanism available is part of our Security Policy.
For those of you reading this that haven’t heard of Computrace, it’s a clever little rootkit for Windows that will allow a (usually corporate) administrator to log into a web page and remote wipe the laptop on which Computrace is installed. It even uses the rootkit part to re-install itself after the wipe. Actually “rootkit” isn’t a perfect description – Absolute Software have actually worked with various motherboard and chip manufacturers to have their agent incorporated quietly into the firmware of supported devices. Therefore, even if you steal one of our company laptops, wipe it, then re-install Windows, the moment you connect that fresh Windows install to the internet, Computrace will immediately wipe it again.
(In case you’re curious, you can still install Linux on the stolen laptop and use it with impunity. The embedded agent will only detect Windows and re-install the Windows version.)
But while Computrace did support Ubuntu 10.04 and have recently updated their support page to reflect 14.04 (the jury is out as to what happened to 12.04 support!) it transpires that this support only extends to the Computrace reporting function. It does not support the remote wipe function.
I briefly investigated Prey, but their goal is to return your laptop to you through uploaded camera grabs and location tracking. While you can lock the device and have it sound an alarm, there’s no wipe function.
So I was scuppered. Without the ability to remote wipe my Ubuntu laptop, I would not be permitted to continue to use it for my daily work.
Necessity is the Mother of Invention
Naturally, I found this situation not to my liking. I didn’t want to use Windows, in any form, to do my day job and only tolerated a Win7 VM for some in-house developed applications that couldn’t run any other way.
And so this leads us to the concept of “Reverse SSH”. Why “Reverse”, you ask? Well, we can’t really use a normal SSH attempt – obviously, a stolen laptop could end up on anyone’s internet connection. The thief could take the laptop home and switch it on there. That home network isn’t going to allow incoming SSH connections for you to conveniently hop into the laptop and perform a wipe, even assuming that you knew the IP address to do so! However, it’s extremely rare for such a home network block outbound connections – so it’s very likely that the stolen laptop could make an SSH attempt back to the company HQ if it were properly configured. And if it does so using the Reverse methodology, that lets you take control of the laptop as if you’d initiated the connection. Perfect!
So how do we do this?
It turns out, that with a bit of groundwork, this is surprisingly straightforward. In fact, only the language used to describe this procedure is complicated. Once you understand the concept, the actual “doing” is very simple. Well, simple to understand, but I admit, there’s a LOT of commands to configure to get the full effect.
Advantages
So, assuming you follow the procedure laid out here, what do you achieve?
First off, you’ll have a laptop that makes persistent connections back to your server, no matter where it is in the world, or what kind of network it connects to, or how often it disconnects/connects to various networks. Assuming that its outbound SSH attempt isn’t blocked by a hardware/gateway firewall, it will succeed and a connection will be established.
Secondly, you’ll be able to trigger a process on your SSH server which will immediately wipe such a laptop, remote locking its drives and reporting on the success of doing so. Once you trigger the process, you can forget about it forever – that means that if the stolen laptop appears online, in Australia, at 4am local time, for a total of 5 minutes, you’ll still have a wiped laptop and an email in your inbox to that effect. No manual intervention is required. You’ll also have a way to cancel the wipe, if you recover the laptop.
Finally, you have a way of troubleshooting and remote controlling the laptop at any time. This makes this procedure ideal for the Mum/Dad or Grandma/Grandpa scenario, where you provide a laptop/PC to them, but you also need a simple way to help out if things go wrong. In fact, while I implemented this about four months ago for my work requirement, it was this post by Stuart Langridge that prompted me to put this on my own website. And if you get stuck with this procedure and I can’t help in the comments, then that post is worth a look too!
One of the nicest things about this procedure is that we’ll set up password-less SSH along the way, so you’ll be able to hop onto the laptop without having to remember passwords AND you’ll have root access to the laptop if you need it. So, by all means, fire up an x11vnc session and watch what the laptop is doing – take control if you like, or perhaps copy a few files, edit a configuration, whatever you need.
So what are we waiting for? Let’s get cracking.
Prerequisites
The main prerequisite for this, of course, is an SSH Server. You need this server to be your own and you’ll need, ideally, root access to it in order to configure everything in this article.
An additional prerequisite, is that your SSH server has either a Dynamic DNS entry, or a static IP address. Without this, your “stolen” laptop won’t know where to connect to and the whole process pretty much falls on its face. You can pay your ISP for a dedicated IP address, but you’re much better off with a ChangeIP.org address or similar. And it should go without saying, but you’ll need to configure your router/firewall to allow inbound SSH connections.
Assumptions
I’m using Ubuntu, so all the commands (particularly apt-get) are Ubuntu specific. I’m also not going to hand-hold you through editing system files – so any time we’re editing something in /etc/, for example, I’m going to assume that you know that you should be root (sudo -s) in order to do so AND that you know your way around your editor of choice, be that vim, nano or gedit. Finally, you should know how to make a file executable (chmod +x filename).
So, we’re not building rockets here, but you need a basic understanding of Linux and how SSH sessions normally work.
For your reference, I’m going to use the following names in this document – change these to whatever you use.
- Server DNS : myserver.mydns.com
- Server Admin account : serveradmin
- Server SSH port for inbound connections : 33322
- Laptop Admin : localadmin
- Laptop SSH port for inbound connections : 22
- Laptop Reverse SSH port : 10100
And here’s a diagram to help visualise what we’re trying to do.
Okay? Okay.
Procedure
Configure the Server
The easy part. Get the SSH daemon running on your server.
sudo apt-get openssh-server
Add the line “ClientAliveInterval 30” to /etc/ssh/sshd_config. That allows the server to detect a dead tunnel if our laptop’s connection is interrupted.
In the same file, change the inbound port to 33322, by editing the “PORT” line. Why? Because it’s less likely to be scanned and brute forced that way. Once you’ve completed this procedure, I suggest that you also edit your /etc/ssh/sshd_config to refuse logins via passwords. I don’t have the reference for that handy, but it’s optional and an easy Google. Obviously, don’t be turning off password-based logins until you’ve configured your SSH keys (which we’ll do below), or you have another method of accessing your server, such as a local KVM (keyboard/video/mouse).
Restart the SSHD daemon with a “killall sshd” (or similar). Or if you’re used to Windows, feel free to reboot. Up to you.
Configure the laptop
<Ensure the laptop has access to the internet when you run this next part>
We’re going to run a set of commands on the laptop to configure it. I usually run these as a script, but to simplify it, I’m assuming that we’ll create a “localadmin” user on the laptop, and that it will use port 10100 as its “reverse port”.
Why are we creating such a user? Well, you don’t have to actually. If you’re only doing this for your one laptop, then feel free just to use the admin-based account already on the laptop. However, if, like me, you have a large number of such devices out and about on the internet, doing this step will SIGNIFICANTLY reduce your pain when it comes time to actually use this functionality.
It gives you confidence that no matter what else has been done to the laptop by whoever is using it, this account should still be there, still have administrator rights and is still configured for key-based login to your server.
Here’s the list of commands.
# Become root sudo -s # Add an admin user for logging into the laptop. Bypass all the various prompts. adduser localadmin --gecos "" # Add the new user to the sudo group so that it can be an admin. adduser localadmin sudo # Install Openssh Server on the laptop apt-get install openssh-server # Configure SSH keys for root. Ubuntu doesn't seem to do this for root, so we have to. # Note the back-ticks after the eval command - these are left of the "1" key on a # UK-based keyboard, just above TAB. eval `ssh-agent -s` ssh-keygen ssh-add # Copy your newly created public key to the server. scp -P 33322 /root/.ssh/id_rsa.pub serveradmin@myserver.mydns.com: # Connect to your server ssh -p 33322 serveradmin@myserver.mydns.com # Place the just-copied public key into the correct place, then delete it. cat id_rsa.pub>>~/.ssh/authorized_keys rm id_rsa.pub # Install autossh which will make the persistent connections. apt-get install autossh # Activate the SSH connection on startup printf "#!/bin/bash -e\nautossh -p 33322 -f -o ServerAliveInterval=30 -o ExitOnForwardFailure=yes -NR 10100:localhost:22 serveradmin@myserver.mydns.com \nexit 0\n" > /etc/rc.local
Either reboot, or just run
sudo /etc/rc.local
We should now have a reverse SSH connection from the laptop to our server and we’ll be testing that shortly. First though, we have one more step to complete on the laptop.
Update the sudoer’s file so that localadmin can do anything without a password prompt :
sudo -s nano /etc/sudoers
Add the line
localadmin ALL=(ALL) NOPASSWD:ALL
to the end of the file. This is necessary for the remote wipe commands to work properly. Technically, we could restrict this line to only the commands that we need to run, but remember, this isn’t as big a security hole as you might think, given that we’ll only be using the localadmin account with password-less login from our own server. Your mileage may vary, however, so if you need to tie this down, go ahead and do that – I won’t cover it here though.
Additional Server Config
Now that we have a reverse SSH connection from our laptop appearing on our server, we’ll use that to finish the config. We have to go back on to our server, grab its public key and add that to our laptop’s authorised user file. And we’re going to do so using the reverse tunnel. Sure, if you’re both on the same network, there are probably easier ways to do this, but we’re actually testing the tunnel for the first time this way, so this is the way I do it.
From the laptop, connect to the server and become root
ssh –p 33322 serveradmin@myserver.mydns.com sudo -s
Now that fun bit. Use the reverse tunnel to connect BACK on to your laptop to copy the server’s public key which will enable password-less login for later connections.
We set our laptop up to connect to the server with a reverse port of 10100 (even though it makes the connection to our server on port 33322 and allows incoming connections to itself on port 22!).
Remember that printf statement above? That’s where we specified the reverse tunnel.
So we connect to that port, but as localadmin, using OURSELVES (the server) as the target machine… which will then zip along the reverse SSH tunnel and we’ll end up on the laptop. This is definitely the hardest and weirdest part to wrap your brain around. Let’s see how it looks.
The SCP command is how we copy files via SSH.
scp -P 10100 /root/.ssh/id_rsa.pub localadmin@localhost:
Minor note – if /root/.ssh/id_rsa.pub doesn’t exist on your server, it’s for the same reason as I outlined in the laptop script. For some reason, Ubuntu doesn’t always create the necessary key associations for the root user. To get around this, just use the same three commands from the laptop script above, namely
eval `ssh-agent -s` ssh-keygen ssh-add
and then re-run the scp command.
Now, back on the laptop, a file has appeared in localadmin’s home folder. We need to place that newly copied id_rsa.pub into the necessary location. In this case, it’s the file “authorized_keys” in the .ssh directory.
Two things – we’ll have to create that directory, because our adduser earlier doesn’t add it automatically. Also, notice the “z” in “authorized”. Ubuntu is pretty well localised, but not to that extent! If you live in the UK, you still need to use the American spelling!
Finally, make sure you are NOT root when you do this. If you are, you’ll lock the file to root and it won’t work.
mkdir /home/localadmin/.ssh cat id_rsa.pub >> /home/localadmin/.ssh/authorized_keys
Testing it all
Assuming we got this far without errors, we at least know that there’s a reverse SSH connection working from our laptop to our server. Well done!
But you can also see these connections “live” by popping into your server (ideally using a different laptop from the one you’ve set up for reverse SSH, since we’re about to disconnect/connect that laptop a few times)
ssh -p 33322 serveradmin@myserver.mydns.com
and running the following command:
netstat -ln | grep 10100
You can also watch the connections happen in real time by doing this:
watch -n 0.5 "netstat -ln | grep 10100"
Run that on your server, then disconnect/connect your laptop a few times over a 10 minute or so period. Remember that the server will only consider a tunnel dead within a 30 second window. I think autossh will only try connections in around the same period, so you’ll only see a connection appearing about a minute or so after an internet connection is established and you’ll only see it disappear about a minute after you disconnect the laptop’s ethernet/wifi connection.
The other big test is password-less login. At this point, we should have done enough that you can make an SSH connection from your server, as localadmin, to your laptop, and you’ll NOT be prompted for a password. Remember that this will ONLY be possible if you are root on your server. That’s because it’s the root users public key that we added to the laptop’s authorized_users file. That’s important, because if we want to automate a laptop wipe later down the line, we’ll need to be root to run the necessary commands. So you need to be root on your server to establish a password-less login on your laptop.
Even better, you’ll be able to become root with “sudo -s” without being prompted for a password.
So let’s give it a try. From your server try
sudo -s ssh -p 10100 localadmin@localhost
You should now be connected to the laptop, regardless of where it’s located in the world, assuming that it has connectivity to the internet and assuming it’s not in some extremely secure environment that is blocking the SSH connection to your server.
You should also be able to do
sudo -s
and become root instantly on your laptop, without a password prompt.
Killing the laptop drive (as a test)
I used this document as a reference for this section. https://ata.wiki.kernel.org/index.php/ATA_Secure_Erase. Basically, you can wipe and lock your SATA drive with these commands.
WARNING! WARNING! These commands do work! They WILL lock your drive and render useless the device on which you run them. Only do this if you have trust issues AND you know how to reverse it AND you have good backups of your data AND you’re happy to rebuild the OS. Really.
You have been warned!
So, assuming we only have one disk in our laptop, it will be /dev/sda.
# THIS WILL ERASE YOUR DATA!!! sudo -s # Set up the drive to be wiped hdparm --user-master u --security-set-pass mypassword /dev/sda # Wipe it, and output how long it took when it's finished. time hdparm --user-master u --security-erase mypassword /dev/sda
Apparently, it should take around 1 minute per 100Gb drive, so 250Gb may take nearly 3 minutes.
And you can unlock the drive again with two commands – one to unlock, the second to permanently disable the lock. The drive will be empty, thanks to that erase command, but at least usable.
hdparm --security-unlock mypassword /dev/sda hdparm --security-disable mypassword /dev/sda
Some BIOS editions support unlocking a security locked drive, but at least on Dell XPS machines, it only unlocks the drive – it doesn’t actually disable the lock. Therefore, you have type the unlock password each time the laptop starts up. Even worse, the BIOS prompt only accepts 8 characters! The first time I tested this, I used a 15 character password and then couldn’t unlock the drive! I had to open the laptop, remove the disk, place it in a USB caddy, unlock the drive with those commands, then replace it in the laptop. Very, very tedious.
Automate the Wipe
The commands above will work if we know the laptop is online, but in the case of a theft, this is unlikely. The server must be set up in a way that it will continually monitor the laptop for connection attempts, and once a connection is detected, the hard disk is wiped.
The commands therefore need to be created in a script which is to be cron’d with a condition that the specified port is available.
So create the following file on your server, call it KillLaptop-10100, then make it executable.
#!/bin/bash # Test if we've already successfully wiped the laptop if [ -f "/home/serveradmin/Success-10100" ] then /bin/echo "`date` Check not required">>/home/serveradmin/ConnectLog-10100 else # Test if the laptop is connected right now /bin/netstat -ln | /bin/grep 10100 if [ "$?" -eq 0 ] then /usr/bin/script -a /home/serveradmin/RunLog-10100.txt -c /home/serveradmin/Commands-10100 /bin/echo "`date` Laptop Wiped, see RunLog-10100 for details">>/home/serveradmin/Connectlog-10100 /bin/touch /home/serveradmin/Success-10100 exit else /bin/echo "`date` Dude hasn't connected yet">>/home/serveradmin/ConnectLog-10100 fi fi
Then, create the command script which that one calls. Call it Commands-10100 and make it executable.
/usr/bin/ssh -p 10100 localadmin@localhost\ '/usr/bin/sudo /sbin/shutdown -r +30 &;\ /bin/echo "Getting stats";\ /usr/bin/sudo /sbin/hdparm -I /dev/sda;\ /bin/echo "Enabling Security";\ /usr/bin/sudo /sbin/hdparm --user-master u --security-set-pass mypassword /dev/sda;\ /bin/echo "Issuing security delete and lock command";\ /usr/bin/sudo /sbin/hdparm --user-master u --security-erase mypassword /dev/sda &;\ /bin/echo "All Drives Complete";\'
Finally, as root, cron the script to run every minute
sudo crontab -e * * * * * /home/serveradmin/killLaptop-10100
And that’s it!
The first script will check for connection attempts, logging each attempt as it does so. Eventually, when it sees the connection it calls the second script via the “script” command, which ensures that it’s run on the laptop. The commands inside that second script are the ones that will kill the laptop.
You’ll notice that those commands start by scheduling a reboot in 30 minutes time. This is because a guest session in Ubuntu runs in memory, so even after you’ve wiped the hard disk with this method, nothing appears to have happened and you’ll only see the effects of the wipe after a reboot. So we force one there and then.
Summary
So it’s all a bit wordy, I admit. But then I’m trying to explain everything step by step, so there’s more reading than doing in this piece.
And if you have full disk encryption on your laptop, you really have to wonder why you’d go to such extents to ensure that the data is wiped. But while that argument is worth having, you also have to admit that there are benefits to running this set up, even if you go down the full-disk encryption route.
You get to see laptop usage for example. It’s a simple task to log the results of each connect attempt to your server – and if you have multiple laptops connecting on different reverse ports, you’ve just established how often each laptop is being used and more importantly if certain devices are sitting idle.
You could go further too. You could probably run Puppet or Chef scripts across these tunnels. Remember that your server has full password-less sudo access to the laptops in question.
And as I mentioned, this is a great support tool. Fire up an x11vnc session to see the laptop’s desktop. Oh, it isn’t installed? Then sudo apt-get install x11vnc, then fire up an x11vnc session to see the laptop’s desktop. Support just became… well, it’s never trivial, but this opens the door to a world of possibility. Commands like netstat, ps, htop and iotop become allies in the fight against the computer illiterate and hand holding doesn’t need an hour’s drive in the evening to visit a confused friend or relative who just needs a nudge in the right direction.
If you think up any other clever uses, let me know in the comments!