[Tutorial] Criando um sistema imutável fácil e prático sem trocar de sistema

Introdução

Tem ocorrido uma nova onda de sistemas operacionais que tem chamado atenção chamados imutáveis, basicamente são sistemas onde não é possível (por meios diretos pelo menos) escrever nos arquivos do sistema, via de regra qualquer sistema Linux possui nativamente um software pra causar esse efeito chamado chattr

chattr

Esse software cujo nome vem de CHange ATTRibutes (ou em português mudar atributos) permite controlar o que se pode fazer ou não com um arquivo ou diretório (ou em outras palavras mudar os atributos do arquivo).

Uma das flags i define o atributo da imutabilidade, a essa altura você já deve ter percebido como isso vai ser feito, mas não adianta muito fazer isso no lugar errado…

Como o Linux distribui os programas do sistema

Existem inúmeros materiais explicando isso mas 3 diretórios merecem atenção:

  • /usr de Unix Shared Resources é onde ficam todos os arquivos do sistema operacional, temas, programas, bibliotecas até os papéis de parede

  • /var é onde ficam os arquivos variáveis do sistema, os arquivos arqui tendem a mudar bastante, é onde estão bancos de dados,
    cache, flatpakss, snaps, logs entre outras coisas ficam

  • /etc de origem incerta é onde ficam as configurações do sistema como os grupos, usuários, configurações, chaves de segurança…

Sabendo disso podemos perceber que, /var precisa ser gravavel, e se você deixar /etc imutável poderá ter problemas e /usr é onde praticamente tudo que não deve ser mexido no sistema está, então achamos nosso diretório, mas tem mais uma coisa, a quantidade de pastas é gigantesca e aplicar de forma recursiva demoraria muito, mas felizmente outra ferramenta pode nos ajudar

find

O find ou encontrar, é uma das ferramentas mais versáteis, ele nos permite procurar pastas e arquivos podendo passar inúmeros atributos pra refinar os resultados, precisamos de duas coisas, encontrar todos os diretórios em /usr e executar o comando chattr +i neles, as flags (parâmetros especiais) que precisamos é o -type e o -exec:

O ao passar o parâmetros d de “directory” a flag -type nós conseguimos filtrar apenas os diretórios

