The Linux Hardening Guide

A practical, magazine-style guide to securing your Linux systems.

In This Issue

User Account Security

Enforce Strong Passwords: Edit `/etc/pam.d/common-password` and ensure the `pam_pwquality.so` module is used. A good starting point is: `password requisite pam_pwquality.so retry=3 minlen=14 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1`.

Password Aging: Use `chage` to set password expiration policies. For example, `chage --maxdays 90 --mindays 7 --warndays 14 username`.

Limit Root Access: Disable direct root login via SSH by editing `/etc/ssh/sshd_config` and setting `PermitRootLogin no`. Use `sudo` for administrative tasks.

Lock Unused Accounts: If an account is not needed, lock it: `passwd -l username`. Also check for accounts with empty passwords: `awk -F: '($2 == "") {print $1}' /etc/shadow`.

Principle of Least Privilege: Grant users only the permissions they absolutely need. Use `sudo` to give granular permissions instead of adding users to the `wheel` or `sudo` group. Edit `sudoers` with `visudo` and define specific commands users can run. For example: `jdoe ALL=(ALL) /usr/bin/apt-get update`.

"The most secure user account is the one that doesn't exist. The second most secure is the one with the fewest privileges."

"UFW - Uncomplicated Firewall. Because your firewall shouldn't be harder to configure than your kernel."

Filesystem Security

Separate Partitions: Use separate partitions for `/`, `/home`, `/tmp`, `/var`, and `/usr`. This prevents one partition from filling up and crashing the system, and allows for more granular mount options.

Secure `/tmp`: Mount `/tmp` with `noexec`, `nosuid`, and `nodev` options in `/etc/fstab`: `tmpfs /tmp tmpfs defaults,rw,nosuid,nodev,noexec,relatime 0 0`.

File Permissions: Regularly check for world-writable files: `find / -xdev -type f -perm -0002 -print`. Ensure critical files like `/etc/shadow` and `/etc/gshadow` have permissions of 0000.

Disable USB Storage: If not needed, prevent USB storage devices from being used: `echo "install usb-storage /bin/true" >> /etc/modprobe.d/disable-usb-storage.conf`.

File Integrity Monitoring: Use a tool like AIDE (Advanced Intrusion Detection Environment). AIDE creates a database of file attributes. After initializing (`aideinit`), you can run `aide --check` to see what files have changed, helping you detect unauthorized modifications.

"Fail2Ban: Tired of brute-force attacks? Let our automated banning system handle them. Set it and forget it."

Network Security

Firewall: Enable and configure a firewall. `ufw` is a user-friendly option. A basic setup: `ufw default deny incoming`, `ufw default allow outgoing`, `ufw allow ssh`, `ufw allow http`, `ufw allow https`, `ufw enable`.

Secure SSH: In `/etc/ssh/sshd_config`, set `Port` to a non-standard port, `Protocol 2`, `MaxAuthTries 3`, and `AllowUsers` to a whitelist of users.

Disable Unused Network Services: Use `ss -tuln` to list listening services. If a service is not needed, disable it. For example, `systemctl stop postfix`, `systemctl disable postfix`.

Disable IPv6 (if not used): If your network doesn't use IPv6, disable it to reduce the attack surface. Add the following to `/etc/sysctl.conf`: `net.ipv6.conf.all.disable_ipv6 = 1`, `net.ipv6.conf.default.disable_ipv6 = 1`, `net.ipv6.conf.lo.disable_ipv6 = 1`. Apply with `sysctl -p`.

"Suricata: The next generation of intrusion detection. Multi-threaded, powerful, and ready for your network."

Service Hardening

Apache/Nginx: Hide version numbers. For Apache, `ServerTokens Prod` and `ServerSignature Off`. For Nginx, `server_tokens off;`.

Disable Unused Modules: If a web server module is not needed, disable it. For example, `a2dismod userdir` for Apache.

HIDS & Malware Detection

Rootkit Scanners: Regularly scan for rootkits and malware. `rkhunter` and `chkrootkit` are two excellent tools. Install them (`apt-get install rkhunter chkrootkit`) and run them periodically via cron jobs.

After running `rkhunter --check`, update its file properties database with `rkhunter --propupd`.

