Crear contenedores con usuarios sin privilegios utilizando LXC en Ubuntu

Introducción

Los contenedores creados por usuarios sin privilegios son muchos mas seguros en comparación con su contraparte creados por el usuario root ya que su administrador no corresponde directamente con el usuario administrador del huésped sino que sus usuarios son mapeados por unos UID y GID diferentes.  Por ejemplo, el root (0) de un contenedor será mapeado el huésped por un UID como 100000 por lo tanto, en el peor caso en que un atacante lograra salir del contenedor hasta el huésped, lo haría como un usuario sin privilegios.

Esto también trae consigo como efecto colateral negativo que las siguientes operaciones no sean permitidas.

  1. Montar la mayoría de sistemas de archivos.
  2. Crear dispositivos de nodo.
  3. Cualquier operación realizada por un uid/gid que no se encuentre en la lista de mapeo.

Adicionalmente esto produce que las plantillas de las distribuciones no funcionen y sea necesario utilizar la plantilla download que permite descargar imagenes preconstruidas de las distribuciones que funcionan en este tipo de ambiente.

Configuración para permitir contenedores por usuarios sin privilegios

$ mkdir -p ~/.config/lxc
$ echo "lxc.id_map = u 0 100000 65536" > ~/.config/lxc/default.conf
$ echo "lxc.id_map = g 0 100000 65536" >> ~/.config/lxc/default.conf
$ echo "lxc.network.type = veth" >> ~/.config/lxc/default.conf
$ echo "lxc.network.link = lxcbr0" >> ~/.config/lxc/default.conf
$ echo "$USER veth lxcbr0 10" | sudo tee -a /etc/lxc/lxc-usernet

Si se desea puede tomarse al archivo /etc/lxc/default.conf  como plantilla para la preparación del archivo de configuración local del usuario ~/.config/lxc/default.conf.

Los valores de lxc.id_map tanto para el grupo como para el usuario deberán coincidir con los registrados en and /etc/subgid y /etc/subuid respectivamente.  En caso que requiera ajustar estos rangos utilizar el siguiente comando.

$ sudo usermod -v 100000-200000 -w 100000-200000 NOMBRE_USUARIO

Comúnmente es necesario cerrar y volver a abrir la sesión del usuario actual o inclusive, reiniciar el sistema operativo para garantizar que el usuario se encuentre correctamente asignado a sus respectivos cgroups
(esto es especialmente importante si cgmanager no se había instalado antes de la instalación de LXC).

En caso de ser necesario, ajuste el permiso de ejecución en el directorio bajo el cual se almacena la configuración y los sistemas de archivos de los contenedores: ~/.local/share/lxc/.

$ sudo chmod -R o+X ~/.local

Administración de los contenedores

La administración de los contenedores se realiza tal y como se reseña en un artículo anterior, esta vez sin la necesidad del sudo ya que son contenedores creados por usuarios sin privilegios de administración.

A continuación se reseñan los comandos principales.

$ lxc-create -t download -n NOMBRE_CONTENEDOR — -d PLANTILLA -r VERSION -a ARQUITECTURA Crear un nuevo contenedor
$ lxc-start -n NOMBRE_CONTENEDOR -d Iniciar un contenedor
$ lxc-attach -n NOMBRE_CONTENEDOR
Acceder al shell de un contenedor desde el actual
$ lxc-stop -n NOMBRE_CONTENEDOR
Detener a un contenedor
$ lxc-destroy -n NOMBRE_CONTENEDOR
Destruir (remover) un contenedor existente

Recursos

  1. LXC in Ubuntu’s Server Guide
    https://help.ubuntu.com/lts/serverguide/lxc.html
  2. LXC Getting Started in Linux Containers
    https://linuxcontainers.org/lxc/getting-started/

Los primeros 10 minutos con LXC en Ubuntu

Rutas

/var/cache/lxc Imágenes de sistemas operativos descargados a partir de un template
/etc/lxc Configuración general
/var/lib/lxc/ Contenedores creados por root
/var/lib/lxc/NOMBRE_CONTENEDOR/config Configuración específica del contenedor
~/.local/share/lxc Contenedores creados por usuarios sin privilegios

Instalación

Instalación de los paquetes básicos.

$ sudo aptitude install lxc lxc-templates

De acuerdo al sistema operativo (template) que se desee instalar también será necesario uno de los siguientes paqutes.

ArchLinux arch-install-scripts
Debian/Ubuntu debootstrap
CentOS yum

Una vez instalado probar el ambiente disponible.

$ lxc-checkconfig

