Console Login

LXC & OpenVZ Security: Hardening the Shared Kernel for Production

The Container Trap: Why "Lightweight" Can Mean "Vulnerable"

It is 2013, and the virtualization world is splitting into two distinct camps. On one side, we have the true hardware virtualization purists sticking to Xen and KVM. On the other, the efficiency obsessives are pushing Linux Containers (LXC) and OpenVZ into production environments. The promise is seductive: near-native speed, zero hypervisor overhead, and the ability to pack hundreds of instances onto a single physical server.

But here is the reality check that most hosting providers in Oslo won't give you: Containers share the host kernel.

If you are running a high-traffic e-commerce site targeting the Norwegian market, latency matters. We all know the trek from a datacenter in Germany to the Norwegian Internet Exchange (NIX) in Oslo adds milliseconds that hurt conversion. However, trading security for raw throughput is a dangerous game. In a shared kernel environment, a root escalation exploit inside a container can theoretically give an attacker keys to the entire physical node. I have seen it happen.

The "War Story": The Fork Bomb That Killed a Node

Last month, I was consulting for a media agency in Bergen. They were running their internal dev environment on a massive OpenVZ node to save costs. One junior developer wrote a recursive script that went rogue. Because the default container configuration lacked strict nproc limits, that single container spawned processes until it exhausted the host's process table.

The result? The entire server locked up. SSH failed. The console was unresponsive. Twenty other clients on that same box went dark. Downtime was 45 minutes while we waited for a hard reboot.

If they had been on CoolVDS KVM instances, that rogue script would have only crashed its own virtual machine. The neighbors would have kept humming along. But since they were committed to containers, we had to harden the stack manually.

Hardening LXC: Essential Configuration

If you must use LXC for production in 2013, you cannot rely on the defaults. The default templates are designed for convenience, not security. You need to manually restrict capabilities and resource usage using Control Groups (cgroups).

1. Limiting Resources with Cgroups

You must define strict limits in your container configuration file (usually found in /var/lib/lxc/NAME/config). Without these, a container can consume all available RAM and CPU.

# /var/lib/lxc/web-node-01/config

# Limit Memory to 1024MB
lxc.cgroup.memory.limit_in_bytes = 1024M
# Limit Memory + Swap
lxc.cgroup.memory.memsw.limit_in_bytes = 2048M

# CPU Shares (Weights). Default is 1024.
# Set to 512 to give this container lower priority during contention.
lxc.cgroup.cpu.shares = 512

# Prevent fork bombs: Limit number of processes
lxc.cgroup.tasks = 1000

2. Dropping Kernel Capabilities

Does your web server really need to load kernel modules or reboot the host? Absolutely not. By default, LXC might grant too many capabilities. We strip them down to the bare metal necessities.

# Drop dangerous capabilities
lxc.cap.drop = sys_module sys_boot sys_time audit_control mac_admin

# Enforce AppArmor profile (if you are on Ubuntu 12.04 LTS)
lxc.aa_profile = lxc-container-default

Network Isolation with IPTables

Bridge networking is standard for LXC, but it allows containers to sniff ARP traffic on the bridge if not careful. In a multi-tenant environment, you don't want Customer A seeing Customer B's packets.

We use iptables on the host to strictly control the forwarding chain. This script ensures that traffic can only flow to the specific container IP and nothing else on the private subnet.

#!/bin/bash
# Hardening the bridge (br0)

# 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 -i br0 -s 192.168.100.0/24 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -i br0 -s 192.168.100.0/24 -p tcp --dport 443 -j ACCEPT

# BLOCK everything else from the bridge to prevent lateral movement
iptables -A FORWARD -i br0 -j DROP

Pro Tip: Always bind your management services (SSH, MySQL) to specific interfaces. Never listen on 0.0.0.0 if you have a public facing interface. Use bind-address = 127.0.0.1 in your my.cnf unless you have a secure VPN tunnel.

Disk Quotas and Inode Exhaustion

A common attack vector in 2013 is filling up the disk with millions of zero-byte files, exhausting the inode count. The disk technically has space, but the filesystem cannot create new files. This crashes mail servers and logging daemons instantly.

On ext4 filesystems, you should mount your container storage with user quotas enabled. In OpenVZ, this is handled via vzctl, but on bare LXC, you rely on the host filesystem.

# Check inode usage on the host
df -i

# If you are building a loopback file for the container (safer than directory backing)
dd if=/dev/zero of=/var/lib/lxc/container_disk.img bs=1M count=10000
mkfs.ext4 /var/lib/lxc/container_disk.img
# Mount this as the rootfs for the container to enforce hard boundaries.

The Compliance Angle: Datatilsynet & Personopplysningsloven

For Norwegian businesses, security isn't just about uptime; it is about law. The Personopplysningsloven (Personal Data Act) places strict requirements on how personal data is secured. If you are hosting patient data or financial records, a shared kernel environment is a compliance nightmare.

If an attacker breaks out of a container on a shared host, they potentially access the memory space of other containers. This is why for any data classified as sensitive, we cannot recommend standard LXC/OpenVZ setups.

The CoolVDS Architecture Choice

This brings us to why CoolVDS relies heavily on KVM (Kernel-based Virtual Machine) for our primary commercial offering. Unlike containers:

  • Hardware Virtualization: Each CoolVDS instance runs its own independent kernel. If your neighbor panics their kernel, your instance doesn't blink.
  • SELinux Integration: We run strict SELinux policies on the hypervisor level to ensure total process isolation.
  • Dedicated Resources: When you buy 2GB of RAM on our KVM platform, that RAM is reserved for you. It isn't burstable memory that might disappear when the host gets busy.

Conclusion

Containers are fantastic for stateless web workers or development sandboxes where density is the priority. I use them daily for testing scripts. But for the core infrastructure that pays the bills?

Don't risk a shared kernel exploit. If you need the speed of an SSD without the noisy neighbor risks, you need full virtualization. Control your own kernel, manage your own modules, and sleep better knowing your memory space is yours alone.

Ready to upgrade from shared environments? Deploy a KVM instance on CoolVDS today and experience true isolation with direct connectivity to NIX.