Reading List

The Selfish Gene
The Psychopath Test: A Journey Through the Madness Industry
Bad Science
The Feynman Lectures on Physics
The Theory of Everything: The Origin and Fate of the Universe


ifknot's favorite books »

Monday 24 November 2014

RaspberryPi Server (Part 2): Security

Getting your head into RaspberryPi security.

TL;DR Having previously setup the RPi as a headless device logging in over ssh here the default password was changed. However, if the RPi is to function as a server then adding a new superuser, deleting the default pi user, enabling passwordless login using ssh keys, disabling password login, restricting incoming connections to port 22 only, banning IPs that fail repeatedly and setting up a restart watchdog timer will go some way to hardening the diminutive server.

UPDATE: "macOS keeps asking my ssh passphrase since I updated to Sierra" *sigh* do this:

 ssh-add -K


This stores passphrases in your keychain.



Setting up a new superuser.


The Raspbian Debian Linux image optimised for the RaspberryPi comes with the default user pi and default password raspberry. Therefore, the most logical step is to change the default password using the passwd command and following the prompts.

However, it makes even more sense to add a completely new user, create them a home directory, set a secure password and then remove the pi user from the system all together. The shell script adduser utility is a front end to useradd that simplifies the process and ensures system compliance, thusly:
sudo adduser johndoe
And follow the onscreen instructions.

In order to mimic the default pi user's privileges, with a view to usurping it later, your new user will now need to be added to the same groups as the original pi user. This can be elucidated by revealing all of the groups that pi belongs to:
groups pi
Which produces a list of groups that pi belongs to separated by spaces, convert this list to one that is separated by commas only and then user the usermod command with the --group switch to add the new user to the same groups as pi:

sudo usermod --groups adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,netdev,input,spi,gpio johndoe
You can double check that the new user and pi groups match by reissuing the groups command for pi and the new user or, if you want to get down to the nitty gritty of it, you can examine the system 'groups' file that the above commands modify for you - because, of course, messing with these files directly can be a recipe for disaster.
sudo nano /etc/group
Seeing that for each occurrence of 'pi' there is an occurrence of the new user, for example:

adm:x:4:pi,johndoe

Finally, log out of this session and log in again as the new user:
exit

Getting rid of the default pi user. 


Having logged back in under the new user:
ssh johndoe@xx.xx.xx.xx
Now to get rid of the default 'pi' user from the system with the deluser utility and the --remove-home flag to expunge its home directory: (With great power comes great responsibility.)
sudo deluser --remove-home pi
Then log out from the RPi again ready for the next step of its hardening.
exit

