Adeus chroot… seja bem vindo LXC…

Eu já escrevi sobre como instalar o Ubuntu em um ambiente chroot antes, mas recentemente descobri que o kernel fornece uma interface mais poderosa de isolar pedaços do sistema, com a qual novas ferramentas têm sido criadas. Uma dessas ferramentas é a ferramenta LXC.

Chroot

O chroot é uma chamada de sistema do sistema operacional que permite mudar o diretório raiz de processos-filhos. Usando esse recurso, você pode, por exemplo, manter uma distribuição Linux secundária instalada em uma pasta (no lugar de uma partição) e executar programas desse lugar sem uma perda de desempenho significativa que ocorre com máquinas virtuais, algumas vezes.

Uma das técnicas para criar um ambiente seguro é isolar o acesso de componentes que não confiem (ou não o precisem) uns nos outros. Em sistemas baseados em Unix, incluindo o GNU/Linux, temos usuários, grupos e o avançado sistema de permissões para “cumprir” essa condição.

Dessa forma, você só precisa ter “paranoia” em evitar que processos consigam acesso ao usuário root. Alguns leitores podem pensar que chroot seria a solução do problema, já que processos rodando dentro da jaula chroot ficariam incapacitados de ler arquivos de fora da jaula. Entretanto, mesmo dentro da jaula, um usuário root ainda é muito poderoso. Um primeiro exemplo:

shot-2013-02-23_14-49-44

shot-2013-02-23_14-57-09

shot-2013-02-23_14-57-32

O exemplo anterior pode ter parecido um pouco inútil, mas seu objetivo foi apenas mostrar que isolar arquivos não é suficiente caso o ambiente dentro da jaula de chroot consiga acesso ao usuário root. Na verdade, como mostra o exemplo seguinte (consulte o asciinema para versão animada), caso o ambiente dentro da jaula de chroot consiga acesso ao usuário root e chroot seja a única técnica de segurança, nem mesmo isolamento de arquivos é alcançado.

shot-2013-02-23_14-48-56

Citando a manpage sobre a chamada chroot:

This call changes an ingredient in the pathname resolution process and does nothing else.

[…]

This call does not close open file descriptors, and such file descriptors may allow access to files outside the chroot tree.

Concluindo, o chroot não livra você da responsabilidade de cuidar da segurança do sistema ou cria um ambiente que pode ser usado para testar software não confiável. O que o chroot fornece é um modo flexível de isolar a hierarquia de arquivos, permitindo, por exemplo, que você execute executáveis (até um determinado ponto) conflitantes no mesmo sistema.

Linux containers, namespaces s LXC

LXC é o nome da ferramenta responsável por gerenciar containers e namespaces. É um projeto legal que fornece uma biblioteca, vários bindings e ferramentas.

https://asciinema.org/a/7831

Um container seria algo parecido com uma jaula chroot, uma forma de isolar componentes do sistema. Do ponto de vista do LXC, a diferença é o nível de segurança que o container fornece, pois o objetivo do container é fornecer acesso isolado a qualquer recurso que possa ser utilizado para controlar ou acessar o sistema fora do container. Uma vantagem-bônus é que o container possui sua própria visão dos processos (o PID) e, assim, é possível usar um init no mesmo.

https://asciinema.org/a/7832

É possível conseguir essa segurança com máquinas virtuais, mas você perde algum desempenho optando por essa solução. Há bastante recursos que vêm sendo investidos para tornar o desempenho de máquinas virtuais mais rápidas, incluindo instruções de virtualização embutidas na CPU, especificação de hardware inexistente, mas que pode ser emulada com um desempenho melhor e mais fácil, drivers implementando a interface de hardware inexistente para sistemas operacionais que irão ser executados em máquinas virtuais, gerenciadores de máquinas virtuais embutidos no kernel com acesso direto ao hardware, …

https://asciinema.org/a/7833

Você tem, de um lado, uma solução com segurança e menos desempenho e, do outro, uma solução com desempenho e menos segurança. Ambos são peças de software complexas e difíceis de desenvolver (e desenvolver da forma certa, sem abrir um novo buraco de segurança).