Host-based Intrusion Detection (HIDS): Tools like AIDE (mentioned in Filesystem Security) are crucial. Another option is OSSEC, which provides real-time monitoring and correlation of events.

Advanced Kernel Hardening: A Custom Sysctl

The `/etc/sysctl.conf` file allows you to tune the kernel's behavior on a running system. The following is a comprehensive set of hardening options. This configuration aims to secure the networking stack, prevent common attacks, and improve memory protection. Review each setting and understand its impact before deploying on a production system.

# IP Spoofing protection net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 # Ignore ICMP broadcast requests net.ipv4.icmp_echo_ignore_broadcasts = 1 # Disable source-routed packets net.ipv4.conf.all.accept_source_route = 0 net.ipv6.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 net.ipv6.conf.default.accept_source_route = 0 # Ignore send redirects net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.default.send_redirects = 0 # Block SYN attacks net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 2048 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_syn_retries = 5 # Log Martians net.ipv4.conf.all.log_martians = 1 net.ipv4.icmp_ignore_bogus_error_responses = 1 # Ignore ICMP redirects net.ipv4.conf.all.accept_redirects = 0 net.ipv6.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv6.conf.default.accept_redirects = 0 net.ipv4.conf.all.secure_redirects = 0 net.ipv4.conf.default.secure_redirects = 0 # Disable IPv6 if not needed net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1 # Hide kernel pointers kernel.kptr_restrict = 1 # Enable ASLR kernel.randomize_va_space = 2

DIY Intrusion Detection with Snort

Setting up a Network Intrusion Detection System (NIDS) like Snort gives you real-time traffic analysis and packet logging. Here’s a step-by-step guide to get a basic Snort instance running.

Step 1: Installation

Install Snort from your distribution's package manager.

sudo apt-get install snort -y # For Debian/Ubuntu sudo yum install snort # For CentOS/RHEL

Step 2: Configure Network and Rules

Edit the main configuration file, `/etc/snort/snort.conf`. The most critical variable to set is `HOME_NET`. It should be the IP address or CIDR range of your local network.

# Find this line in snort.conf ipvar HOME_NET any # Change it to your network (e.g., a single machine or a /24 block) ipvar HOME_NET 192.168.1.0/24

You also need to tell Snort where your rules are. The default community rules are a good start.

# Ensure this line is present and points to your rules directory var RULE_PATH /etc/snort/rules

Step 3: Test Configuration

Before running Snort, test your configuration file for syntax errors.

sudo snort -T -c /etc/snort/snort.conf

If everything is correct, you will see a success message.

Step 4: Run Snort in NIDS Mode

Run Snort and tell it to listen on your primary network interface (e.g., `eth0` or `enp0s3`). The `-A console` flag prints alerts to the screen, and `-l` specifies the log directory.

sudo snort -A console -i eth0 -c /etc/snort/snort.conf -l /var/log/snort

Step 5: Run as a Service (Systemd)

To have Snort run automatically, create a systemd service file at `/etc/systemd/system/snort.service`.

[Unit] Description=Snort NIDS After=network.target [Service] Type=simple ExecStart=/usr/sbin/snort -A full -c /etc/snort/snort.conf -i eth0 -l /var/log/snort -K ascii ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure [Install] WantedBy=multi-user.target

Then, enable and start the service.

sudo systemctl enable snort sudo systemctl start snort

DIY SELinux Hardening

SELinux adds Mandatory Access Control (MAC) to the kernel, providing a robust, policy-based security layer. It can be intimidating, but mastering a few commands makes it manageable.

Step 1: Check SELinux Status

First, see if SELinux is running and in what mode.

sestatus

You want to see `SELinux status: enabled` and `Current mode: enforcing`.

Step 2: Set Enforcing Mode

If the current mode is `permissive` or `disabled`, change it. Permissive mode logs denials but doesn't block them, making it a good testing step before full enforcement.

sudo setenforce 1

To make this permanent, edit `/etc/selinux/config` and set `SELINUX=enforcing`.

Step 3: Understand Contexts

Every file, process, and user has an SELinux context. Use `ls -Z` to see them. Processes can only access objects if there is an explicit policy rule allowing it based on their contexts.

