This is a mini-HOWTO for setting up Linux Containers (LXC) on Ubuntu. This guide focuses on the creation of a web server with good process isolation and firewalling.
apt-get install lxc
lxc-create -t ubuntu -n my_server
LXC automatically creates a lxcbr0 bridge on the host, with an IP of 10.0.3.1. By default, there is no DHCP server, so you have to manually set an ip address on the guest container.
Put something like this in /var/lib/lxc/my_server/rootfs/etc/network/interfaces:
auto eth0
iface eth0 inet static
address 10.0.3.10
netmask 255.255.255.0
gateway 10.0.3.1
Manually:
lxc-start -n my_server -d
Automatically on host startup:
ln -s /var/lib/lxc/my_server/config /etc/lxc/auto/my_server.conf
lxc-ls --fancy
lxc-attach -n my_server
You will see your prompt has changed to indicate you are connected as root@my_server. Press ctrl-d to get back to the host system when done.
Delete the ubuntu user. You don't need it.
deluser ubuntu
rm -rf /home/ubuntu
By default, the ubuntu template starts up an SSH server. That's probably unnecessary, so just uninstall it:
apt-get remove openssh-server
Linux Containers are lightweight, meaning that processes from all guests are running under the same kernel. You need to make sure that user and group ids are not colliding between the host and guests, otherwise any processes or files with the same user/group id used in the other system, be they on the host, or one of the guests, can be killed or deleted by the user from that other system.
You can modify each system's uid and gid range inside /etc/adduser.conf. The settings shown here is for the first LXC guest. It uses 2000-2199 as the system id range and 2200-2999 as the user id range. The second LXC guest would start at 3000, and so on:
FIRST_SYSTEM_UID=2000
LAST_SYSTEM_UID=2199
FIRST_SYSTEM_GID=2000
LAST_SYSTEM_GID=2199
FIRST_UID=2200
LAST_UID=2999
FIRST_GID=2200
LAST_GID=2999
Note, that for users created before making this change, you will need to change those user's uid/gid, as well as all file permissions for those users, manually:
usermod -u <NEWUID> <LOGIN>
groupmod -g <NEWGID> <GROUP>
find / -uid <OLDUID> -exec chown -h <NEWUID> '{}' \+
find / -gid <OLDGID> -exec chgrp -h <NEWGID> '{}' \+
I personally see no reason to change the ids of the default system users that ubuntu ships with, unless you're planning to give root access to an untrusted person. However, LXC may not be the best choice if you don't trust your users.
Here's a suitable set of iptables rules for a machine hosting linux containers. It has the following features:
- Allows pinging the host machine.
- Allows SSH to the host machine.
- Setup IP masquerading for the guest containers, so they can reach the net.
- Opens a single port, port 80, and forwards it to the guest container.
- Logs denied packets. Useful for debugging your rules, as well as intrusion detection.
Put your rules in /etc/iptables.up.rules :
*filter
# Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allows all outbound traffic:
-A OUTPUT -j ACCEPT
# Allow all outbound traffic from Linux Containers:
-A FORWARD -i lxcbr0 -j ACCEPT
# Allow HTTP traffic (to be forwarded to the Linux Container hosting the server) :
-A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT
-A FORWARD -i eth0 -p tcp --dport 80 -j ACCEPT
# Allows SSH to the host:
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
# log iptables denied calls (access via 'dmesg' command)
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables INPUT denied: " --log-level 7
-A OUTPUT -m limit --limit 5/min -j LOG --log-prefix "iptables OUTPUT denied: " --log-level 7
-A FORWARD -m limit --limit 5/min -j LOG --log-prefix "iptables FORWARD denied: " --log-level 7
# Reject all other inbound - default deny unless explicitly allowed policy:
-A INPUT -j REJECT
-A FORWARD -j REJECT
COMMIT
*nat
# Forward HTTP traffic to the Linux Container running it:
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.3.10:80
# Allow LXC subnet net access.
-A POSTROUTING -s 10.0.3.0/24 -j MASQUERADE
COMMIT
To load these rules on boot, you can create /etc/network/if-up.d/iptables :
#!/bin/sh
iptables-restore /etc/iptables.up.rules
And make it executable:
chmod +x /etc/network/if-up.d/iptables
- Good guide on Ubuntu system security
- How to add SELinux or Smack for even better process/filesystem isolation.
- The Ubuntu server guide on LXC - I felt this guide was too long, a bit out of date, and hard to follow, hence why this page was written.
Allow LXC subnet net access.
-A POSTROUTING -s 10.0.3.0/24 -j MASQUERADE
returns an error:
iptables: No chain/target/match by that name.