Já a flag -exec é tão simples quanto com um detalhe, passamos chattr +i que é o comando que queremos executar, depois o {} que representa o diretório encontrado e por fim o `;’ que indica o fim da flag -exec

O \ é necessário porque ; é um caractere especial do bash/zsh/fish

Deixando o sistema imutável

Agora que sabemos onde fazer, como fazer e o que fazer, podemos deixar o sistema imutável assim:

sudo find /usr -type d -exec chattr +i {} \;

E pronto, ao término da execução o sistema estará travado para modificação

Testando

Podemos testar isso simplesmente removendo pacotes:

sudo apt remove nano

Você vai notar que o pacote não foi removido, outro exemplo seria criar um arquivo:

echo | sudo tee /usr/bin/teste-imutavel

Note que também resulta em erro e o arquivo não é criado

Nota para usuários Arch e derivados, pode ser necessário passar o parâmetro --overwrite '/etc/*' caso tente instalar um pacote no sistema imutável e tente instalar novamente com a imutabilidade desativada

Desfazendo

Se prestou atenção, vc deve ter percebido que o gestor de pacotes está travado, não consegue remover ou instalar pacotes, isso é claro, impede a atualização do sistema, para desfazer é tão simples quanto fazer, basta trocar o +i por -i:

sudo find /usr -type d -exec chattr -i {} \;

E é isso

Esse é talvez o jeito mais simples e intuitivo de deixar o sistema imutável, tem suas limitações é claro mas dada a simplicidade e universalidade é algo bem interessante de se ter

Se esse artigo te ajudou ou te ensinou algo de útil ou valioso, considere fazer um pix de qualquer valor para natanaelpix@gmail.com e fácil, rápido e me motiva trazer esse tipo de conteúdo

7 curtidas

Isso é um recurso a mais, não faz parte da imutabilidade, num cenário com OverlayFS a camada (ou sistema imutável) é simplesmente a camada somente leitura (sem permissão de gravação, o objetivo da camada de OverlayFS é permitir modificações sem alterar a base, é possível por exemplo sobrepor uma camada mutável sobre outra ou ainda sobrepor duas camadas imutáveis ou ainda sobrepor uma camada imutável sobre uma mutável para impedir acesso de escrita em um diretório em uma sandbox por exemplo

Faz se você quer um sistema imutável sem alterar pontos de montagem, um dos pontos de eu ter feito menção a esse post no do Vanilla OS é porque (embora eu não tenha tirado de lá), eles usam exatamente o mesmo mecanismo para tornar o sistema imutável a única diferença na forma de execução é que eles rescreveram o utilitário chattr em golang (sendo que no início do projeto aparentemente usavam chamadas diretas ao binário tal qual eu fiz):

Eles o fazem inclusive de forma mais agressiva alterando outros atributos diretamente ao arquivo (verificavel ativando a verbosidade)

E esse método apenas altera a possibilidade de escrita nos diretórios esse método simplesmente não causa qualquer tipo de erro, uma vez que o único software que realmente deveria escrever em /usr é o gestor de pacotes logo fora o gestor de pacotes (cujo objetivo é exatamente falhar sua execução caso tente modificar o /usr) qualquer software que falhe por escrever em /usr sem ser o gestor de pacotes provavelmente nem deveria estar em execução

Corrigido

1 curtida

Pelo menos em teoria o APT e o RPM falhaam em extrair já que listam os atributos em prerm e preinst, e é um pouco estranho você sugerir isso uma vez que mesmo sistemas que usam OverlayFS não o trazem (inspecionando o Endless.img e o source do Vanilla OS) o Vanilla OS destrava e trava (por padrão) apenas o,/bin, /lib, /lib64 e /sbin (que nas distros atuais são subdiretorios de /usr) além do próprio /usr:

Sinceramente não entendi seu ponto já que o próprio Vanilla OS faz isso (nem nenhuma outra que que eu tenha conhecimento pelo menos) talvez o Nix mas já seria exceção a regra

Cara, eu baixei e testei a iso do Vanilla OS e do Endless OS só pra verificar sua informação e elas não gerenciam:

Teste, caso queira replicar:

Aquivo .deb injetando arquivos em /var e /etc

Em nenhum dos dois falhou e em ambos os arquivos foram extraídos no caso do Endless OS, o /etc foi compartilhado entre imagens (inspecionado de fora por imagem Live), no caso do Vanilla OS não possuiu qualquer layer estando o arquivo diretamente em /etc

Imagem do Vanilla OS pode ser encontrada em CI/assets no repositório os

Em ambos o pacote .deb foi instalado por dpkg

Então sua tese de que distros imutáveis por design gerenciam isso não está totalmente correto, pelo menos nos meus testes

Não sei no caso do Arch mas comparando Vanilla OS e Ubuntu:

Mesmo em ambos criando o arquivo em nenhum ocorreu erro por reinstalação uma vez que o pacote não foi registrado no banco de dados do dpkg

No caso do Vanilla OS é ainda mais interessante porque o gestor de pacotes e atualizações dele basicamente faz o que vc disse:

Destrava o atributo
Instala os pacotes que tem que instalar
Trava novamente o atributo

Um Script shell meio simplista faria isso:

#!/bin/bash
[ ! "${EUID}" = "0"  ] && {
  echo "Execute como root"
}

find /usr -type d -exec chattr -i {} \;

apt dist-upgrade

find /usr -type d -exec chattr +i {} \;

O que causa essa impressão no caso do Vanilla OS é que ele não usa o APT por padrão, mas sim o APX que instala os pacotes em um container, caso use o APT vai ter exatamente o mesmo problema que teria sem um OverlayFS, caso use o APX no Ubuntu normal, vc também não vai ter pacotes fora de local, mas sim dentro de um container distrobox, o OverlayFS não ajuda em nada no sistema, tudo que eu disse até a compilação atual pode ser facilmente verificado

Parabéns,você é praticamente o cara que criou o Ubuntu SilverBlue hoje.
sério,sem ironia…mais uns tweaks aqui e ali,e tá pronto.
Agora eu adoraria ver uma Distro tipo um cara pegasse um Mint e colocasse nele Base Fedora ou Base Arch…seria interessante tambem.

1 curtida

O ponto de um sistema imutável não é apenas isso vai muito mais além, pensando do ponto de vista “vou instalar linux no PC da minha mãe”, essa modificação de atributos deixa ela praticamente imune a malwares, mesmo ela dando permissão não vai conseguir destruir o sistema facilmente, um ataque teria que ser feito especificamente para aquele sistema

A questão é que aparentemente nenhuma delas protege o /etc

Imutabilidade é diferente de ter um OverlayFS, tenha isso em mente, imutabilidade significa que os arquivos do sistema operacional são imutáveis

Mesmo o Arch que eu testei isso não quebra o sistema ao tentar substituir, o pacman apenas assume que aquilo é um sinal de o usuário compilou o pacote:

pacman --overwrite '/etc/*' -S nginx 

Resolve o problema, um simples alias “desquebra” o sistema

Ou compilando e instalando via make install, ou restaurando um backup de uma instalação… Eu consigo citar n jeitos de ter esse exato mesmo problema no Arch, o grande problema causado além de não desmerecer nenhum benefício de se ter um Arch imutável pode ser corrigido com um simples alias no /etc/profile, vc só pode estar de sacanagem querendo comparar algo que é literalmente plug and play, com soluções que envolvem alterar todo o filesystem o mecanismo de funcionamento do sistema sendo que todos precisam geralmente trocar de sistema pra ter o exato mesmo benefício? Vc só pode ser troll e eu besta por cair:

Característica chattr outros métodos
Plug and play, ative e desative quando quiser sim não
Não altera mecanismo base do sistema sim não
Pode ser adicionado em qualquer distro sim geralmente requer ISOs especiais ou complexos mecanismos sem garantia de sucesso
Impactos no sistema 1 linha no /etc/profile no Arch e derivados Dezenas de arquivos adicionais

Acho que temos um vencedor

1 curtida

Vc não entendeu o conceito, a camada de OverlayFS serve justamente pra deixar o sistema mutavel novamente, a ideia é ter uma base imutável e um topo mutável, nenhuma mesmo usando OverlayFS faz o que você propõe então eu realmente não entendo o seu ponto, uma camada mutável NÃO É parte da definição de um sistema imutável é um recurso que alguns sistemas imutáveis colocam, Android e Chrome OS por exemplo são imutáveis e NÃO possuem o mecanismo, pela última vez: sistemas imutáveis são sistemas onde não é possível alterar o conteúdo de determinados diretórios chave

O objetivo NÃO É fazer uma distro embora pudesse ser estendido para tal, lógica simples:

Tenho um sistema A, quero ele imutável por quaisquer motivo que seja

Porque instalar outra distro? Não faz sentido

A maioria das distros Linux imutáveis (além de novamente: não resolverem o problema que você propõe, o que me faz pensar que talvez seja algo pessoal e não técnico que esteja sendo discutido aqui) trazem outros propósitos, por exemplo o Silverblue quer testar o conceito de gerenciamento de pacotes híbrido (o que novamente foge do escopo de um sistema imutável), o Endless se propõe separar pacotes aplicativos de pacotes do sistema e atualizações atômicas (novamente diferente fugindo do escopo de sistema imutável), Vanilla OS que se propõe a trazer apps e utilitários atualizados trazendo algo híbrido de liberação fixa com atualização corrente (de novo fora do escopo de um sistema imutável)

Todas as modificações extras nesses sistemas não são apenas pra deixar o sistema imutável mas também para trazer essas e outras características que NÃO FAZEM PARTE do conceito de imutabilidade então é óbvio que a solução não vai ser tão simplista, pela última vez porque já passou de ficar chato:

Sistemas imutáveis são sistemas onde não é permitido alterar os arquivos do sistema

Essas distro fazem é trazer muitos outros conceitos associados que definitivamente não são unanimidade entre elas

E se as distros pensadas em imutabilidade NÃO RESOLVEM o problema que vc identificou na minha abordagem, sinceramente? Por que me cobra que eu resolva? E como eu disse não é tão difícil deixar /etc imutável só é maçante, mas se vc faz tanta questão, eu mostro como deixar o /etc imutável (coisa que distros pensadas em imutabilidade NÃO fazem):

find /etc -type d -exec chattr +i {} \;
find /etc -type f -exec chattr -i {} \;

Mais um ponto pro meu método: versatilidade

/etc é o sistema de registro do sistema, o GNU/Linux tem registro mas ele faz em arquivo já que o kernel Linux lida com arquivos.

1 curtida

Cara, achei essa ideia bem interessante e simples. Em alguns casos isso pode ser bastante útil. Valeu pela dica!

1 curtida

Veja o que disse o Carlos E.Morimoto criador do GNU/Linux Kurumim.

diretório “/etc” concentra os arquivos de configuração do sistema, substituindo de certa forma o registro do Windows.
A vantagem é que enquanto o registro é uma espécie de caixa preta, os scripts do diretório “/etc” são desenvolvidos justamente para facilitar a edição manual.
É verdade que na maioria dos casos isto não é necessário, graças aos vários utilitários de configuração disponíveis, mas a possibilidade continua aí.
1 curtida

Sim, o “registro” do Linux são arquivos de configuração e usualmente ficam em /etc, o /etc algum momento ganhou o nome de “Edit To Configure” por isso, mas historicamente nem sempre foi assim, lá nos tempos do Minix o /etc significava tudo que não fosse executavel, recurso estático do sistema, arquivo do usuário, dados de servidor ou biblioteca, então era fusionado com o atual /var

1 curtida