Uma das propostas para melhorar a segurança sem recorrer a virtualização é construir (e usar) uma interface de userspace mais poderosa capaz de criar ambientes isolados, que seriam gerenciados pelo próprio kernel, e, além disso, teriam um gargalo bem menor de desempenho. Essa interface já existe no Linux e pode ser utilizada por ferramentas como o systemd-nspawn e lxc. O systemd-nspawn não tem foco na segurança, mas sim em capacidades de debug, então não será mais citado nesse texto.

É chegado o momento

Para tornar o texto mais claro, irei usar os termos hospedeiro e convidado para me referenciar, respectivamente, ao sistema inicial no qual você quer instalar o LXC e o novo ambiente, que irá ser executado dentro do container LXC.

Crie uma estrutura para um ambiente chroot seguindo as instruções na wiki do ArchLinux (ou esse segundo artigo, mais detalhado) e depois instale, adicionalmente, o pacote systemd-sysvcompat. Esse pacote não é listado como necessário em instruções de chroot, porque ele não é necessário para ambientes chroot, mas containers são ambientes mais isolados que ambientes chroot e ainda precisam de um init para funcionar (de forma mais fácil, ou mais completa, se preferir). Lembre de instalar outros programas que você queira acessar dentro do ambiente (como o firefox, por exemplo).

Com o seu rootfs pronto, é hora de configurar o container. Para gerar a configuração inicial do container, use o seguinte comando, como root:

Agora mova o seu rootfs para a pasta /var/lib/lxc/nome_do_seu_container. O meu arquivo config foi baseado no template do ArchLinux e tem o seguinte conteúdo:

Meu arquivo /var/lib/lxc/nome_do_seu_container/fstab ficou com o seguinte conteúdo:

Agora você pode iniciar o seu container usando o seguinte comando (como root):

E pará-lo usando esse outro (como root):

Configuração de rede

Grande parte das instruções abaixo eu aprendi na wiki do Arch.

Instale o pacote netctl no ambiente hospedeiro e o pacote iproute2 no ambiente convidado. Então crie, no ambiente hospedeiro, o arquivo /etc/netctl/nat com o seguinte conteúdo:

Depois inicie e habilite o serviço netctl para o perfil criado (nat) com os comandos, no ambiente hospedeiro:

Últimas mudanças no ambiente hospedeiro para habilitar a rede:

Depois crie o arquivo (dentro do convidado) etc/systemd/system/multi-user.target.wants/routes.service, com o seguinte conteúdo:

Agora execute esse serviço no ambiente convidado:

Algo que não é necessário, mas é bastante útil, é editar o arquivo /etc/hosts de ambos ambientes (hospedeiro e convidado) e incluir alias para os ips que são chatos para memorizar:

  • 192.168.100.1: Hospedeiro
  • 192.168.100.2: Convidado

Rodando aplicações que usem o X

Para conseguir rodar aplicações que usem o X de forma fácil, vamos usar o X11Forward via ssh, que fornece um túnel seguro para o tráfego de dados. É claro que as aplicações estão rodando em rede, mas é uma rede virtual acessível somente do seu computador local, então a “segurança” extra fornecida pelo ssh é desnecessária e, à primeira vista, serve somente como um gargalo a mais de desempenho. O real motivo de eu optar pelo ssh foi a facilidade (configura o ambiente X e outras coisas para você), mas o ssh fornece sim algumas opções para melhorar a segurança.

Antes de entrar em mais detalhes sobre as consequências da escolha por ssh, a descrição do processo é mais útil. Para rodar aplicações dentro dessa configuração, instale os pacotes xorg-server, xorg-xauth e openssh no ambiente convidado. Então edite o arquivo /etc/ssh/sshd_config adicionando seguinte a linha:

Agora execute o comando abaixo para executar o serviço sshd e permitir que o mesmo seja iniciado junto com o sistema operacional (convidado):

Pronto! Agora você pode executar aplicação X dentro do ambiente convidado usando o servidor X do ambiente hospedeiro. Se quiser iniciar o chromium do ambiente convidado, por exemplo, execute o seguinte comando dentro do ambiente hospedeiro:

