As discussed in Part 1, I am setting up a Raspberry Pi with a USB thumb drive to be my “cloud storage” provider. I got the proof-of-concept going, so the next step was to implement it for real, and create a proper installation. Below are the some of the major things I did to lock down the Pi and make it production ready:
When you first booted your Pi, you ran this little graphical app, well go launch that again:
In there, there are a few things we should set:
- 1) Expand file system – by default, you will have a bunch of extra space on your SD card that isn’t used. So, unless you plan on partitioning it special, just choose this option to give the root mount point more space
- 3) Enable boot to desktop – in a “server” type setup, there is no need for XWindows. So, boot to the command-line instead (run-level 2) and later, we’ll even remove XWindows from this system.
- 7) Overclock – I overclocked to “Medium”, 900MHz, because that seems a little better than default, and it’s not as dangerous as High or Turbo (“dangerous” meaning overheating or melting your PI)
- 8) Advanced Options –> A3) Memory Split – since you aren’t running XWindows, you want to give as much RAM as you can to the operating system (as opposed to video processing). So, set this to 16.
After you are done, reboot:
Create a new user account for remote administration
To create a new, non-privileged account, I just did:
sudo adduser johndoe
You can call the account whatever you’d like, I’m just using johndoe as an example. You will be prompted for a name, password, etc. Use a VERY strong password for this account. Presumably, this would be the account that I connect with via SSH to do remote administration. I don’t want to expose the root account over SSH because it would be too much of a target.
“johndoe”, or whatever you name this account is though, just an unprivileged user. He/she can do “su” to login as root, but I also want to be able to sudo commands. So, if you edit the sudoers file:
sudo nano /etc/sudoers
and then add a line after the “root” line, like this:
root ALL=(ALL:ALL) ALL
except make it for your new account, so it might look like this afterwards:
root ALL=(ALL:ALL) ALL
johndoe ALL=(ALL:ALL) ALL
Also comment out or delete the “pi” reference later in the file, we’re going to delete that account anyhow.
Set the root password
Before we do anything else, make sure to set or reset the root password. If you don’t know it, from the pi account you should be able to do:
sudo passwd root
and you can just set it that way. If you already know it, you can log in as root and just type “passwd” to change your password. You should DEFINITELY create very strong passwords (see this blog post on how to do this, effectively!)
Delete the default “pi” account
At this point, you should have a root account with a very good password, and a non-privileged account with a good password – from which you can “sudo” and “su”. At this point, we can safely remove the default “pi” account. To do that, log in as your new maintenance account and run:
sudo deluser pi
And that’s about it!
Clear the screen on boot-up
This is a small thing, but worth doing. When the Pi boots, if you have it hooked to a monitor, you’ll notice that the boot screen stays up, and the prompt to log in is at the bottom of the screen. A malicious user might be able to glean some details from that, so it’s best to clear the screen after boot. The simplest way to do that is to modify the /etc/inittab file
sudo nano /etc/inittab
and replace this line
1:2345:respawn:/sbin/getty –noclear 38400 tty1
with this line
1:2345:respawn:/sbin/getty 38400 tty1
Save changes and exit. Upon next boot, the screen will clear (on the console) and you’ll be left with just a prompt at the top of the screen. Similarly though, the default prompt also gives a lot of information about the current system: the operating system, version, platform, and server name. Again, to the malicious user, this gives them unnecessary information. So, you may wish to edit the /etc/issue file
sudo nano /etc/issue
and just put the machine name in for example. Don’t hard-code it. Instead, there are codes you can use – see this page for all of the replaceable tokens you can use. More on this in a minute…
Add a banner, configure SSH
Another relatively small thing is you might want to add a warning banner to the login prompt – this might at least scare off a non-professional hacker. To do that, we can add that banner to the /etc/issue file. However, we also need to tell the SSH daemon to show it. To do that, we need to edit
sudo nano /etc/ssh/sshd_config
and you want to uncomment:
Note that /etc/issue is what is shown at a local prompt, and /etc/issue.net is what would be shown for remote users (like via telnet, if it were installed). So, I made a backup copy, and then made /etc/issue.net the same as /etc/issue. The /etc/issue.net file doesn’t respect those escape sequences that issue does, so I hard-coded the machine name in there.
Meanwhile, I found this pretty good whitepaper on login banners. The thinking is that you give yourself a tiny bit of legal advantage in case you ever end up in court. If you have this banner, then the other person can’t claim “I didn’t know I couldn’t log in there!”. Anyhow, this is what my /etc/issue and /etc/issue.net look like now:
WARNING: Unauthorized access to this system is forbidden and will be
prosecuted by law. By accessing this system, you agree that your
actions may be monitored if unauthorized usage is suspected.
That gives me something like this on the console:
and this when SSH-ing in:
Anyhow – back to the sshd_config – while we are in this file, further up, also you may want to disallow root from logging in via SSH. That way, a malicious user must break into your maintenance account to get to the root account. It’s one more small obstacle. So, I set this from yes to no:
# PermitRootLogin yes
Save the file and reboot. By the way, how do you see failed login attempts? This seems to work:
sudo grep “Failed” /var/log/auth.log
Update to the latest firmware/kernel
I just followed the instructions from here: http://simonthepiman.com/how_to_setup_your_pi_for_the_internet.php and then worked without issue. Basically, these commands:
sudo apt-get install ca-certificates
sudo wget http://goo.gl/1BOfJ -O /usr/bin/rpi-update && sudo chmod +x /usr/bin/rpi-update
sudo apt-get install git-core
and you can repeatedly run “sudo rpi-update” in the future to just update to the latest firmware.
Setup a firewall (iptables)
I basically just followed the directions from here. In short, I did this:
sudo bash -c ‘iptables-save > /etc/network/iptables’
sudo nano /etc/network/interfaces
add the following:
pre-up iptables-restore < /etc/network/iptables
modify the iptables (see below), then run
sudo iptables-restore /etc/network/iptables
If you locked yourself out, you did something wrong! Go hook the Pi up to a TV and manually log back in to see what is amiss. Otherwise, you should be good. For me, I want to allow SSL and SSH. I don’t care about the port number because the access will be made via port forwarding. So, I am allowing SSH (port 443) and SSH (port 22). My /etc/network/iptables looks something like this:
# Dont accept any incoming network traffic unless a following rule overrides.
:INPUT DROP [23:2584]
# Accept any forwarding requests
:FORWARD ACCEPT [0:0]
# Allow any outbound network traffic
:OUTPUT ACCEPT [1161:105847]
# Allow any connections from the local host
-A INPUT -i lo -j ACCEPT
# Allow all SSH traffic
-A INPUT -i eth0 -p tcp -m tcp –dport 22 -j ACCEPT
# Allow all SSL traffic
-A INPUT -i eth0 -p tcp -m tcp –dport 443 -j ACCEPT
# Allow all traffic from the internal LAN
-A INPUT -s 192.168.1.0/24 -j ACCEPT
# Allow ping traffic so you can test from outside, delete this line
# once you have finished testing.
-A INPUT -p icmp -m icmp –icmp-type 8 -j ACCEPT
# Allow inbound access to any internally generated requests
-A INPUT -i eth0 -m state –state RELATED,ESTABLISHED -j ACCEPT
# Finally commit the entries to the firewall
Uninstall unnecessary software
This will likely be the most daunting task. To get a list of all installed software, run:
sudo dpkg –get-selections
You will likely see an ENORMOUS list of software. To uninstall a package, do:
sudo apt-get remove packagenamehere
So, just go through the list and de-install anything that isn’t related to this server installation. That means anything x11, xserver or anything x related can go, python can go, “cups” (printing from this linux machine) can go. Just work your way through the list. What did I delete? Here’s everything I started with:
This basically got rid of XWindows and any X-apps, and some other obvious things, like listed above. I’ll see over time if there are other packages I could safely remove.
Delete any unused or unnecessary accounts
At this point, you should have a pretty good handle on what you need and don’t need on this system. So, take a look at the user accounts:
sudo cat /etc/passwd
if you have any leftover accounts from software you installed before, but have now removed – delete those accounts with:
sudo deluser theusernamehere
Actually setting up OwnCloud:
Just a couple of things to note, here. For now, I’m just using the self-signed SSL certificate that Apache provides. See this page for how to enable SSL both for Apache and in the OwnCloud settings page. Aside from that, just follow the wizard on the first-run and it should be pretty intuitive.
One of the key features of OwnCloud is user-specific encryption. To turn this on, while logged in as administrator, click the Files dropdown and choose “Apps”.
From the next screen, choose Encryption and then “Enable”. Afterwards it will look like this:
and now – you must log out and log back in for the encryption process to start. All your existing files and future files will now be encrypted, based off your password (you DID make a very strong password, right?!)
Turn off HTTP port 80:
I don’t want to accidentally be able to connect to this server over unsecured HTTP, so I want to disable port 80. To do that, edit the config:
sudo nano /etc/apache2/ports.conf
and comment out these two lines:
# NameVirtualHost *:80
# Listen 80
Restart the web server and make sure you can only connect via https:
sudo service apache2 restart
Setting out outbound e-mail:
I would like to be able to e-mail myself interesting things. For example, maybe I set up a cron job which looks for unauthorized access, and reports disk space – and e-mails me that daily. Well, I just installed ssmtp and used a dummy/throwaway SMTP gmail account for sending e-mail – see this page: http://iqjar.com/jar/sending-emails-from-the-raspberry-pi/
I was initially annoyed at having to use gmail. I AM an SMTP server, why can’t I just send e-mails myself? Well, because the e-mails bounce because all of the major ISP’s (Comcast, TWC, Cox, etc) are all blacklisted by Hotmail, GMail, etc and they won’t accept incoming messages. So, you MUST use a “smart host” to be able to send e-mail.
By the way, receiving e-mail isn’t necessary and would be exponentially more difficult – so I will not be doing that, with this installation.
First, let me say one thing. In putting together this blog post, I realize that this is NOT a simple project (if you want it to be secure). However, one thing to note is this:
For every obstacle, problem, or unknown I ran up against, the answer was almost always one google search away, and the answer was always in one of the first couple of links.
There is a tremendous community around the Raspberry Pi’s (and Debian linux) – so I was never bogged down for more than a few minutes on any one issue. So, although there are a lot of steps involved – it wasn’t that bad because there were no major problems.
Well, that’s it for now. I believe this should get this system into pretty good shape and fairly secure in preparation to be exposed to the internet. Only two ports will be exposed (via port forwarding), a non-standard SSL port for the application and a non-standard port for SSH. I am going to run this exposed for a bit and keep a regular eye on the log files. I’d really like to get some input from my Linux colleagues to get a professional opinion on it too.
If everything seems solid, then I’ll start using this as my production setup in a few weeks once I feel comfortable with the security.
Lastly, one of the other things I was thinking of doing is doing this whole thing again on a fresh SD card, and then make a copy of it. The SD card of a Pi is kind of like the C: drive of your Windows machine – that’s where the OS lives. The Win32 Disk Imager that you use to burn an OS onto an SD card can be used to make an image too. So, I could use this setup as my default OS setup for future Pi projects. If you are interested in that let me know. The image files are like 3GB, so too big to post online – but I could probably burn you an SD card and send it off, if interested.
If you have any ideas, questions, or comments on this – I’d love to hear from you, please let me know!