Portal | Level: L2: Operations | Topics: Linux Hardening, Compliance & Audit, Audit Logging | Domain: Security
SELinux & Linux Hardening - Primer¶
Why This Matters¶
A default Linux installation is not secure. It is convenient. Every service runs with more permissions than it needs, every port is a potential entry point, and every misconfigured file permission is a privilege escalation waiting to happen. Hardening is the process of reducing the attack surface to only what the system actually needs to do its job.
Who made it: SELinux (Security-Enhanced Linux) was originally developed by the United States National Security Agency (NSA) and released as open source in 2000. It implements Mandatory Access Control (MAC) based on the Flask security architecture from the University of Utah. The NSA contributed it to the mainline Linux kernel in 2003 (kernel 2.6). Red Hat adopted it as the default security module for RHEL, Fedora, and CentOS.
SELinux is the most powerful — and most misunderstood — security tool in the Linux kernel. Most engineers disable it on day one because it "breaks things." What it actually does is prevent unauthorized access patterns, and the things it "breaks" are things that should not have been allowed in the first place. Understanding SELinux is the difference between a system that survives a compromised service and one that gives an attacker full root access.
Core Concepts¶
1. SELinux Modes¶
Enforcing → Policies are enforced. Violations are blocked AND logged.
Permissive → Policies are NOT enforced. Violations are logged only.
Disabled → SELinux is completely off. No logging, no enforcement.
Check current mode:
$ getenforce
Enforcing
$ sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
# Temporarily switch to permissive (survives until reboot)
setenforce 0
# Switch back to enforcing
setenforce 1
# Persistent change: edit /etc/selinux/config
# SELINUX=enforcing
Warning: Going from Disabled to Enforcing requires a full filesystem relabel. This takes time and can brick a system if done wrong.
2. SELinux Contexts and Labels¶
Every file, process, port, and user has an SELinux context:
user:role:type:level
Example file context:
$ ls -Z /var/www/html/index.html
system_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html
Example process context:
$ ps -eZ | grep httpd
system_u:system_r:httpd_t:s0 1234 ? 00:00:01 httpd
Remember: SELinux context format mnemonic: URTL — User, Role, Type, Level. In targeted policy (the default on RHEL/CentOS), only the Type matters for enforcement. The type label on a process determines what files, ports, and resources it can access. Think of the type as a "security badge" —
httpd_tcan only enter rooms labeledhttpd_sys_content_t.
The type field is what matters most in targeted policy:
| Component | Description | Example |
|---|---|---|
httpd_t |
Apache process type | Can read httpd_sys_content_t files |
httpd_sys_content_t |
Web content type | Readable by httpd_t |
httpd_sys_rw_content_t |
Writable web content | Read/write by httpd_t |
var_log_t |
Log files type | Writable by logging processes |
sshd_t |
SSH daemon type | Can access SSH keys, PAM |
3. SELinux Troubleshooting¶
# Check for recent denials
ausearch -m avc -ts recent
# Human-readable denial analysis
sealert -a /var/log/audit/audit.log
# Generate a policy module to allow a specific denial
ausearch -m avc -ts recent | audit2allow -M mypolicy
# Review the generated policy before applying
cat mypolicy.te
# Apply the policy module
semodule -i mypolicy.pp
# Check what booleans are available for a service
getsebool -a | grep httpd
# Enable a boolean (e.g., allow httpd to connect to network)
setsebool -P httpd_can_network_connect on
Common SELinux Denials and Fixes¶
Problem: Apache can't read files in /var/www/html/
→ Files have wrong context
Fix: restorecon -Rv /var/www/html/
Problem: Nginx can't bind to port 8080
→ Port not labeled for http
Fix: semanage port -a -t http_port_t -p tcp 8080
Problem: App can't write to /opt/myapp/data/
→ Directory has default_t context
Fix: semanage fcontext -a -t httpd_sys_rw_content_t "/opt/myapp/data(/.*)?"
restorecon -Rv /opt/myapp/data/
Problem: Service can't connect to database on network
→ Boolean not set
Fix: setsebool -P httpd_can_network_connect_db on
4. CIS Benchmarks¶
The Center for Internet Security publishes hardening benchmarks for every major OS. These are the gold standard for compliance auditing.
CIS Benchmark Categories:
1. Filesystem Configuration (partitions, mount options, permissions)
2. Software Updates (package manager config, auto-updates)
3. Filesystem Integrity (AIDE, file integrity monitoring)
4. Boot Settings (GRUB password, single-user auth)
5. Process Hardening (core dumps, ASLR, ExecShield)
6. Mandatory Access Control (SELinux/AppArmor)
7. Command Line Warning Banners
8. Network Configuration (IP forwarding, ICMP, TCP wrappers)
9. Firewall (iptables/nftables/firewalld)
10. Logging and Auditing (rsyslog, auditd)
11. PAM and Password Policies
12. SSH Configuration
13. User Accounts and Environment
5. sysctl Hardening¶
# /etc/sysctl.d/99-hardening.conf
# Disable IP forwarding (unless this is a router)
net.ipv4.ip_forward = 0
# Disable source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Enable SYN flood protection
net.ipv4.tcp_syncookies = 1
# Disable ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# Log suspicious packets
net.ipv4.conf.all.log_martians = 1
# Disable IPv6 if not needed
net.ipv6.conf.all.disable_ipv6 = 1
# Restrict kernel pointer exposure
kernel.kptr_restrict = 2
# Restrict dmesg access
kernel.dmesg_restrict = 1
# Enable ASLR (Address Space Layout Randomization)
kernel.randomize_va_space = 2
# Restrict ptrace (prevent process tracing)
kernel.yama.ptrace_scope = 1
# Apply immediately
sysctl -p /etc/sysctl.d/99-hardening.conf
6. PAM Hardening¶
# /etc/pam.d/system-auth (or common-password on Debian)
# Enforce password complexity
password requisite pam_pwquality.so retry=3 \
minlen=14 dcredit=-1 ucredit=-1 ocredit=-1 lcredit=-1
# Lock accounts after 5 failed attempts
auth required pam_faillock.so preauth silent audit deny=5 unlock_time=900
auth [default=die] pam_faillock.so authfail audit deny=5 unlock_time=900
# Restrict su to wheel group
# /etc/pam.d/su
auth required pam_wheel.so use_uid
7. SSH Hardening¶
# /etc/ssh/sshd_config hardening
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
X11Forwarding no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers deploy ansible
Protocol 2
LogLevel VERBOSE
# Restrict ciphers and MACs
Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms curve25519-sha256,diffie-hellman-group16-sha512
8. File Permission Hardening¶
# Find world-writable files (should be minimal)
find / -type f -perm -0002 -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null
# Find SUID/SGID binaries (audit these)
find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -la {} \; 2>/dev/null
# Remove unnecessary SUID bits
chmod u-s /usr/bin/unnecessary-suid-binary
# Restrict home directory permissions
chmod 750 /home/*
# Secure cron directories
chmod 700 /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.weekly /etc/cron.monthly
chown root:root /etc/crontab
chmod 600 /etc/crontab
# Restrict access to su
chown root:wheel /usr/bin/su
chmod 4750 /usr/bin/su
9. Auditd Rules¶
# /etc/audit/rules.d/hardening.rules
# Monitor file access to sensitive files
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/sudoers -p wa -k actions
-w /etc/ssh/sshd_config -p wa -k sshd
# Monitor login events
-w /var/log/lastlog -p wa -k logins
-w /var/log/faillog -p wa -k logins
# Monitor privilege escalation
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=4294967295 -k privileged
# Monitor kernel module loading
-w /sbin/insmod -p x -k modules
-w /sbin/modprobe -p x -k modules
# Make audit config immutable (requires reboot to change)
-e 2
Common Pitfalls¶
Debug clue: When troubleshooting SELinux denials, always check
/var/log/audit/audit.logfortype=AVCmessages first. Thesealert -acommand translates raw AVC messages into human-readable explanations with suggested fixes. Ifaudit.logis empty but SELinux is blocking things, the denial might be indontauditrules — temporarily runsemodule -DBto disable dontaudit rules and reveal hidden denials.Analogy: Think of SELinux like airport security. Without SELinux (DAC only), anyone with a boarding pass (file permissions) can go anywhere in the airport. With SELinux (MAC), your boarding pass also has a specific gate number and zone — you can only access the areas matching your ticket type, regardless of what doors you can physically open.
- Disabling SELinux instead of fixing the policy — The single most common Linux hardening failure. Learn to read AVC denials and write targeted policy modules.
- Hardening a server but leaving default SSH keys — You locked every door but left the master key on the welcome mat.
- Not testing hardening changes in staging — A sysctl change that disables IP forwarding will break a server that is supposed to be a router.
- CIS compliance without understanding — Blindly applying every CIS recommendation without understanding your workload. Some benchmarks conflict with application requirements.
- Forgetting to persist changes —
setenforce 1does not survive reboot.sysctl -wdoes not survive reboot. Always use the persistent config files. - Auditing everything — An auditd configuration that logs every syscall will fill your disk and degrade performance. Be selective.
- Hardened AMIs that drift — You build a hardened AMI but never re-harden running instances. Configuration drift undoes your hardening within weeks.
Wiki Navigation¶
Prerequisites¶
- Linux Ops (Topic Pack, L0)
- Security Basics (Ops-Focused) (Topic Pack, L1)
Next Steps¶
- Compliance & Audit Automation (Topic Pack, L2)
- SELinux & AppArmor (Topic Pack, L2)
Related Content¶
- Compliance & Audit Automation (Topic Pack, L2) — Audit Logging, Compliance & Audit, Linux Hardening
- Infrastructure Forensics (Topic Pack, L2) — Audit Logging, Linux Hardening
- Audit Logging (Topic Pack, L1) — Audit Logging
- Audit Logging Flashcards (CLI) (flashcard_deck, L1) — Audit Logging
- Compliance Flashcards (CLI) (flashcard_deck, L1) — Compliance & Audit
- Deep Dive: Systemd Service Design Debugging and Hardening (deep_dive, L2) — Linux Hardening
- LDAP & Identity Management (Topic Pack, L2) — Linux Hardening
- Linux Security Flashcards (CLI) (flashcard_deck, L1) — Linux Hardening
- Linux Users & Permissions (Topic Pack, L1) — Linux Hardening
- Runbook: Unauthorized Access Investigation (Runbook, L2) — Audit Logging
Pages that link here¶
- Anti-Primer: Linux Hardening
- Audit Logging
- Certification Prep: CKAD — Certified Kubernetes Application Developer
- Certification Prep: CKS — Certified Kubernetes Security Specialist
- Compliance & Audit Automation
- Incident Replay: SELinux Denying Service
- Incident Replay: iptables Blocking Unexpected Traffic
- Infrastructure Forensics
- LDAP & Identity Management
- Linux Users and Permissions
- Master Curriculum: 40 Weeks
- Production Readiness Review: Answer Key
- Production Readiness Review: Study Plans
- Runbook: Unauthorized Access Investigation
- SELinux & AppArmor