In many operating systems the Pi gets a user and a password, the ports are open and the security is not covered. This article is about 17 ways to increase the security of your Pi. Not all tips have to be applied but it is recommended depending on the access possibilities of attackers.
Updates
Keep your system up to date! The first point may seem obvious, but it is an important one. With the updates in the Raspbian repository you not only get latest features, but most importantly security fixes for your installed software
Try to keep your Raspberry Pi regularly updated:
sudo apt update
sudo apt upgrade
You can also automate this process with the “unattended-upgrades” package. With this procedure, you can automatically install security fixes every day:
- install the unattended-upgrades package.
sudo apt install unattended-upgrades. - open the configuration file
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades. - change what you want in this file. By default, only security updates are downloaded, but you can change this if you want to install all Debian updates or even other repositories. I recommend commenting out at least this line:
Unattended-Upgrade::Mail "root";This sends a mail to root (or another address if you have a mail server installed). Save and exit (CTRL+O, CTRL+X) - Then we need to set the periodic upgrade. Open this file:
sudo nano /etc/apt/apt.conf.d/02periodic. Add these lines (the file should be empty, if not, change the values):
This will activate the automatic update every day. We ask apt to run update, download upgrades, install upgrades, auto-clean every day. The last line is the verbose level you get in ‘/var/log/unattended-upgrades’ and email (1=low, 3=max). Save and exit (CTRL+O, CTRL+X).APT::Periodic::Enable "1"; APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Download-Upgradeable-Packages "1"; APT::Periodic::Unattended-Upgrade "1"; APT::Periodic::AutocleanInterval "1"; APT::Periodic::Verbose "2"; - this should be fine, you can debug your configuration with this command:
sudo unattended-upgrades -dDon’t forget to check the log file and/or the email you received to make sure everything is working as expected
Do not use auto-login or blank passwords.
Passwords are an important part of system security. Make sure all critical access points ask for a password. Don’t use auto-login and add a login step for every application you can access directly. I won’t list all applications, but if you have a web server, for example, make sure that personal data or administration pages cannot be accessed without a password.
Make sure no one uses a blank password on the Raspberry Pi. If you have only a few user accounts, it is easy to check all access. If you have many user accounts, these commands might help:
- Look for empty passwords:
sudo awk -F: '($2 == "") {print}' /etc/shadowThis will only show accounts with an empty password. - Lock insecure accounts
passwd -l <username>
Changing the default password for pi
A common mistake is to leave the default password for the Pi user (raspberry). Anyone who has used a Raspberry Pi knows this password. So many people scan SSH ports and try to log in with “pi”/“raspberry”.
Changing the default password should be the first thing you do when reinstalling.
Doing this is easy, log in as pi and type this command: passwd.
Try to use a phrase with more than 15 characters to be safe from brute force attacks and easy to remember (e.g.: thisisasecurepassword4denPi is a good, easy to remember password)
Disable the pi user
As I said earlier, the pi user is one of the most commonly forced logins with root. Hackers have a list of commonly used logins and mainly try these.
If possible, create a new user and disable the pi user to prevent these types of attacks:
- Create a new user
sudo adduser <username> - Give him the sudo right if necessary
sudo adduser <username> sudoThis will add the new user to the sudo group - Check that everything is working correctly (ssh access, sudo, …).
- If necessary, copy files and permissions from the pi user to the new user
sudo cp /home/pi/documents/* /home/<username>/documents/…sudo usermod -a -G adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,netdev,gpio,i2c,spi alice. - Delete the pi user
- first kill all processes of the user
sudo pkill -u pi - and then delete the account
sudo deluser -remove-home pi.
- first kill all processes of the user
If you prefer, you can first block the account (as described before) and only delete it after a few weeks when you are sure that everything is in order
Stop unnecessary services
On the Raspberry Pi we do a lot of projects on top of everything, and this could be a bad habit for security Let’s say you installed PHPMyAdmin 3 months ago to try something out, but you no longer use it This could create a loophole for an attacker to get into your system
Try stopping or uninstalling services and applications you don’t need
- To stop a service, use:
sudo service <service-name> stop. - If it starts automatically at boot time, try:
sudo update-rc.d <service-name> remove. - Or to uninstall it, it should be something like:
sudo apt remove <service-name>
Ask for a password for sudo
As you should know, sudo does not always ask for a password Most of the time you don’t need to type your password again It’s cool for productivity, but it’s not a good idea for security reasons
If someone manages to get terminal access to your Raspberry Pi as a power user, the super-user privileges are accessible even without a password I recommend asking for a password when using sudo:
- Edit this file
sudo nano /etc/sudoers.d/010_pi-nopasswd - Find this line
pi ALL=(ALL) NOPASSWD: ALLOr all other users if you followed the previous steps - Replace it with this
pi ALL=(ALL) PASSWD: ALLDo the same for each user with sudo access - Save and exit (CTRL+O, CTRL+X)
SSH: Prevent root login
As mentioned earlier, root and pi users are often the main target for brute force attacks. Usually, this is done via SSH.
So you need to make sure that root does not have direct SSH access If you need root, log in with your normal user (not pi) and then use sudo to get superuser privileges
By default, root access is disabled You can check this:
- Open the configuration file of the SSH server
sudo nano /etc/ssh/sshd_config. - Look for this line
#PermitRootLogin prohibit-passwordIf you have something else, comment this line out (by adding # to the beginning) - Save and exit (CTRL+O, CTRL+X)
- Restart the SSH server
sudo service ssh restart.
It is also possible to block or allow certain users from using SSH. To do this, we use the lines AllowUsers <username> and DenyUsers <username> in the file /etc/ssh/sshd_config and restart the service.
SSH: Changing the Default Port
The SSH default port is 22. Therefore, attackers will always create bots that attempt to log in on this port. To prevent this, you can change the default port and set a different one
- Edit the configuration file of the SSH server
sudo nano /etc/ssh/sshd_config. - Look for this line
#port 22 - Replace the port with whatever you want
Port 1111as an example - Make sure you don’t take a port you use for something else List of known ports on Wikipedia 🔗
- Save and exit (CTRL+O, CTRL+X)
- Restart your server
sudo service ssh restart.
Don’t forget to adjust the firewall rules if you have one Run a new connection test before closing the current connection, this might help you if you made a mistake
You can add the connection via the new port with the ‘-p’ option
ssh <username>@<ipadress> -p 1111
SSH: Use SSH keys instead of passwords
With the previous steps we have already blocked most script kiddies We now move on to things that can protect you even if you are facing a strong hacker who is only targeting your system
Using a strong password will slow down his attack, but it is always possible for him to find it, even if it takes weeks to find the right password What you can do to block him is to use SSH keys instead of passwords for your SSH connections An attacker could guess a 15-digit password, but not an SSH key
The main idea is to generate a key on your computer and then add it to the Raspberry Pi to allow a connection from your computer (with or without a password)
- if you don’t already have one, create your SSH keys with this command:
ssh-keygen -t rsa. Just press enter for each question, the default path and no password - copy the public key file to your Raspberry Pi:
cp ~/.ssh/id_rsa.pub pi@IP:/home/pi/your_key.pubwith a changed SSH port you can use scp:scp -p 1111 ~/.ssh/id_rsa.pub pi@IP:/home/pi/your_key.pubReplace IP with the IP address of your Raspberry Pi and name the key as you wish - add this key to the allowed keys on the Raspberry Pi with this command:
cat /home/pi/you_key.pub >> ~/.ssh/authorized_keys. SSH now needs authorisation to use this key. For this, two lines in ‘/etc/ssh/sshd_config’ are un-commented:PubkeyAuthentication yesandAuthorizedKeysFile .ssh/authorized_keys. - try to connect again:
ssh pi@IPYou should not need to enter a password and you should be able to log in directly. 6. - to disable password login altogether and only allow access to users with the SSH key, we need to make changes to the .config file -
sudo nano /etc/ssh/sshd_config- here we change:bash ChallengeResponseAuthentication no PasswordAuthentication no UsePAM no- Save and restart service.
Install Fail2ban
Fail2ban is a tool to detect and block brute force attacks. In the previous steps I said that an attacker could try for months to find your password and maybe he could succeed The main purpose of Fail2ban is to prevent this from happening
Fail2ban blocks the attacker’s IP if they fail to log in more than X times You can configure the number of attempts before blocking and the duration of blocking Follow these steps to install Fail2ban on your Raspberry Pi:
- install the package
sudo apt install fail2ban - by default, fail2ban will ban the attacker for 10 minutes after 5 failed attempts.
I think this is fine for now, but if you want to change this, all the configuration is in the ‘/etc/fail2ban’ folder in ‘/jail.conf’ and ‘jail.local’. If there is no ‘jail.local’ file, you can create one with
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.localand write to it usingsudo nano /etc/fail2ban/jail.local.[ssh] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 6 - restart the service if you have made any changes with
sudo service fail2ban restart
This should really slow down your attacker 5 attempts every 10 minutes, that’s 720 attempts per day If your password is not like “password” or “123456789”, it should take a very long time to find it
Install a firewall
In case you don’t know: With a firewall, you can block all ports except the ones you need and filter access by IP For example, you can block everything and only allow SSH access from your computer’s IP address
I’m used to installing iptables for my firewall rules, but maybe that’s not the easiest way to do it for a beginner So I’ll explain how to install ufw (Uncomplicated FireWall), which is easier, and then allow only what you need
Uncomplicated Firewall
It’s a basic configuration with HTTP access for everyone and SSH only for you, but you need to adapt this to what you want to do
- install the firewall package
sudo apt install ufw - allow access for everyone on HTTP and HTPS
sudo ufw allow http #port 80 sudo ufw allow https #port 443 - allow SSH access for own IP address only
sudo ufw allow from <IpAddress> port 22Don’t forget to replace the values with your own settings In a local network, you can find out your IP address with ipconfig (Windows) or ifconfig (Linux/Mac) If you changed the SSH port in the previous step (to 1111 or something else), replace it here. 4. - enable the firewall
sudo ufw enable. Be careful, this will enable the firewall now and also at boot time. If you lose access to your device, you will not be able to fix this, even after a reboot You will need to change the configuration directly on the Raspberry Pi (physically) - check if everything is OK
To view your current rules after activating ufw, use this command:
sudo ufw status verbose.
For more complex configurations, please read the man page
iptables
-
install the package iptables-persistent with the command apt-get.
sudo apt install iptables-persistent. In the menu, select ‘Yes’ for the rule.v4 file. The second selection is for the rule.v6 and IPv6 support, select it according to your needs. -
after the installation is complete, go to:
sudo nano /etc/iptables/rules.v4. -
now you will see the existing iptables configuration, in my case, since there are no rules set up yet, it is completely empty:
# Generated by iptables-save v1.4.14 on Fri Dec 26 20:13:04 2014 *Filter. :INPUT ACCEPT [5897:7430402] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [1767:169364] COMMIT # Completed on Fri Dec 26 20:13:04 2014Now you can start creating your iptables in this file, one per line, just before the COMMIT command. When you are done, save the file. I would suggest adding at least the following rule to validate our concept.
sudo iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j REJECT. The above rule filters incoming ICMP type 8 traffic and responds with a “Destination port unreachable” message and will only take effect after the Pi is rebooted. -
ping the device, it should respond normally. Now reboot the unit. 5.
-
after the device is powered on again, ping it again. This time you should get the message “Destination port unreachable”. The iptables have been loaded successfully, congratulations. Now issue
iptables -L:Chain INPUT (policy ACCEPT) target prot opt source destination REJECT icmp - anywhere anywhere icmp echo-request reject-with icmp-port-unreachable Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destinationOur rule is in the third line. Now you can add the rest of the rules according to step 3.
Extra tip: If you prefer to add the rules directly in iptables and not in the file, the following command can be useful:
/etc/init.d/iptables-persistent save. This command takes the current configuration of your iptables and saves it to the rules.v4 file.
Removing unused network-oriented services
Almost all Linux server operating systems have a few network-related services enabled. Most of them you will want to keep. However, there are a few that you may want to remove. You can view all running network services with the command ss:
sudo ss -atpu.
The output of ss will vary depending on your operating system. This is an example of what you might see. It shows that the SSH (sshd) and Ngnix (nginx) services are listening and ready to connect:
tcp LISTEN 0 128 *:http *:* users:(("nginx",pid=22563,fd=7))
tcp LISTEN 0 128 *:ssh *:* users:(("sshd",pid=685,fd=3))
How you proceed to remove an unused service (<service_name>) depends on your operating system and the package manager you are using. To remove an unused service on Debian/Ubuntu:
sudo apt purge <service_name>
Disable unwanted Linux services
Disable all unnecessary services and daemons (services that run in the background). You must remove all unwanted services from the system startup. Output a list of services showing which runlevels are enabled or disabled at any one time
systemctl list-unit-files --type=service
systemctl list-dependencies graphical.target
Turn off service at boot time
systemctl disable service
systemctl disable httpd.service
Start/stop/restart service
systemctl disable service
systemctl disable httpd.service
close unused ports
Use the following command to list all open ports and associated programs:
netstat -tulpn
OR use the ss command as follows:
ss -tulpn
OR
nmap -sT -O localhost
nmap -sT -O server.example.com
Back up your system
One of the worst consequences of an attack is to lose data. If you back up your files correctly and regularly, you will be safe even if the hacker has destroyed your SD card.
There are several methods you can use to back up your Raspberry Pi:
- Back up only important files (configuration, documents, mysql databases).
- Create a complete image of the SD card on another computer.
- Or make a full backup of the Raspberry Pi while it is running.
It all depends on how you use the Raspberry Pi and what your network looks like. For our server, we will use Borg backup and control it via a script; the backup will be automatically deduplicated, encrypted and backed up to another server.
-
install necessary dependencies
sudo apt install python3 python3-dev python3-pip python-virtualenv libssl-dev openssl libacl1-dev libacl1 build-essential sudo apt install libfuse-dev fuse pkg-config # optional, for FUSE supportIf you get complaints about denied permissions in ‘/etc/fuse.conf’: On Ubuntu, this means your user is not in the ‘fuse’ group. Add yourself to this group, log out and log in again.
-
install BorgBackup
sudo apt install borgbackup. -
before a backup can be created, a repository must be initialised:
borg init --encryption=repokey user@hostname:/path/to/repo. This repository must be located on the hard disk on which the backup is to be stored later. In our case we used another computer in the network.Note from BorgBackup: The user under which the backup is saved should not be a standard or root account. It is best to create a ‘borg’ user beforehand and use it for all backup actions.
A Borg archive is the result of a single backup (borg create). An archive stores a snapshot of the data of the files ‘in’ it. You can extract or mount an archive later to restore it from a backup. Repositories are directories in the file system that function as self-contained stores of archives. Repositories can be accessed locally via the path or remotely via ssh. Under the bonnet, repositories contain data blocks and a manifest that records which blocks are in each archive. If some data has not changed from one backup to another, Borg can simply point to a block of data that has already been uploaded (deduplication).
-
before you start creating backups, please make sure that there is always a good amount of free space on the file system where your backup repository is located (and also on ~/.cache). A few GB should be enough for most disk-sized repositories. Borg does not use root reserved space on repository disks (even when running as root). On filesystems that do not support this mechanism (e.g. XFS), we recommend reserving some space in Borg itself to be on the safe side by adjusting the additional_free_space setting (a good starting point is 2 GB):
borg config /path/to/repo additional_free_space 2G.When Borg runs out of space, it tries to free up as much space as possible while safely aborting the current operation, which allows it to free up more space by deleting/pruning archives. This mechanism is not bulletproof under certain circumstances.
-
let’s create a script
sudo nano automatebackupthat controls the automatic backup operation and records our options. In this file we write:#!/bin/sh # Setting this, so the repo does not need to be given on the commandline: export BORG_REPO=ssh://username@example.com:2022/~/backup/main # See the section "Passphrase notes" for more infos. export BORG_PASSPHRASE='XYZl0ngandsecurepa_55_phrasea&&123' # some helpers and error handling: info() { printf "\n%s %s\n\n" "$( date )" "$*" >&2; } trap 'echo $( date ) Backup interrupted >&2; exit 2' INT TERM info "Starting backup" # Backup the most important directories into an archive named after # the machine this script is currently running on: borg create \ --verbose \ --filter AME \ --list \ --stats \ --show-rc \ --compression zstd,22 \ --exclude-caches \ --exclude '/home/*/.cache/*' \ --exclude '/var/cache/*' \ --exclude '/var/tmp/*' \ \ ::'{hostname}-{now}' \ /etc \ /home \ /root \ /var \ backup_exit=$? info "Pruning repository" # Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly # archives of THIS machine. The '{hostname}-' prefix is very important to # limit prune's operation to this machine's archives and not apply to # other machines' archives also: borg prune \ --list \ --prefix '{hostname}-' \ --show-rc \ --keep-daily 7 \ --keep-weekly 4 \ --keep-monthly 6 \ prune_exit=$? # use highest exit code as global exit code global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit )) if [ ${global_exit} -eq 0 ]; then info "Backup and Prune finished successfully" elif [ ${global_exit} -eq 1 ]; then info "Backup and/or Prune finished with warnings" else info "Backup and/or Prune finished with errors" fi exit ${global_exit}This script should only be readable and executable by the root user, which contains the address and password of our backup.
sudo chown root:root automatebackup sudo chmod 0700 automatebackup sudo chmod +x automatebackup -
start the script and test if the backup has been created
sh automatedbackup borg list user@hostname:/path/to/repo #lists all archivesTo restore a backup we can select and mount an archive
borg mount ssh://user@hostname:/path/to/repo::myserver-system-2019-08-11 /mnt/borg`
Encrypt your connections
This is an extensive topic and I won’t go into much detail, but I will give you an example.
With basic protocols, data flows on the network in plain text. This means that if you type in your password, a hacker could get it while listening to the network. Fortunately, there are often other protocols that work more securely by encrypting all data.
The first thing you should do is stop using insecure protocols (e.g. FTP, Telnet or HTTP). And then try to replace these with more secure accesses (SFTP, SSH, HTTPS).
The procedure depends on which protocols you use with your Raspberry Pi. Let’s take HTTP as an example: HTTP is fine if you only use it for static content, you never enter a password and you don’t have sensitive data But if you switch your application to the HTTPS protocol, you are still more secure. It’s pretty easy to do, you just need a certificate and change lines in the Apache or Nginx configuration. You can find a lot of helpful instructions on the internet
And most of the time it’s quite simple. You can switch from FTP to SFTP because your Raspberry Pi already has SSH enabled. Same goes for Telnet, why do you need Telnet when SSH is available?
Then look at all the protocols you use with sensitive data and what you can do to improve it
Use a VPN
A more radical option is to access your Raspberry Pi via a VPN. VPN stands for Virtual Private Network and allows you to remotely access all services on your Raspberry Pi as if you were on the local network. All data flows between you and the Raspberry Pi are encrypted using a strong protocol. This is a good option to prevent many ports from being opened on the Internet without security.
Protect physical access
The last protection is obvious but often ignored when we talk about security. You can configure all the security protocols, firewall and VPN from all the previous steps but if your Raspberry Pi is physically accessible to anyone, it is useless.
Make sure it can’t be easily stolen (or the SD card) or that no one could come in and plug in a keyboard and screen and be logged in automatically. The steps to implement to protect against this type of attack will depend on your system. Maybe you need an automatic logout after X minutes, a password in the grub boot menu or encryption of the data on the SD card.
Think about what would be the worst thing that could happen if someone gets physical access to your Raspberry Pi? And find solutions to block it
Check your logs regularly
The last two items on this list are not further protective measures, but rather a commitment to follow. Most of the time, attacks are visible in the log files, so try to read them regularly to spot suspicious activity.
All logs are located in the /var/log folder, but the main log files to check are:
/var/log/syslog: Main log file for all services./var/log/message: log file for the whole system/var/log/auth.log: all authentication attempts are logged here/var/log/mail.log: if you have a mail server, a record of the last emails sent can be found here- Any critical application log file, for example
/var/log/apache2/error.logor/var/log/mysql/error.log.
To simplify this work, there are some solutions. For example, you could configure syslog to send logs to a master server, with an interface to read them, filter them, etc. …
You could also use logwatch to get daily reports on system operation
Read the messages
To maintain a good level of security in your projects, try to stay updated all the time. I see new security vulnerabilities in many major software programs every day, and it can take weeks or more for the fix to be available in the Raspbian repository. If you read security news regularly, you can take quick action to stay protected.
Conclusion
That’s it, you now know the most important security steps to protect your Raspberry Pi. I know these are just the first steps, and there are other important ones too, but we’re talking about a Raspberry Pi here, not high-availability servers with tons of confidential data. I think you already have good protection if you implement the 17 ideas from this article.
💬 Comments
Comments are not enabled for this article yet.