Setting up passwordless access.
(modified from http://blog.self.li/post/63281257339/raspberry-pi-part-1-basic-setup-without-cables)


Public key authentication allows you to login to a remote host via the SSH protocol without a password and, being free of dictionary attacks, is more secure than password-based authentication. SSH keys are a way to identify trusted computers, without involving passwords.

The first job is to get an SSH Key onto your OS X system, so follow this guide from GitHub to get yours.

Under normal circumstances the next step would be to copy this key to the Raspberry Pi using the ssh-copy-id script, however, and unfortunately, although BSD based OS X does not posses the ssh-copy-id script. However, Aaron Glenn has aMac OSX port of the useful unix utility ssh-copy-id for download.

Once installed go ahead and copy your public ssh key into RPi with:
ssh-copy-id johndoe@xx.xx.xx.xx
Test that you can now ssh into the RPi without needing to enter a password:
ssh johndoe@xx.xx.xx.xx
If everything has worked then you will not have been asked to enter a password. If this is indeed the case then you are ready for the next step...

How To Fix Offending key in ~/.ssh/known_hosts file


Following error will be displayed when the remote host key changes (after you’ve connected earlier with a valid remote host key).

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
a7:a8:f2:97:94:33:58:b7:9d:bc:e0:a6:6b:f7:0a:29.
Please contact your system administrator.
Add correct host key in /home/ramesh/.ssh/known_hosts to get rid of this message.
Offending key in /home/ramesh/.ssh/known_hosts: 4
Permission denied (publickey,password).

The offending key will have to be removed in order to proceed further.
Within OS X it is necessary to use the following Perl solution:
perl -pi -e 's/\Q$_// if ($. == 4);' ~/.ssh/known_hosts

Disable password login.


If you are certain that passwordless ssh key log in is working correctly then go ahead and disable password log in to the RPi.

To do this directly edit the system sshd_config file:
sudo nano /etc/ssh/sshd_config
And change the following values within the file:

#change it to no
PermitRootLogin yes

#uncomment and change it to no
#PasswordAuthentication yes

Then log out from the RPi once again:
exit
  • From now on in you will only be able to ssh into your RPi with your private SSH key. 
  • Nobody will be able login to the RPi with the default user and password.
  • Nobody knowing your user name will be able to login to your RPi by mounting a dictionary attack on your password.

Restricting incoming connections only to 3 standard ports only.


There are several worms which attempt to exploit vulnerable SSH servers, by logging in to a host with a collection of usernames and passwords such as "admin/admin", "test/test", "root/root", etc. These shouldn't be of much concern if you're keeping good passwords, but there are simple ways to prevent them regardless.

For the Raspbian operating system of the would-be RPi server using iptables to restrict access to the RPi by modifying the system interfaces file to pull in a tables file that define tables, as filters, containing chains of rules for the treatment of packets will enable the new superuser account to restrict incoming connections to the standard ports:

  • Allow HTTP  connections from anywhere on port 80
  • Allow HTTPS connections from anywhere on port 443 (the normal ports for websites)
  • Allow SSH connections from anywhere on port 22 (or go further and restrict to certain IPs only)

The iptables administration tool provides packet filtering, network address translation (NAT) and other packet mangling but firstly have a look at the current state of affairs:
sudo iptables --list
Which generates the following report:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination 

This allows anyone access to anything from anywhere! Time to batten down the hatches against the vicissitudes of the WWW. Begin by modifying the system interfaces file directly once again (like in part 1):
sudo nano /etc/network/interfaces
Add the following at the end of the file:
pre-up iptables-restore < /etc/network/iptables.rules
CTRL-O to save and CTRL-X to exit nano.

This instructs iptables to pull in the iptables configuration file (that will be created next) before the firewall is up.

Create the configuration file:
sudo nano /etc/network/iptables.rules
And populate it with the following basic rules (courtesy of the Debian WiKi):

*filter

# Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

# Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allows all outbound traffic
# You could modify this to only allow certain traffic
-A OUTPUT -j ACCEPT

# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

# Allows SSH connections 
# The --dport number is the same as in /etc/ssh/sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

# Now you should read up on iptables rules and consider whether ssh access 
# for everyone is really desired. Most likely you will only allow access from certain IPs.
# https://www.debian-administration.org/article/87/Keeping_SSH_access_secure

# Allow ping
#  note that blocking other types of icmp packets is considered a bad idea by some
#  remove -m icmp --icmp-type 8 from this line to allow all kinds of icmp:
#  https://security.stackexchange.com/questions/22711
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# log iptables denied calls (access via 'dmesg' command)
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Reject all other inbound - default deny unless explicitly allowed policy:
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

As you can see this is a big improvement, accepting incoming SSH connections only on port 22 and HTTP/HTTPS on the standard ports for websites, logging denied calls and rejecting all other inbound traffic. However, the new filter rules must first be activated:
sudo iptables-restore < /etc/network/iptables.rules
Take a look at the effect of the new rules:
sudo iptables --list
And in order for the new filter rules to endure into the next startup they must be saved:
sudo iptables-save
It is likely that once your RPi server is up on the web then within a short timespan it will be subject to relentless attempts to login to it. The next step is to ban those IP addresses that repeatedly fail to login.

Automatically ban IP addresses that are repeat login failures.
(modified from www.digitalocean.com/community/tutorials/how-to-install-and-use-fail2ban-on-ubuntu-14-04)


A service called fail2ban can mitigate recurring malicious approaches to an RPi server by creating rules that can automatically alter the firewall configuration based on a predefined number of unsuccessful login attempts. This will allow the server to respond to illegitimate access attempts without administrator intervention:
sudo apt-get install fail2ban
The fail2ban service keeps its configuration files in the /etc/fail2ban directory. There is a file with defaults called jail.conf.

Since this file can be modified by package upgrades, it should not be edited in-place, but rather copied so that changes can be made safely. This file must be copied specifically to a file called jail.local for fail2ban to find it:
sudo apt-get install fail2ban
Restart the fail2ban service:
sudo service fail2ban restart
At any time to review the automatic modifications that may have been made:
sudo iptables --list
The RPi is a stable device and will provide a high hardware uptime for a server, but nothing is perfect and should the RPi system hang for some reason then having seen means of automatically rebooting it would be useful.

Setting up an automatic reset watchdog timer.
(modified from http://pi.gadgetoid.com/article/who-watches-the-watcher)


The RPI's Broadcom BCM2708 has a hardware watchdog which, with a simple kernel module and watchdog daemon, can automatically reset the Pi when/if it ever freezes.

Firstly use modprobe to add the aforementioned kernel module:
sudo modprobe bcm2708_wdog
Then directly modify the system modules file to have the watchdog module loaded:
sudo nano /etc/modules
By adding the module name at the bottom of the file:

bcm2708_wdog

CTRL-O to save and CTRL-X to exit.

Next install the watchdog daemon service with chkconfig (to remove the burden of fiddling with the system runlevel information directly). This service does little more than send /dev/watchdog a heartbeat every 10 seconds if /dev/watchdog fails to receive this signal it does a hard reboot of the RPi.
sudo apt-get install watchdog chkconfig
Configure watchdog:
sudo nano /etc/watchdog.conf
Uncomment the following:

max-load-1 #to reset RPi if the load average exceeds 24 in any 1-minute span.
watchdog-device 

Add it to startup applications:
chkconfig watchdog on
Finally, get it up and running:
sudo /etc/init.d/watchdog start
Use chkconfig --list or top to see a list of services at boot and see currently active services.

The RPi is now secure and hardened ready for the interwebs!

Credits.


photo credit: Howard Dickins via photopin cc

No comments:

Post a Comment