Kernel configuration not found at /proc/config.gz; searching...
Kernel configuration found at /boot/config-3.13.0-37-generic
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled
Multiple /dev/pts instances: enabled

--- Control groups ---
Cgroup: enabled
Cgroup clone_children flag: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled

--- Misc ---
Veth pair device: enabled
Macvlan: enabled
Vlan: enabled
File capabilities: enabled

Note : Before booting a new kernel, you can check its configuration
usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig

Comandos principales

Listar los templates disponibles

$ ls /usr/share/lxc/templates

    lxc-alpine    lxc-archlinux  lxc-centos  lxc-debian    lxc-fedora  lxc-openmandriva  lxc-oracle  lxc-sshd    lxc-ubuntu-cloud
 lxc-altlinux  lxc-busybox    lxc-cirros  lxc-download  lxc-gentoo  lxc-opensuse      lxc-plamo   lxc-ubuntu

Crear un contenedor (usuario con privilegios)

$ sudo lxc-create -n NOMBRE_CONTENEDOR -t NOMBRE_TEMPLATE

Para especificar una versión (release) específico del template que se desea instalar.  Por ejemplo, si se desea elegir ubuntu lucid específicamente se debe ejecutar el siguiente comando.

$ sudo lxc-create -t ubuntu -n NOMBRE_CONTENEDOR -- -r lucid

Si se desea crear un contenedor de 32 bits en una máquina de 64 bits es necesario agregar el parámetro -a de la sigiuente manera.

$ sudo lxc-create -n NOMBRE_CONTENEDOR -t NOMBRE_TEMPLATE -a i386

Información de los contenedores

$ lxc-ls --fancy

Obtener información ampliada de un contenedor específico

$ lxc-info --name NOMBRE_CONTENEDOR

Iniciar un contenedor

$ lxc-start -n NOMBRE_CONTENEDOR -d

Acceder a la consola de un contenedor

$ lxc-console -n NOMBRE_CONTENEDOR

Para salir de la consola es necesario presionar la secuencia de teclas Ctrl+A Q.

Para acceder al shell del contenedor desde el mismo shell actual, ejecutar el siguiente comando.

$ lxc-attach -n NOMBRE_CONTENEDOR

Suspender (congelar) la ejecución de un contenedor

$ lxc-freeze -n NOMBRE_CONTENEDOR

Reanudar (descongelar) la ejecución de un contenedor

$ lxc-unfreeze -n NOMBRE_CONTENEDOR

Finalizar la ejecución de un contenedor

Realizar una finalización segura (apagado).

$ lxc-shutdown -n NOMBRE_CONTENEDOR

Realizar un apagado abrupto (halar del cable).

$ lxc-stop -n NOMBRE_CONTENEDOR

Destruir un contenedor

Esta acción elimina los archivos asociados con el contenedor.

$ lxc-destroy -n NOMBRE_CONTENEDOR

Recursos

Los primeros 10 minutos con LXD el hypervisor de contenedores en Ubuntu

Instalación

$ sudo add-apt-repository ppa:ubuntu-lxc/lxd-git-master

$ sudo apt-get update

$ sudo apt-get install lxd

El proceso de instalación incluye la creación del grupo lxd al que deberán pertenecer todos los usuarios que interactúen con los contenedores.  Inicialmente se agregan a este grupo todos los usuarios que pertenecían a admin y sudoers en el momento de la instalación.

Una vez realizada la instalación es necesario cerrar y volver a abrir la sesión de usuario para que la inscripción en el grupo lxd sea tomada en cuenta.  Si se desea obviar esto, ejecute el siguiente comando para incluir al usuario en el grupo mencionado sobre la sesión actual.

$ newgrp lxd

Gestión de imágenes

Agregar el repositorio de linuxcontainers.org.

$ lxc remote add lxc-org images.linuxcontainers.org

$ lxc remote list

+---------+-----------------------------------------+--------+
|  NAME   |                   URL                   | PUBLIC |
+---------+-----------------------------------------+--------+
| local   | unix:///var/lib/lxd/unix.socket         | NO     |
| lxc-org | https://images.linuxcontainers.org:8443 | YES    |
+---------+-----------------------------------------+--------+

Importar imágenes para tenerlas disponibles localmente.

# Ubuntu Cloud
$ lxd-images import ubuntu --alias ubuntu-cloud

# Debian 8 64 bits
$ lxc image copy lxc-org:/debian/jessie/amd64 local: --alias=jessie-amd64

Consultar mas información acerca de las imágenes disponibles en el repositorio de linuxcontainers.org.

Listar las imágenes disponibles en un repositorio remoto

$ lxc image list lxc-org:

