Host Hardening

 

Overview

When maintaining systems, hardening refers to configuring it in such a way that it is as unlikely to contain vulnerabilities as possible. This term encompasses both technical details of setting up specific pieces of software and also general strategies for ensuring systems are as secure as possible.

General principles include:

Of course one goal in hardening systems is to avoid being victim of a cyber attack. Depending on your organization, it may be mandated by law that you provide certain security configurations. For instance, the following all have such rules:


 

Securing SSH

SSH is configured through the /etc/ssh/sshd_config. After making changes to the file, the service must be reloaded or restarted. Reloading is preferable since it won't kick off people (including perhaps you) who are connected.

The current configuration can be printed out with the following command:

sudo sshd -T

The following configurations are generally recommended for SSH


PermitRootLogin no
PermitEmptyPasswords no 
PasswordAuthentication no # if using keys

The software fail2ban is used to further secure SSH. It monitors SSH login attempts and blocks users who have submitted an incorrect password too many times. The number of incorrect passwords and the amount of time they are blocked is configurable.

It's configured by copying the /etc/fail2ban/jail.conf file to /etc/fail2ban/jail.local, and then editing the local configuration file. The file includes configurations for not just SSH, but other services as well. Make sure the service for fail2ban is enabled and running.

You can check what IPs have been banned with the command:

sudo fail2ban-client status sshd

 

Host Firewalls

Firewalls are divided into two categories: network and host. Network firewalls are installed as part of a local network (either built into routers or as dedicated devices) and protect all hosts on the network.

A host firewall is installed a particular host and filters packets just from that hosts incoming network traffic. This can provide defense in depth on that particular host.

There are multiple host firewall systems available for Linux. iptables is the traditional, low-level packet filtering framework which works with the kernel's network stack. It is detailed and relatively difficult to set up.

Two simpler front-ends for iptables have been developed:

UFW can be installed with the ufw package and then managed like any other service with systemctl. However, even when it's running ufw needs to be turned off and on:

$ sudo systemctl status ufw
● ufw.service - Uncomplicated firewall
     Loaded: loaded (/usr/lib/systemd/system/ufw.service; enabled; preset: enabled)
     Active: active (exited) since Mon 2026-04-20 10:33:21 EDT; 1s ago
 Invocation: 102818059e194412909cd484ae90c4c5
       Docs: man:ufw(8)
    Process: 606278 ExecStart=/usr/lib/ufw/ufw-init start quiet (code=exited, status=0/SUCCESS)
   Main PID: 606278 (code=exited, status=0/SUCCESS)
   Mem peak: 2M
        CPU: 11ms

$ sudo ufw status
Status: inactive

$ sudo ufw enable

$ sudo ufw status
Status: active

By default UFW allows all outgoing connections and blocks all incoming connections. We can explicitly allow services through allowing application profiles. Available ones can be seen with the ufw app list command, and turned on using a command such as:

sudo ufw allow "OpenSSH"

This will allow connections on port 22 for our SSH server, but keep blocking other incoming connections. You could also do sudo ufw allow 22 to allow ports by name instead of application name.

We can also block specific IP addresses or blocks of addresses with ufw:

$ sudo ufw deny from 34.6.217.81

$ sudoe ufw deny from 34.6.217.0/24

Installing a host firewall which only allows traffic on ports you want to support provides good defense in depth.


 

Passwords

Passwords should be carefully managed, especially for users with sudo privileges. Some general principles are:

Password policies can be enforced on Linux with the chage command. We can get info on passwords by passing the -l flag:

$ sudo chage -l ifinlay
Last password change                                    : Feb 17, 2026
Password expires                                        : never
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires       : 7

It also allows all of these fields to be modified by passing different flags, on a per-user basis. This can be done to enforce password rules on users, ensuring their passwords are changed regularly. For example, to make sure the user susan4 changes her password every 90 days, we could use the following:

$ sudo chage -M 90 susan4

Minimum password length is configured differently, through the PAM (Pluggable Authentication Modules) system. One must first install the password quality module in the libpam-pwquality package. Then, we can configure this in the /etc/security/pwquality.conf file. There are multiple settings available, but a minimum length can be set with:


minlen = 10

 

AIDE

AIDE is the Advanced Intrusion Detection Environment, and is a host-based intrusion detection system. It essentially scans system files and creates hashes of their contents. It treats this as the baseline of the system and then we can periodically re-scan system files. If there are any deviations from the baseline, we'll know.

The goal is to be notified if system files have been changed without our knowledge which would indicate that the machine has been compromised in some way.

AIDE can be configured with the /etc/aide/aide.conf file. This file pulls in several other configurations. One helpful change to make is to exclude the /home directory from scans. We can do that with the line !/home. Then, we can build the initial baseline of the system with the following command:

$ sudo aide --config /etc/aide/aide.conf --init

This produces a database of hashes for all of our system files. We can tell AIDE to use this going forward for checking by getting rid of the ".new" at the end of the file name:

$ sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

We can then subsequently perform a check on the sytem with the --check flag:

$ sudo aide --check --config /etc/aide/aide.conf

It will tell us if everything matched up ok, with output like this:

Start timestamp: 2026-04-20 12:33:47 -0400 (AIDE 0.19.1)
AIDE found NO differences between database and filesystem. Looks okay!!
Ignored e2fs attributes: EINV

Number of entries:      3163

Or it will give us output like the following, indicating an error:

Start timestamp: 2026-04-20 12:43:45 -0400 (AIDE 0.19.1)
AIDE found differences between database and filesystem!!
Ignored e2fs attributes: EINV

Summary:
  Total number of entries:      3163
  Added entries:                0
  Removed entries:              0
  Changed entries:              2

---------------------------------------------------
Changed entries:
---------------------------------------------------

d =.... mc.. .. .  : /etc/ssh
f <.... mci.H.. .  : /etc/ssh/sshd_config

If we make a legitimate change to the system (such as updating packages), we can update the database using:

$ sudo aide --update --config /etc/aide/aide.conf
$ sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

For best results the check should be run regularly, which is best accomplished by putting it in a cron job.


 

Vulnerabilities

When software vulnerabilities are discovered, they are published so the problem can be mitigated and eventually fixed. The primary authority on vulnerabilities is the Common Vulnerabilities and Exposures (CVE) system. Vulnerabilities are published online at https://cve.mitre.org/, which is run by National Security FFRDC and MITRE.

Vulnerabilities are given a distinct identifier, to make talking about them easier, and also an impact score. based on the Common Vulnerability Scoring System (CVSS). Each vulnerability listed must be:

  1. Independently Fixable
  2. Acknowledged by the vendor or documented
  3. Affecting a single code base (multiple CVEs can come from a single vulnerability)

There are many security-related mailing lists which send messages when vulnerabilities in systems of interest are found. For example, the debian-security-announce list sends messages when vulnerabilities in software packaged by Debian are found. Subscribing to such a mailing list is a good idea for critical systems.