Table of Contents
- Intro
- Operating System Selection
- Installing MinibianPi
- Creating New User With Administrative Privileges
- Securing The Operating System
- Getting The System Up-to-Date
Intro
A RaspberryPi isn’t the most powerful computer around, nor is it equipped to perform server-grade mission-critical tasks. But a lot of people use it as their home-grown server, some have multiple units or clusters of them, and some companies even offer RaspberryPi data centers.
I’m a tinkerer. This means I make mistakes, I ruin one of my servers, and — more often than not — I re-install it from scratch because I don’t know how to fix it. Then I do it all over again. Setting up a base system that I can build on has become a somewhat mundane task. This post documents just that: my endeavor to create a secured minimum system from which I can build a RaspberryPi server.
Disclaimer
I am by no means an expert in server installation or maintenance. I do this for fun, and sometimes I get lazy and cut corners. Please don’t treat this as a you-must-do-this guide, but more of a this-is-what-I-did and I’d like to share it with you. If you spot any mistakes, please let me know and I’ll do my best to address it immediately.
Operating System Selection
The objective of this build is to prepare a minimum system that is reasonably secured and can be used as a base system from which we can build a RaspberryPi-based server. Note the keywords: minimum and server. We won’t need to have a desktop environment, let alone Minecraft. Let’s leave all unnecessary things out of the build.
To achieve the objective, I chose MinibianPi. It’s a stripped-down version of Raspbian which is quite up-to-date, and even supports Pi 2. I think it’s a great place to start.
Installing MinibianPi
- Download MinibianPi image.
- Write the image to an SD card (there are instructions for Windows users, Mac users, and Linux users).
- Login as root (password is raspberry), either directly or via SSH using Terminal if you’re on a Mac or PuTTY if you’re a Windows user. The image has SSH enabled by default.
-
Install
raspi-config.
We
could
just
re-partition
the
SD
card
ourselves,
but
I
would
personally
try
to
not
mess
with
partitions.
apt-get install raspi-config -y
- Run raspi-config, and then expand filesystem. We have to do this now to avoid running out of disk space when we start installing other stuff.
- Reboot
Creating New User With Administrative Privileges
I believe this is one of the most important things to do, because the default ‘pi’ user on the Raspbian image is vulnerable enough if exposed to the internet, let alone having a system with a known root password.
-
First
we
need
to
update
our
repositories.
I
found
out
the
hard
way
that
if
we
do
this
any
later,
some
installations
just
won’t
work.
apt-get update
-
Next,
we
need
to
install
sudo
so
that
we
can
grant
administrative
privileges
to
non-root
users.
apt-get install sudo
-
Alright,
with
that
done,
let’s
add
the
new
user.
adduser USERNAME
We have to set a password for this new user, but all other fields can be left blank.
-
To
grant
administrative
privileges,
we
can
add
USERNAME
to
the
sudo
group.
adduser USERNAME sudo
- With that done, we can reboot and login as USERNAME.
Securing The Operating System
Regenerating Unique Host Keys
-
The
very
first
thing
we
need
to
do
is
regenerate
the
unique
host
keys.
sudo rm /etc/ssh/ssh_host_* && sudo dpkg-reconfigure openssh-server
-
Next
we
need
to
verify
that
the
keys
have
indeed
changed
and
make
sure
we’re
still
able
to
login.
If
you’ve
been
doing
all
this
via
SSH,
try
to
login
using
another
Terminal
or
PuTTY
session.
If
you’re
using
PuTTY,
you
should
see
a
warning
and
getting
past
it
is
simple. If
you’re
using
Terminal
or
a
Linux
machine,
you
need
to
remove
the
host
key
from
your
known
hosts
file.
Here’s
how
you
do
it
if
you
previously
logged
in
using
the
Pi’s
IP
address:
ssh-keygen -R 192.168.1.111
If that doesn’t work, and you’re okay with resetting your entire known hosts file, just delete it:
cd rm .ssh/known_hosts ssh ras.mydomain.com
Setting Up Key Pair Authentication for SSH
Next, we should prefer key pair authentication for SSH than the default password authentication. As long as we don’t lose our private key, that is. If you’re a Mac or Linux user, follow along. If you’re stuck with Windows, like I am, here‘s a good article about setting up key pair authentication using PuTTY.
-
On
your own
terminal
(not
on
the
Pi),
do
this
to
create
your
private
and
public
key
pair:
ssh-keygen
-
Follow
the
on-screen
instructions
to
create
the
SSH
keys
on
your
computer.
To
use
key
pair
authentication
without
a
passphrase,
press
Enter
when
prompted
for
a
passphrase.
After
completing
this,
2
files
will
be
created
in
the
directory
~/.ssh
(or
/home/USERNAME/.ssh).
The
file
id_rsa
is
your
private
key,
and
id_rsa.pub
is
your
public
key.
Now,
we
need
to
upload
the
public
key
to
the
Pi.
Let’s
use
SCP
for
this:
scp ~/.ssh/id_rsa.pub USERNAME@192.168.1.2:
Change 192.168.1.2 to your Pi’s reserved IP address.
-
Then,
using
the
Pi’s
console,
on
the
Pi’s
home
directory,
let’s
create
the
.ssh
directory:
mkdir .ssh
-
Next,
move
and
rename
the
id_rsa.pub
file
to
the
.ssh
directory
and
change
permissions
to
secure
it:
mv id_rsa.pub ~/.ssh/authorized_keys chown -R USERNAME:USERNAME .ssh chmod 700 .ssh chmod 600 .ssh/authorized_keys
After that’s done, our Pi will be able to authenticate us using our public key. To try this out, logout from your Pi and try to login again. Instead of the usual SSH login prompt, you will be prompted to enter your passphrase if you have one. If you didn’t set a passphrase, you’ll be logged in immediately.
Disabling Password Authentication and Root Login
When we’re able to log in using key pair authentication, we should disable password authentication. While we’re at it, let’s disable root login as well:
-
Edit
the
file
/etc/ssh/sshd_config
sudo nano /etc/ssh/sshd_config
- Set ‘PasswordAuthentication’ value to ‘no’.
- Set ‘PermitRootLogin’ value to ‘no’.
-
Restart
SSH
service.
sudo service ssh restart
- Test by logging in without your private key, the attempt should be rejected.
Installing Iptables and Setting Up Basic Firewall Rules
To protect against attackers who take advantage of open ports, we should install iptables and set our default firewall rules. For now, we’ll just block everything except localhost, network pings, and SSH on port 22.
-
Install
iptables
using
apt-get
sudo apt-get install iptables -y
-
Create
a
new
file
for
our
default
firewall
settings
sudo nano /etc/iptables.firewall.rules
-
Put
the
following
text
into
the
file,
then
save
it
and
exit
*filter # Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0 -A INPUT -i lo -j ACCEPT -A INPUT -d 127.0.0.0/8 -j REJECT # Accept all established inbound connections -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow all outbound traffic - you can modify this to only allow certain traffic -A OUTPUT -j ACCEPT # Allow SSH connections # The -dport number should be the same port number you set in sshd_config -A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT # Allow ping -A INPUT -p icmp --icmp-type echo-request -j ACCEPT # Log iptables denied calls -A INPUT -m limit --limit 5/min -j LOG --log-prefix "[NETFILTER] denied: " --log-level 7 # Drop all other inbound - default deny unless explicitly allowed policy -A INPUT -j DROP -A FORWARD -j DROP COMMIT
-
Save
and
exit
nano,
then
apply
the
rules
sudo iptables-restore < /etc/iptables.firewall.rules
-
Check
to
see
that
the
rules
are
in
place
sudo iptables -L
You should get an output like this:
Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere REJECT all -- anywhere loopback/8 reject-with icmp-port-unreachable ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh ACCEPT icmp -- anywhere anywhere icmp echo-request LOG all -- anywhere anywhere limit: avg 5/min burst 5 LOG level debug prefix "[NETFILTER] denied: " DROP all -- anywhere anywhere Chain FORWARD (policy ACCEPT) target prot opt source destination DROP all -- anywhere anywhere Chain OUTPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere
-
All
good!
We
just
need
to
make
sure
those
rules
get
loaded
on
every
reboot.
To
do
that,
we’ll
need
to
create
a
script:
sudo nano /etc/network/if-pre-up.d/firewall
-
Put
the
following
code
in
the
file:
#!/bin/sh /sbin/iptables-restore < /etc/iptables.firewall.rules
-
Save,
exit,
nano,
and
make
the
file
executable
by
root
and
not
accessible
by
anyone
else.
sudo chmod 700 /etc/network/if-pre-up.d/firewall
- Test by rebooting and checking iptables right after you’re able to login again.
-
After
confirming
that
the
firewall
is
automatically
restored
on
boot,
let’s
make
the
system
logger
divert
all
iptables-related
rules
to
a
different
log
file.
This
will
come
in
handy
when
we
need
to
analyze
the
logs,
saving
us
the
time
to
sort
out
the
firewall
log
from
other
log
entries.
First,
let’s
create
a
new
file:
sudo nano /etc/rsyslog.d/iptables.conf
In the file, enter the following:
:msg, contains, "[NETFILTER]" /var/log/netfilter.log :msg, contains, "[NETFILTER]" ~
Save and exit, and then restart rsyslog service:
sudo service rsyslog restart
After doing this you should have all log messages having the prefix [NETFILTER] stored in /var/log/netfilter.log.
NOTE: This build will eventually evolve into a server, which means we will need some more ports opened for our services to be able to function properly. When you have your services up and running locally but can’t access it from your network, just remember to check your iptables settings and make sure it’s not blocking your service port.
Installing fail2ban
The last item in our security checklist is installing a piece of software called fail2ban. It will monitor our log files for failed login attempts. After an IP address has exceeded the maximum number of authentication attempts, it will be blocked at the network level and the event will be logged in /var/log/fail2ban.log. To install it, issue the following command:
sudo apt-get install fail2ban -y
Getting The System Up-to-Date
Now the system is relatively secure and almost ready, but before we proceed with actually building the server, let’s upgrade everything first.
-
Update
all
installed
software
packages:
sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y
-
Update
the
Pi’s
firmware
while
we’re
at
it
sudo apt-get install rpi-update -y sudo rpi-update
That’s it, now we have a secured minimum system ready to build. What servers can we build from this starting point? That depends on your imagination. Enjoy!
References and Further Reading
These articles are a good read if you’re into setting up your own RaspberryPi-based server. I believe they use the standard Raspbian Wheezy image for their tutorials, but most of the commands will run just fine.
- How to set up a secure Raspberry Pi web server, mail server and Owncloud installation — pestmeester.nl
- Setting up a (reasonably) secure home web-server with Raspberry Pi — Matt Wilcox
Please have a look at them if you’re interested in learning more. Meanwhile, I’ll be documenting my own endeavor to build my server based on MinibianPi (as opposed to standard Raspbian Wheezy).
To copy the public key to the raspberry the following command can be used:
ssh-copy-id user@192.168.1.111
Also root login without password (this means only with a key) can be allowed in /etc/ssh/sshd_config with the following entry:
PermitRootLogin without-password
Kind regards
Moo
Thanks for this helpful read. Great entry for a start with Minibean. Well structured.
Regards
mpr