+--------------------------------+--------------+--------+-------------------------+---------+-------------------------------+
|             ALIAS              | FINGERPRINT  | PUBLIC |       DESCRIPTION       |  ARCH   |          UPLOAD DATE          |
+--------------------------------+--------------+--------+-------------------------+---------+-------------------------------+
|                                | ee326b31ae93 | yes    | Debian squeeze (amd64)  | x86_64  | Oct 1, 2015 at 6:17pm (COT)   |
|                                | cd3f30323ce2 | yes    | Centos 6 (amd64)        | x86_64  | Oct 1, 2015 at 10:17pm (COT)  |
|                                | b6a940bfe3a4 | yes    | Plamo 5.x (amd64)       | x86_64  | Sep 30, 2015 at 5:23pm (COT)  |
|                                | 5351e4792a81 | yes    | Plamo 5.x (amd64)       | x86_64  | Oct 1, 2015 at 5:24pm (COT)   |
|                                | 02a8d955bc82 | yes    | Plamo 5.x amd64 (mini)  | x86_64  | Sep 30, 2015 at 5:50pm (COT)  |
|                                | 5df2ba98422b | yes    | Plamo 5.x amd64 (mini)  | x86_64  | Oct 1, 2015 at 5:50pm (COT)   |

...

Listar las imágenes disponibles localmente

$ lxc image list

+--------------+--------------+--------+------------------------------------+--------+------------------------------+
|    ALIAS     | FINGERPRINT  | PUBLIC |            DESCRIPTION             |  ARCH  |         UPLOAD DATE          |
+--------------+--------------+--------+------------------------------------+--------+------------------------------+
| jessie-amd64 | 87c085189294 | yes    | Debian jessie (amd64)              | x86_64 | Oct 3, 2015 at 1:40am (COT)  |
| ubuntu-cloud | a1448d43bb7c | no     | Ubuntu 14.04 LTS server (20150930) | x86_64 | Oct 3, 2015 at 12:49am (COT) |
+--------------+--------------+--------+------------------------------------+--------+------------------------------+

Obtener información de una imagen disponible localmente.

$ lxc image info jessie-amd64

Fingerprint: 87c085189294cd6a316dbefe1e235f9b9e69aa1b049df4ddce2202ad0f9c56ab
Size: 1e+02MB
Architecture: x86_64
Public: no
Timestamps:
    Created: 2015/10/02 23:30 UTC
    Uploaded: 2015/10/03 06:40 UTC
    Expires: never
Properties:
    description: Debian jessie (amd64)
Aliases:
    - jessie-amd64

Remover una imagen dispoible localmente.

$ lxc image delete jessie-amd64

Sincronizar la versión de las imágenes locales con la disponible en los repositorios.

$ lxd-images sync

Es posible agregar la opción --sync durante la importación de la imagen para mantenerla actualizada automáticamente.

Gestión de contenedores

Crear un nuevo contenedor a partir de una imagen disponible localmente.

$ lxc launch ubuntu-cloud myContainer

Si la imagen solicitada, ubuntu-cloud en este caso, no se encuentra disponible localmente, esta es importada automáticamente y puesta en el caché por 10 días.

Listar los contenedores disponibles y su estado.

$ lxc list

Iniciar un contenedor explícito.

$ lxc start myContainer

Consultar el registro (log) de un contenedor explícito.

$ lxc info --show-log myContainer

Detener a un contenedor explícito.

$ lxc stop myContainer

Destruir (remover) a un contenedor explícito.

$ lxc delete myContainer

Interacción con el contenedor

Ejecutar un comando en un contenedor específico.

$ lxc exec myContainer -- COMANDO

Acceder al shell del contenedor.

$ lxc exec myContainer -- /bin/bash

Transferir un archivo hacia el contenedor.

$ lxc file push ARCHIVO myContainer/ruta/de/destino

Transferir un archivo desde el contenedor.

$ lxc file pull myContainer/ruta/de/origen .

Recursos

  1. What’s LXD?
    https://linuxcontainers.org/lxd/introduction/
  2. LXD – The Linux container hypervisor
    http://www.ubuntu.com/cloud/tools/lxd
  3. Getting started with LXD – the container lightervisor
    https://insights.ubuntu.com/2015/04/28/getting-started-with-lxd-the-container-lightervisor/
  4. Installing LXD and the command line tool
    https://insights.ubuntu.com/2015/03/20/installing-lxd-and-the-command-line-tool/
  5. Infographic: LXD Machine containers from Ubuntu
    https://insights.ubuntu.com/2015/09/23/infographic-lxd-machine-containers-from-ubuntu/
  6. Repositorio de LXD en GitHub
    https://github.com/lxc/lxd