Console Login

Securing the Cage: Hardening Linux Containers (LXC/OpenVZ) for Production Environments

Securing the Cage: Hardening Linux Containers (LXC/OpenVZ) for Production Environments

Let’s be honest: the recent hype around Docker (currently v0.5) and the longstanding dominance of OpenVZ in the budget VPS market has made developers lazy. We love the sub-second boot times and the minimal overhead. But most systems administrators are deploying containers with default configurations that are, frankly, a security nightmare waiting to happen.

I recently audited a setup for a client in Oslo—a media streaming startup trying to squeeze every ounce of performance out of their hardware. They were running a multi-tenant environment using standard LXC templates on Ubuntu 12.04 LTS. It took me less than ten minutes to demonstrate how a rogue process inside one container could starve the entire host of CPU cycles, bringing their service to a grinding halt. If that had been a malicious escalation attack instead of a resource exhaustion test, they would have been explaining a massive data breach to Datatilsynet (The Norwegian Data Protection Authority).

In this guide, we are going to look at how to actually lock down Linux containers. We will cover dropping kernel capabilities, enforcing strict resource limits via cgroups, and why, for true isolation, you might just want to abandon containers entirely in favor of KVM.

The Shared Kernel Fallacy

The fundamental problem with LXC and OpenVZ is that they are operating system-level virtualization. Unlike a true hypervisor, your container is sharing the kernel with the host and every other container on that box. If there is a kernel panic in Container A, the whole server goes down. More frighteningly, if there is an unpatched exploit in the kernel syscall interface, root inside a container can theoretically become root on the host.

To mitigate this, you must limit what the root user inside the container is allowed to do. We do this by dropping capabilities.

1. Drop Dangerous Capabilities

By default, a container retains many privileges it does not need. You should explicitly strip these in your container configuration file. For LXC, this is usually found in /var/lib/lxc/CONTAINER_NAME/config.

Here is a battle-tested configuration snippet that drops the ability to insert kernel modules, manipulate raw I/O ports, or reboot the host:

# Drop capabilities to prevent escape and host modification
lxc.cap.drop = sys_module
lxc.cap.drop = sys_rawio
lxc.cap.drop = sys_time
lxc.cap.drop = sys_boot
lxc.cap.drop = mac_admin
lxc.cap.drop = mac_override
lxc.cap.drop = sys_admin

Warning: Dropping sys_admin is the safest route but may break some applications that expect full root behavior. Test this in a staging environment first.

2. Preventing Neighbor Noisiness with Cgroups

One of the biggest complaints we hear from clients migrating to CoolVDS from budget providers is the "Noisy Neighbor" effect. In a shared container environment without strict limits, one user compiling a massive C++ project can steal CPU time from your database.

We use the Linux Control Groups (cgroups) subsystem to strictly enforce fair scheduling. You shouldn't rely on the operating system to play nice; you must force it.

To limit a container to using only 512MB of RAM and preventing it from swapping the host into oblivion, apply these flags:

# Resource Limiting via Cgroups
lxc.cgroup.memory.limit_in_bytes = 512M
lxc.cgroup.memory.memsw.limit_in_bytes = 512M
# CPU shares (default is 1024). Set to 512 to give it half priority.
lxc.cgroup.cpu.shares = 512
Pro Tip: Never set the swap limit equal to the memory limit if you want to allow some burstability, but in high-security environments, disabling swap for containers prevents sensitive data from being written to the host's disk unencrypted.

3. Network Isolation with iptables

Another common failure point is the bridge network. By default, containers on the same bridge (like lxcbr0) can ARP spoof or sniff traffic from each other. If you are hosting multiple clients or distinct services (e.g., your payment gateway vs. your blog), they must not touch.

You can use iptables on the host node to ensure traffic only flows to the gateway, not between containers.

# Flush existing forward rules
iptables -F FORWARD

# Allow established connections
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow outbound HTTP/HTTPS from the container subnet
iptables -A FORWARD -s 10.0.3.0/24 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -s 10.0.3.0/24 -p tcp --dport 443 -j ACCEPT

# DROP everything else (Crucial for isolation)
iptables -P FORWARD DROP

This ensures that even if a container is compromised, it cannot easily scan your internal network looking for other targets.

The MAC Layer: AppArmor and SELinux

Discretionary Access Control (DAC)—standard chmod/chown permissions—is insufficient for modern threat landscapes. You need Mandatory Access Control (MAC). On Ubuntu/Debian systems, AppArmor profiles are essential for containing LXC processes.

Verify that your container is actually running under a confined profile:

# Check current AppArmor status
sudo apparmor_status

# Ensure your container config includes:
lxc.aa_profile = lxc-container-default

If you are running CentOS 6.4 (common in enterprise), SELinux is your weapon of choice. While many admins disable SELinux (`setenforce 0`) because it's "too hard," this is lazy engineering. Learn the contexts. A container process should run as svirt_lxc_net_t to ensure it cannot read files labeled ssh_home_t on the host.

The Ultimate Fix: KVM and Hardware Virtualization

While the steps above harden a container, they cannot change the architecture. Shared kernels always carry a non-zero risk of privilege escalation. This is why financial institutions and health organizations in Norway, governed by strict interpretations of the Personopplysningsloven, often reject container-based hosting for sensitive data.

At CoolVDS, we acknowledge the utility of containers for development, but for production infrastructure, we default to KVM (Kernel-based Virtual Machine).

Feature OpenVZ / LXC (Containers) KVM (CoolVDS Standard)
Kernel Shared with Host Dedicated Kernel per VPS
Isolation Process level (weak) Hardware level (strong)
Resource Guarantees Soft limits (burstable) Hard reservation (RAM/CPU)
OS Variety Linux only Linux, BSD, Windows, Solaris

KVM treats your VPS as a distinct machine. If your neighbor's kernel crashes, your server keeps humming. If they get DDoSed, our upstream filtering combined with hard resource separation protects your bandwidth. For low-latency applications targeting the Nordic market, this stability is non-negotiable.

Summary

If you must use containers in 2013, do not rely on the defaults. Drop capabilities, enforce cgroups, and use MAC layers like AppArmor. However, if your business relies on guaranteed uptime and strict data privacy compliance, stop playing with shared kernels.

Secure your infrastructure with the isolation it deserves. Deploy a KVM-based, SSD-accelerated instance on CoolVDS today and experience the stability of dedicated resources.