Securing your Raspberry Pi
A bit more ...
Thanks to Mark for his presentation on Let's
Encrypt - I borrowed a bunch of ideas from there.
More information here:
- Change the pi password.
- As the pi user type passwd you will be prompted for the new
- Perhaps change the pi user name or remove it eventually
- We will be using a GUI desktop interface. By
default this does not have a password. We should set one.
- in /etc/lightdm/lightdm.conf change:
- Set a root password. There is discussion around this.
Some say don't become root. always use sudo <desired
command> Others argue it is better to do su - and then do
- Uncomment -i in /root/.bashrc for protection against
foolishness and clumsy fingers:
- # Some more
alias to avoid making mistakes:
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
- Do Updates
- update the package index: apt update
- update packages: apt upgrade
- upgrade system: apt
full-upgrade. May not want to do this.
- If you are starting with a new system then do the
above. If you have a lot of software already installed
you probably don't want to do a full-upgrade to the latest
version of the OS. Doing this will probably break some
Require sudo to have pw.
- Edit /etc/sudoers.d/010_pi-nopasswd # This allows pi
to su without a pw. We will change this:
- pi ALL=(ALL)
NOPASSWD: ALL to
- pi ALL=(ALL)
Add a new new non pi user. The pi user is known to the
world. If you are running Raspbian you will have a pi
- adduser foo
- to delete a user deluser --remove-home
- Add new user to sudo group in /etc/group. E.G.:
edit /etc/group and search for sudo and add your new user e.g.
- Add entry to /etc/sudoers.d/010_pi-nopasswd
- foo ALL=(ALL) PASSWD: ALL
- Perhaps change the pi id to something else to eliminate it as
a attack vectoradd
- To change the pi login to pip usermod --login pip --home pip pi
Set a hostname different from raspberry
- edit /etc/hostname and change the name from raspberry to
- reboot at some point to implement the new name
- sudo hostnamectl set-hostname <hostname>
ufw - user friendly firewall
- ufw is a somewhat more friendly front end to iptables and
iptables is the interface to the kernel netfilter
netfilter is a set of hooks inside the Linux kernel that allows
kernel modules to register callback functions with the network
stack. A registered callback function is then called back for
every packet that traverses the respective hook within the
iptables is a generic table structure for the definition
of rulesets. Each rule within an IP table consists of a
number of classifiers (iptables matches) and one connected
action (iptables target).
- Install ufw with
- This creates a bunch of files in /etc/ufw that are used to
ufw opens up more than what is shown above. From the man
- ufw status
- ufw allow ssh
- ufw enable
- ufw status verbose
Logging: on (low)
(incoming), allow (outgoing), disabled (routed)
ALLOW IN Anywhere (v6)
- ACCEPT certain icmp packets (INPUT and FORWARD):
destination-unreachable, source-quench, time-exceeded,
problem, and echo-request for IPv4. destination-unreachable,
packet-too-big, time-exceeded, parameter-problem,
and echo-request for
- ACCEPT icmpv6 packets for stateless autoconfiguration
- ACCEPT ping replies from IPv6 link-local (fe80::/10)
- ACCEPT DHCP client traffic (INPUT)
- DROP non-local traffic (INPUT)
- ACCEPT mDNS (zeroconf/bonjour/avahi 18.104.22.168 for IPv4 and
ff02::fb for IPv6) for service discovery (INPUT)
- ACCEPT UPnP (22.214.171.124 for IPv4 and ff02::f for IPv6)
for service discovery (INPUT)
If you want to remove mDNS and UPnP or others see below. Be cautious. Removing
some of the icmp packets and DHCP packets my break your
Universal Plug and Play (UPnP) is a
set of networking protocols that permits networked devices,
such as personal computers, printers, Internet gateways,
Wi-Fi access points and mobile devices to seamlessly
discover each other's presence on the network and establish
functional network services for data sharing, ...
In computer networking, the multicast DNS (mDNS)
protocol resolves hostnames to IP addresses within small
networks that do not include a local name server. It is a
zero-configuration service, using essentially the same
programming interfaces, packet formats and operating
semantics as the unicast Domain Name System (DNS). Although
Stuart Cheshire designed mDNS as a stand-alone protocol, it
can work in concert with standard DNS servers.
iptables and ip6tables are used to set up, maintain,
and inspect the tables of IPv4 and IPv6 packet filter rules in
the Linux kernel. Several different tables may be
defined. Each table contains a number of built-in chains
and may also contain user-defined chains.
Each chain is a list of rules which can match a set of
packets. Each rule specifies what to do with a packet that
matches. This is called a `target', which may be a jump to
a user-defined chain in the same table.
ip(6)tables does the same thing as ufw. It has likely has
more capability and is more obtuse. It is also not
persistent over a reboot. Showing examples for
ip6tables. iptables would be the same in this case.
- ip6tables -L | egrep 'Chain|ssh' | egrep --color -B 1
Chain INPUT (policy DROP)
Chain ufw6-track-forward (1 references)
Chain ufw6-user-input (1 references)
- ip6tables -L | egrep 'Chain|5900' | egrep --color -B 1
Chain ufw6-user-input (1 references)
Generating public/private rsa key pair.
Enter file in which to save the key
Created directory '/home/pi/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in
Your public key has been saved in
The key fingerprint is:
The key's randomart image is:
|EB+oo+.. . o.o= .|
| +.. . o. +.= |
| o o .o o o .|
| + .S. + . |
| o . o
| . +
. . |
- Do NOT forget the pass phrase. It can not be
- Normal practice is to generate the public private
key pair on the machine you are going to connect
from. Then send the public key to the machine you are
going to connect to and put it in the file
~you/.ssh/authorized_keys. Likely in this case your
Raspberry Pi(s). ssh-copy-id will also create
the .ssh directory and the authorized_keys file if required.
- The utility Linux utility ssh-copy-id will copy do
this for you.
- ssh-copy-id -i <identity file> firstname.lastname@example.org
- If you are not able to move the public key with
ssh-copy-id you need to:
- Put id_rsa (the private key) into
the .ssh directory of the machine(s) you will be
- Put id_rsa.pub (the public key)
into the ~<userid>/.ssh/authorized_keys file. This
file can contain multiple public keys. If the .ssh
directory does not exist:
- create it with mkdir .ssh
from the user home directory.
- chmod 700 .ssh to set the
permissions to rwx for only the owner
- Ensure that both key files are
owned by the same owner as the .ssh directory they are
- Ensure that both files are rw by
only the owner
- Edit the /etc/ssh/sshd_config file to:
- disable root login
- add the following after #PermitRootLogin
- Add the following before #Port 22 Any user
other than root or pi
- AllowUsers <userid1>
- When you are sure you can log in with your PPK then.
- Add the following after #PasswordAuthentication
- PasswordAuthentication no
- From the man page:
Gufw is an easy to use Ubuntu / Linux firewall, powered by ufw.
Gufw is an easy, intuitive, way to
manage your Ubuntu firewall. It supports common tasks such as
allowing or blocking pre-configured, common p2p, or individual
ports port(s), and many others! Gufw is powered by ufw.
Introduction iptables is already a very powerful tool by itself,
but it's syntax can get awkward at times and
hard to figure out, so Ubuntu developers decided to make ufw
("The reason ufw was developed is that we wanted to create a
server-level firewalling utility that was a little bit more for
`human beings`"), which was to be simpler. Now, on the graphical
side of things, Firestarer already existed. But why not make an
even easier to use GUI for desktop `human beings`, powered by
ufw? This is where Gufw comes in.
Fail2Ban consists of a client, server and configuration files to
limit brute force authentication attempts. The
server program fail2ban-server is
responsible for monitoring log files and issuing ban/unban
commands. It gets configured through a simple
protocol by fail2ban-client, which can also read configuration
files and issue corresponding configuration commands to
the server. Thanks to https://pimylifeup.com/raspberry-pi-fail2ban/
for much of the following instructions.
- apt update
- apt upgrade
- apt install
- Find [sshd] without # and Add the following after backend
- enabled =
- filter = sshd
- banaction =
- bantime = -1
- maxretry = 3
- Apache or other
- enabled =
- filter =
- Start/restart fail2ban
- Should you ban yourself: https://serverfault.com/questions/285256/how-to-unban-an-ip-properly-with-fail2ban.
E.G. I experimented:
all -- 8gig.lan anywhere reject-with
Status for the
| |- Currently failed: 0
| |- Total failed: 28
| `- File list: /var/log/auth.log
|- Currently banned: 1
|- Total banned: 8
`- Banned IP list: 2001:db8:e8cd:0:ba97:5aff:fe23:2781
set sshd unbanip 2001:db8:e8cd:0:ba97:5aff:fe23:2781
Shut down unneeded services
- lsof -i4 -i6
- avahi-dae? You may not need
"The avahi-daemon Linux service runs on client machines to
perform network-based Zeroconf service discovery. Avahi is
an implementation of the DNS Service Discovery and Multicast
DNS specifications for Zeroconf Networking. User
applications receive notice of discovered network services
and resources using the Linux D-Bus message passing. The
daemon coordinates application efforts in caching replies,
helping minimize network traffic." https://www.thegeekdiary.com/linux-os-service-avahi-daemon/
Computers use this service to discover printers (mostly)
and other things such as file servers. It should be pointed
out that mDNS and Avahi are limited to the "broadcast
domain" and will not cross routers. Therefore, I think the
risk is low in leaving this enabled, especially
if you have printers on the same "wire".
- To remove a running service:
systemctl --now disable
- systemctl mask
- Don't run services as root
How To Change The ufw
Defaults for mDNS and uPnP
Change directory to the /etc/ufw.
Run a 'ufw reset' command to start from a known state.
Make a copy of before.rules and before6.rules and give them
a .dist extension for distribution).
This is for safe keeping of the original distribution rules as we
# cp before.rules before.rules.dist
# cp before6.rules before6.rules.dist
Edit those two before(6).rules
files and change the ACCEPT command to DROP
for the rules designating mDNS and uPNP:
Running a diff command against these two rule sets should produce.
root@meet:/etc/ufw# diff before.rules.dist before.rules
< -A ufw-before-input -p udp -d 126.96.36.199 --dport 5353 -j ACCEPT
> -A ufw-before-input -p udp -d 188.8.131.52 --dport 5353 -j DROP
< -A ufw-before-input -p udp -d 184.108.40.206 --dport 1900 -j ACCEPT
> -A ufw-before-input -p udp -d 220.127.116.11 --dport 1900 -j DROP
root@meet:/etc/ufw# diff before6.rules.dist before6.rules
< -A ufw6-before-input -p udp -d ff02::fb --dport 5353 -j ACCEPT
> -A ufw6-before-input -p udp -d ff02::fb --dport 5353 -j DROP
< -A ufw6-before-input -p udp -d ff02::f --dport 1900 -j ACCEPT
> -A ufw6-before-input -p udp -d ff02::f --dport 1900 -j DROP
This shows the changes you made to the before(6).rules files
Now make a copy of your altered files like so
to preserve your changes as a ufw reset will destroy the changes:
# cp before.rules before.rules.nomdns_or_upnp
# cp before6.rules before6.rules.nomdns_or_upnp
You can use these files in the future to save yourself
editing time if you run 'ufw reset' again.
just need to copy the .nomds_or_pnp files to .rules.
To cause these new rule sets to be implemented do a ufw disable
and ufw enable.