ls -Z /var/www/html/ # Output shows user, role, type, and level

Step 4: Manage Booleans

Booleans are on/off switches for specific SELinux rules. They let you easily customize policy without writing custom modules. For example, to allow a web server to connect to the network:

# List all HTTP-related booleans getsebool -a | grep httpd # Allow httpd to make network connections (and make it permanent with -P) sudo setsebool -P httpd_can_network_connect on

Step 5: Troubleshoot with Audit Logs

When SELinux blocks something, it logs a denial to `/var/log/audit/audit.log`. The `ausearch` tool helps you find them.

# Search for recent AVC (SELinux) denials sudo ausearch -m AVC -ts recent

The `audit2allow` tool can even suggest policy changes based on these denials. This is the standard workflow for fixing SELinux issues.

# Find denials and pipe them to audit2allow sudo ausearch -m AVC -ts recent | audit2allow -a # To create a local policy module to allow a specific action: sudo ausearch -m AVC -ts recent | audit2allow -M my_local_policy sudo semodule -i my_local_policy.pp

"Permissions-based security is guessing. SELinux is knowing."

50 Command Lines to Harden Your Linux Server

User & Authentication

chage --maxdays 90 [user]: Set password expiration.

passwd -l [user]: Lock a user account.

userdel -r [user]: Delete a user and their home directory.

awk -F: '($2 == "")' /etc/shadow: Find accounts with empty passwords.

visudo: Safely edit the sudoers file.

lastlog: Review last login times for all users.

usermod -aG [group] [user]: Add a user to a group.

Filesystem & Permissions

find / -type f -perm -o+w: Find world-writable files.

find / -type d -perm -o+w: Find world-writable directories.

chmod 600 /etc/shadow: Secure shadow file permissions.

chmod 750 /etc/sudoers: Secure sudoers file permissions.

mount | grep /tmp: Check /tmp mount options.

aideinit: Initialize the AIDE database.

aide --check: Check for file integrity changes.

ls -lZ: View file SELinux contexts.

chown root:root /etc/crontab: Set ownership of main crontab.

Networking & Firewall

ufw enable: Enable the Uncomplicated Firewall.

ufw default deny incoming: Set default deny policy.

ufw allow ssh: Allow SSH traffic.

ufw status verbose: Check firewall status.

ss -tuln: List all listening ports.

ss -tan: Show all TCP connections.

sysctl -p: Apply kernel parameters from sysctl.conf.

netstat -r: Display the kernel routing table.

Services & System

systemctl list-units --type=service: List all active services.

systemctl disable [service]: Disable a service from starting on boot.

systemd-analyze security: Analyze security of running units.

journalctl -p err: View system logs for errors.

apt-get update && apt-get upgrade: Update system packages (Debian).

yum update -y: Update system packages (RHEL).

reboot: Reboot the system (e.g., to apply kernel updates).

Auditing & Scanning

rkhunter --check: Scan for rootkits.

chkrootkit: Check for rootkit signatures.

lynis audit system: Perform a full system security scan.

sestatus: Check SELinux status.

setenforce 1: Put SELinux in enforcing mode.

getsebool -a: List all SELinux booleans.

setsebool -P [boolean] on: Persistently enable an SELinux boolean.

ausearch -m AVC -ts recent: Find recent SELinux denials.

auditctl -l: List all auditd rules.

SSH Hardening

sshd -t: Test the SSH daemon configuration.

systemctl restart sshd: Restart the SSH service.

echo "PermitRootLogin no" >> /etc/ssh/sshd_config: Disable root login.

echo "Protocol 2" >> /etc/ssh/sshd_config: Use SSH protocol 2 only.

echo "PasswordAuthentication no" >> /etc/ssh/sshd_config: Disable password authentication (use keys).

echo "MaxAuthTries 3" >> /etc/ssh/sshd_config: Limit authentication attempts.

echo "AllowUsers [user1] [user2]" >> /etc/ssh/sshd_config: Whitelist allowed users.

ssh-keygen -t rsa -b 4096: Generate a strong SSH key pair.

fail2ban-client status sshd: Check Fail2Ban status for the SSH jail.

Hardening Checklist