Lab 20: Capstone — Hardened Container-Ready Server

Time: 40 minutes | Level: Advanced | Docker: docker run -it --rm --privileged --cgroupns=host ubuntu:22.04 bash

This capstone combines every advanced topic from Labs 16–19 into a complete server hardening workflow. You'll apply kernel hardening, audit rules, AppArmor profiles, cgroup resource limits, namespace isolation, LUKS encryption concepts, a hardened systemd service unit, and finally run a comprehensive security audit script that scores your system. This is the workflow a senior Linux/DevSecOps engineer follows before declaring a server production-ready.

⚠️ Run with: docker run -it --rm --privileged --cgroupns=host ubuntu:22.04 bash This is required for sysctl writes, cgroup management, and AppArmor tools.


Step 1: Kernel Hardening — sysctl Security Parameters

The kernel exposes hundreds of runtime tunable parameters via sysctl. Hardening starts here:

apt-get update -qq && apt-get install -y -qq procps iproute2 auditd apparmor apparmor-utils libpam-apparmor

echo '=== Current security-relevant sysctl values ==='
sysctl kernel.randomize_va_space
sysctl net.ipv4.tcp_syncookies
sysctl net.ipv4.conf.all.rp_filter

📸 Verified Output:

kernel.randomize_va_space = 2
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 0
# Apply comprehensive kernel hardening
cat > /etc/sysctl.d/99-hardening.conf << 'EOF'
# === KERNEL HARDENING ===
# Address space layout randomization (2=full randomization)
kernel.randomize_va_space = 2
# Prevent core dumps from SUID programs
fs.suid_dumpable = 0
# Restrict /proc/PID access to process owner
kernel.yama.ptrace_scope = 1
# Restrict kernel pointer exposure in /proc/kallsyms
kernel.kptr_restrict = 2
# Restrict kernel log access to root
kernel.dmesg_restrict = 1
# Disable magic SysRq key (useful in VMs, disable in prod)
kernel.sysrq = 0
# Restrict unprivileged user namespaces (set to 1 in prod if Docker not needed)
# kernel.unprivileged_userns_clone = 0  # Debian-specific

# === NETWORK HARDENING ===
# Enable TCP SYN cookies (SYN flood protection)
net.ipv4.tcp_syncookies = 1
# Enable reverse path filtering (prevent IP spoofing)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Disable IP forwarding (enable only if this is a router)
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0
# Disable ICMP redirects (prevent routing manipulation)
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# Ignore ICMP ping broadcasts
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Disable source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
# Log suspicious packets (martians)
net.ipv4.conf.all.log_martians = 1
# Protect against time-wait assassination
net.ipv4.tcp_rfc1337 = 1

# === MEMORY PROTECTION ===
# Minimum address for mmap (prevent NULL pointer dereference exploits)
vm.mmap_min_addr = 65536
EOF

# Apply (some may fail in container — that's expected)
sysctl -p /etc/sysctl.d/99-hardening.conf 2>/dev/null | head -20

echo ''
echo '=== Verify key settings applied ==='
sysctl kernel.randomize_va_space
sysctl net.ipv4.tcp_syncookies
sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.conf.all.accept_redirects

📸 Verified Output:

💡 Save and persist: sysctl -p /etc/sysctl.d/99-hardening.conf applies at runtime. Files in /etc/sysctl.d/ are loaded on boot by systemd-sysctl.service. Name files with a number prefix for ordering (99 = last, highest priority).


Step 2: Audit Rules — File Integrity Monitoring

The Linux Audit framework logs security-relevant events to /var/log/audit/audit.log:

📸 Verified Output:

💡 auditctl -e 2 locks audit rules (immutable) until reboot — even root can't change them. Use this in high-security environments. Leave as -e 1 (soft lock) if you need to update rules without rebooting.


Step 3: AppArmor — Mandatory Access Control Profile

AppArmor confines programs by defining what files, capabilities, and network operations they can access:

📸 Verified Output:

💡 Complain vs Enforce mode: Start with apparmor_parser -C (complain mode) — logs violations without blocking. Monitor /var/log/syslog for ALLOWED entries, then tighten the profile and switch to enforce with apparmor_parser -r. Use aa-logprof to auto-generate rules from complain-mode logs.


Step 4: Resource Limits via cgroups

📸 Verified Output:

💡 This mirrors exactly what systemd creates when you put MemoryMax=512M and CPUQuota=50% in a service unit — systemd just writes to these same cgroup files. Doing it manually gives you deep insight into what systemctl set-property does.


Step 5: Namespace Isolation Demo

📸 Verified Output:

💡 This is what happens inside a Kubernetes Pod's container: different pid:[], net:[], uts:[], mnt:[] namespace IDs than the host. Multiple containers in the same Pod share the same net:[] namespace ID — that's how they can talk to each other on localhost.


Step 6: LUKS Encryption Concepts and Workflow

📸 Verified Output:

💡 Key slots: LUKS supports 8 key slots (LUKS1) or 32 (LUKS2). Use slot 0 for the primary passphrase, slot 1 for a recovery key stored securely offline, slot 2 for automated scripts (with a keyfile). Never leave the emergency key only in one place.


Step 7: Hardened systemd Service Unit

📸 Verified Output:

💡 SystemCallFilter=@system-service is a predefined set of ~300 safe syscalls for normal services. It blocks dangerous calls like ptrace, kexec_load, create_module. Check available filter groups with systemd-analyze syscall-filter.


Step 8: Final Security Audit Script

Scenario: The server is almost production-ready. Run a comprehensive security audit that checks all hardening measures and outputs a scored report.

📸 Verified Output:


Summary

Step
Topic
Key Commands / Files

1. Kernel hardening

sysctl security params

/etc/sysctl.d/99-hardening.conf, sysctl -p

2. Audit rules

File integrity monitoring

auditctl -w FILE -p wa -k KEY, /etc/audit/rules.d/

3. AppArmor

Mandatory access control

/etc/apparmor.d/, apparmor_parser -r PROFILE

4. cgroup limits

Resource containment

/sys/fs/cgroup/SLICE/memory.max, cpu.max, pids.max

5. Namespaces

Process isolation

unshare --pid --net --uts --ipc --fork

6. LUKS

Data encryption at rest

cryptsetup luksFormat, cryptsetup open, /etc/crypttab

7. systemd hardening

Service sandboxing

NoNewPrivileges, CapabilityBoundingSet, SystemCallFilter

8. Security audit

Continuous verification

/usr/local/bin/security-audit.sh — scored report

Defense in depth achieved:

  • Kernel level: sysctl hardening, ASLR, network filtering

  • Filesystem level: permissions, LUKS encryption, ProtectSystem

  • Process level: namespaces, cgroups, capabilities

  • MAC level: AppArmor profiles enforce per-binary policies

  • Audit level: auditd tracks all privileged access

  • Service level: systemd sandboxing restricts blast radius

  • Verification level: automated scoring catches regressions

This is the layered security model used in production Kubernetes nodes, hardened VMs, and container-ready bare metal servers.

Last updated