Raspberry Pi security
Although focusing on the Raspberry Pi, this article is intended not just helping securing your Raspberry Pi but any other Linux operating system in general as well as any other Debian based distros.
Right out of the box your Raspberry Pi is not secure and thus vulnerable to potential well planed attacks and therefore you should harden it with security in mind. This tutorial requires superuser access either root or sudo permissions.
Re-generate SSH keys
If you have not hardened your raspberry pi yet you should always assume that the ssh keys are compromised. Therefore, you must re-generate them for your own usage by removing the old ones and create new ones.
rm -v /etc/ssh/ssh_host_* dpkg-reconfigure openssh-server
Password
After installation your Raspberry Pi login is an easy target to aim. It should be changed, locked or even removed.
Add a new user:
useradd --groups sudo -m copperfield
Change password to a passphrase such as: t0d@y!sth3b3std4yOf2020]
passwd copperfield
Next, reset the root password. Choose another long and hard passphrase to guess like previously shown
passwd root
Remove the pi user:
userdel -fr pi
Securing SSH
Edit sshd_config
nano -w /etc/ssh/sshd_config
# Make sure only the users you allow, are actually the only ones able to try to connect and adding their ip will be even more secure. AllowUsers copperfield # AllowUsers copperfield@ip # is more restrictive # AllowUsers copperfield@ip root@ip # is even more restrictive Port 22022 # Changing to a non default port is a good practice. # Authentication: LoginGraceTime 2m PermitRootLogin no # PermitRootLogin prohibit-password # to allow only with ssh key StrictModes yes MaxAuthTries 3 PubkeyAuthentication yes AuthorizedKeysFile %h/.ssh/authorized_keys # To enable empty passwords, change to yes (NOT RECOMMENDED) PermitEmptyPasswords no # Change to yes to enable challenge-response passwords (beware issues with # some PAM modules and threads) ChallengeResponseAuthentication no # Change to no to disable tunneled clear text passwords PasswordAuthentication no UsePAM no
SSH keys
Next, and as regular user, (not root or sudo) generate an Ssh keypair and create a .ssh directory in your user’s (Copperfield) home directory and an authorized_keys file with the following commands. Be sure to set the permissions properly (otherwise the key based authentication will fail):
mkdir ~/.ssh touch ~/.ssh/authorized_keys touch ~/.ssh/known_hosts chmod 600 ~/.ssh/known_hosts chmod 600 ~/.ssh/authorized_keys
cd ~/.ssh/ ssh-keygen -t ecdsa -b 521 -f <key_name_of_your_choice>
For added security you may want to add a password to this pub key when you are asked about it. This is recommended.
cat <key_name_of_your_choice.pub> >> ~/.ssh/authorized_keys
Make sure that <key_name_of_your_choice> does not stay on the raspberry pi. That is your private key.
systemctl enable ssh systemctl restart ssh
Firewall
You should configure the firewall so that it logs a message whenever a firewall rule is activated and a connection is blocked.
Lets install what is needed:
apt-get install iptables iptables-persistent netstat-nat
Check for any previous rules:
iptables -L
Create a basic rule to ensure ssh on port 22020. If the port changes, also change the number here:
nano -w /etc/iptables/rules.v4
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] # 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 SSH connections # The --dport number is the same as in /etc/ssh/sshd_config -A INPUT -p tcp -m state --state NEW --dport 22022 -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
Enable and start the service
systemctl enable netfilter-persistent.service systemctl start netfilter-persistent.service
openvpn
If you are going to use openvpn, you will need to add a specific rule set at the begining of the iptables configuration file. OpenVPN may do this for you if you are using pivpn.
nano -w /etc/iptables/rules.v4
Add this at the top:
*nat :PREROUTING ACCEPT [319:21288] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [3:464] :POSTROUTING ACCEPT [3:464] -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE COMMIT
Add this after the ssh rule:
# Allows openvpn connections -A INPUT -p udp -m state --state NEW -m udp --dport 1195 -j ACCEPT -A INPUT -i tun+ -j ACCEPT -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT -A INPUT -j REJECT --reject-with icmp-port-unreachable -A FORWARD -i tun+ -j ACCEPT -A FORWARD -i tun+ -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT -A FORWARD -i eth0 -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT
Disable ICMP
Do not reply to external ping requests but allow doing them to others
nano -w /etc/iptables/rules.v4
Add this at the bottom and before COMMIT:
-A INPUT -p icmp --icmp-type echo-request -j DROP -A OUTPUT -p icmp --icmp-type echo-request -j ALLOW
Apply rules
Next, ensure your iptables are working properly:
iptables-apply /etc/iptables/rules.v4 iptables-save
Check and confirm rules:
iptables -L
Log file
You can read the log in real time by doing:
tail -f /var/log/debug
and on Linux Mint:
tail -f /var/log/kern.log
Hide SSH with tor
The best you can do to secure ssh access to your Raspberry Pi is to access ssh using a tor hidden service. Doing so, not only hides the service on ipv4 and ipv6 as well as will bypass hardware firewalls and will not need configuration behind them.
Lets install what is needed:
apt-get install tor
Backup default configuration file:
mv /etc/tor/torrc /etc/tor/torrc-default
Create new configuration file:
nano -w /etc/tor/torrc
Add the following inside:
# Defaults at /usr/share/tor/tor-service-defaults-torrc User debian-tor RunAsDaemon 1 PIDFile /var/run/tor/tor.pid Log notice file /var/log/tor/tor.log DataDirectory /var/lib/tor/services DataDirectoryGroupReadable 0 ## Hidden service configuration # Version 3 HiddenServiceDir /var/lib/tor/services/ssh HiddenServiceVersion 3 HiddenServicePort 22022 127.0.0.1:22
Edit tor-service-defaults-torrc and comment to close SocksPort 9050
nano -w /usr/share/tor/tor-service-defaults-torrc #SocksPort 9050
Enable and start tor hidden service:
systemctl enable tor systemctl start tor
Find your tor hidden service address for port 22022:
cat /var/lib/tor/services/ssh/hostname
And you will get something like this which will be your raspberry pi hidden address:
dkfljsdfsdlksdcvoiskdcvklscsdcsdmcsdmcklsdmlcmsdkciwejfowpef.onion
To connect to your hidden ssh raspberry pi service you need torsocks to be running on your client.
torsocks ssh -x -i <key_name_of_your_choice.key> user@6dkfljsdfsdlksdcvoiskdcvklscsdcsdmcsdmcklsdmlcmsdkciwejfowpef.onion -p 22022
ChrootDirectory jail
The term chroot refers to a process of creating a virtualized environment in a Linux or Unix operating system, separating it from the main operating system and directory structure. This process essentially generates a confined space, with its own root directory, to run software programs.
Edit sshd_config and add the following configuration at the very end of the configuration file. This can be done for any user or more than one user and or group of users.
nano -w /etc/ssh/sshd_config
Match User copperfield ChrootDirectory /home/copperfield AllowTCPForwarding no X11Forwarding no ForceCommand internal-sftp PermitTunnel no
Disable ipv6
Disabling IPv6 minimizes potential network attacks as it is as if you were uninstalling a second network adapter.
Edit:
nano -w /etc/sysctl.conf
and add this line, save and exit the editor:
net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1 net.ipv6.conf.tun0.disable_ipv6 = 1
In your terminal type to commit changes:
sysctl -p
Unattended Upgrades
The purpose of unattended-upgrades is to keep the computer current with the latest security (and other) updates automatically.
Ensure Continuity
The Raspberry pi can crash when you are away, making all that depends on it to become offline but you can use it's broadcom hardware watchdog timer that can reboot the Raspberry pi in case it becomes unresponsive.
We need to use the bcm2708 module and make it persistent:
modprobe bcm2708_wdog echo bcm2708_wdog >> /etc/modules
Packages needed:
apt-get install watchdog chkconfig
Enable and activate watchdog:
chkconfig watchdog on systemctl enable watchdog /etc/init.d/watchdog start
Configure the watchdog:
nano -w /etc/watchdog.conf
Uncomment the line #watchdog-device = /dev/watchdog so it reads:
watchdog-device = /dev/watchdog
The watchdog daemon will send /dev/watchdog a heartbeat every 10 seconds. If /dev/watchdog does not receive this signal it will restart your Raspberry Pi.
Receive reports
Install the package:
apt-get install logwatch exim4 exim4-config
Re-configure it:
dpkg-reconfigure exim4-config
Edit email setup:
nano -w /etc/exim4/passwd.client
Add something to passwd.client like:
*.google.com:your_account_name@gmail.com:your_password
Restart exim4
systemctl restart exim4
Test the email setup on another shell by doing:
mail -s Test me@somemail.web Test . Cc:
And confirm reception.
Edit and adjust logwatch as needed:
nano -w /usr/share/logwatch/default.conf/logwatch.conf
Real mail logs in real time with:
tail -f /var/log/exim4/mainlog
See also
Links
- What is a Raspberry PI
- Raspberry Pi (wikipédia)
- ssh-keygen pair
- Who watches the watcher
- Watchdog timer