This overview doesn’t aim to be comprehensive, but it gives a few ideas on the minimum required to secure any server accessible from the Internet. Many thanks to Tony from @EliteStakePool as he graciously reviewed and added more input. A physical firewall might be best, however it’s obviously not the same cost. I’ll focus on using mostly FOSS and a very basic network topology.
-
Use a stable production release of your favorite GNU/Linux distribution. With the latest or testing releases of packages come the latest bugs, regressions, and incompatibilities.
-
Always install security updates, use the latest microcode for your CPU, upgrade your BIOS.
-
Always use strong passphrases and encryption whenever possible.
-
Follow good practices and advices on hardening GNU/Linux OS, e.g.
-
Use a Host-based or Network-based Intrusion Prevention Systems or an Intrusion Detection System, depending on your needs, to be installed using the package manager of your distribution whenever possible (when not the case it’s sometimes possible to package an installation from sources, e.g. with
checkinstall
).- HIDS OSSEC https://www.ossec.net
- HIDS AIDE (Advanced Intrusion Detection Environment) https://aide.github.io
- NIDS Snort https://www.snort.org/
- NIDS Zeek https://zeek.org/
- NIDS Suricata https://www.suricata-ids.org/
-
Use
rkhunter
orchkrootkit
to check for potential rootkits. -
Harden Linux kernel in order to make it tougher to use 0-day exploits and/or rootkits, e.g. apply
grsecurity
patch set https://www.grsecurity.net/ on Linux kernel before compiling it. -
Use and configure properly your firewall, it doesn’t matter that you use
nft
,iptables
orufw
as long Netfilter is up and running. -
Avoid letting exploits be executed on world accessible partitions like
/tmp
or/dev/shm
by using flagsnoexec,nosuid,nodev
in/etc/fstab
. -
Avoid running services as
root
. -
Limit the programs with suid or sgid bit set, you may list them all with
$ sudo find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -l {} \;
-
Disable any unneeded open port/service or at least filter them using an adequate firewall rule. You have several options to list open ports with their associated service (some of these commands will also list services listening on
127.0.0.1
which is on thelo
interface i.e.loopback
):$ sudo netstat -latupen
$ sudo lsof -i
$ sudo ss -antlp
-
Use firewall rules to mitigate DoS attacks, port flooding by using
connlimit
rules, seeiptables-extensions(8)
for examples. -
It might also be useful to add a rule with target
LOG
before dropping packets. -
Monitor logged on users and activities with
w
orwho
, e.g.sudo watch -d -n5 w
. -
Use quotas to mitigate a few resources exhaustion attacks, e.g. fork bombs, see all with
ulimit -a
(bash builtin). -
A simple vulnerability scan can be conducted using
nmap
, it won’t be as precise or comprehensive as a commercial vulnerability scanner, though. For instance :-
$ sudo nmap --script vuln <target>
In this case, be aware that when usinglocalhost
as target, you’ll also scan for services listening on loopback interface but not if you use an external IP address.
-
-
For those using
systemd
services, their security may be checked withsystemd-analyze security
. It’s possible to harden everyUNSAFE
orEXPOSED
service without messing with the distribution service file by adding anoverride.conf
file in/etc/systemd/system/unit.service.d/
directory (unit
being the name of anysystemd
service). Directives (likeProtectHome
,ProtectSystem
,ProtectHostname
, etc.) are described insystemd.exec(5)
. The command line to do it issystemctl edit unit.service
. -
a simple overview of system health, load and security events might be easily be set up, using a terminal multiplexer like
tmux
(and eventuallytmuxp
session manager to reproduce atmux
session from a YAML/JSON file). Quick, light on resources and secure for remote access via SSH, a text-mode alternative or complement to Grafana. For example: dmesg, journalctl, iptables, tload, htop, systemctl, alone or with any combination of watch, tail, grep… -
If a remote access using SSH is needed then you might want to :
- use a different port than the well-known
22/tcp
- use port knocking
- disable banners
- define a number of max concurrent sessions
- add
fail2ban
in order to delay any attempt at brute-forcing or password guessing - disable root access (you will still be able to
sudo su
orsu
when connected) - preferably use authentication by certificate, instead of a passphrase
- when possible, restrict access to the only IP address you’ll be using to connect.
- use a different port than the well-known
-
Last but not least, instead of providing open services, it’s always possible to use SSH tunneling in order to encrypt traffic and control access to any local service, a few examples here.