A opção -X habilita o encaminhamento de pacotes relacionados ao servidor X para o ambiente hospedeiro. A opção -X faz o encaminhamento funcionar sob certas restrições, desabilitando algumas extensões que os desenvolvedores do ssh não consideram completamente seguras. Assim sendo, talvez nem todas as aplicações funcionem dessa forma. Uma opção substituta para pessoas menos paranoicas é a opção -Y. Por exemplo, a seguinte saída no chromium só acontece quando eu o executo sob menos privilégios (opção -X):

Nesse momento você deve ter percebido que o ssh fornece sim alguma segurança adicional. O último passo para essa seção é configurar o ambiente convidado para que ele pare de perguntar a senha toda vez que você quer logar (isso é incômodo). Para tal, execute os seguintes comandos:

Para mais informações sobre execução remota de aplicações X, visite a wiki do ArchLinux.

Configuração de placa de vídeo

SIM, eu tive todo esse trabalho (o trabalho maior é a parte de pesquisa/encontrar-documentação, pois usar essas ferramentas é fácil) para usar o Steam e jogos closed-source sem ficar *muito* paranoico. É claro que não adiantaria utilizar todo esse esquema de “segurança” se você utilizasse um módulo do kernel fechado da NVidia, mas os drivers open source já são bons o suficiente para eu jogar alguns jogos 3D no meu bem modesto netbook.

Altere o arquivo de configuração do container LXC e adicione a seguinte linha:

Depois crie o arquivo especificado acima com o conteúdo a seguir (e lembre de dar permissão de execução ao mesmo):

Pronto! Agora você pode rodar aplicações do container que usem openGL sem precisar recorrer ao llvmpipe, que faria sua CPU chorar.

Configurando o suporte a áudio

Bom, já que vou usar o steam para jogar mesmo, então é melhor fazer o serviço completo e habilitar áudio também. Primeiro copie o arquivo de configuração do ambiente hospedeiro ~/.config/pulse/cookie para para o ambiente convidado. Então use o programa paprefs, vá na aba “Servidor de rede” e habilite a opção “Habilitar o acesso a dispositivos de som locais via rede”. O último passo é configurar a seguinte variável de ambiente (pode ser feito no arquivo .bashrc):

paprefs

Mais ideias

Essa seção é só uma desculpa para compartilhar esse post de muito tempo atrás sobre como uma empresa está usando a capacidade de ativação por socket do systemd para permitir alta densidade em seus servidores. Iniciar um container é bem rápido, bem mais rápido que iniciar uma máquina virtual. E usar um kernel único permite um gerenciamento de recursos mais inteligente do que temos, por exemplo, aqui (spoiler: é sobre hypervisor).

Na teoria, Linux containers permitem fazer um gerenciamento de recursos mais eficiente que máquinas virtuais. Servidores são grandes candidatos para se beneficiar de tal tecnologia. Isso não significa, entretanto, que máquinas virtuais perdem sua utilidade. Quando deseja-se utilizar um sistema operacional diferente (ou mesmo uma versão diferente do kernel) ou uma arquitetura diferente, por exemplo, containers não são melhores (nem sequer são uma opção).

Dois alvos que podem ser atacados usando containers são servidores e computadores de usuários. Em um você ganha desempenho e melhor compartilhamento de recursos da máquina física para os diferentes containers. No caso dos servidores poderia usar algo como o Docker. No outro (computadores de usuários) você ganha segurança e melhor isolamento ao rodar aplicações não-confiáveis e a solução poderia ser melhor que o gerenciamento de aplicações do Android. Para o problema de aplicações no computadores de usuários tem essa palestra legal do Lennart Poettering.

Um vídeo bem curto que mostra o Steam funcionando dentro do ambiente LXC:

http://vimeo.com/83444753

Referências adicionais

Além dos link encontrados em meio ao texto que você leu (assim espero), usei esse artigo do lwn.net como referência inicial.

EDIT (2014/01/06):

Seção “Mais ideias” estendida.

EDIT2 (2014/02/23):

Descobri o asciinema e coloquei algumas referências/links no meio do texto.

Tags:,

2 responses to “Adeus chroot… seja bem vindo LXC…”

  1. Magnun says :

    Ótimo artigo. Você já testou o Docker também?

Comentários (with MarkDown support)

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: