Estou usando o FreeBSD 11.2 no momento (provavelmente passarei para o 12 daqui a pouco). Eu preciso de um pequeno servidor DNS autoritativo (sem necessidade de pesquisa ou armazenamento em cache, menos de 10 domínios e menos de 10 consultas/hora, quase sem alterações de registro).
É provável que eu vá com TinyDNS
, parte do djbdns
, que é bem conhecido pela segurança e também parece mínimo e faz o que eu preciso.
Parte do motivo da segurança é que ele será exposto à internet, embora por trás de um filtro de IP/porta e taxa muito baixa, limitador de taxa (usando pf
para isso). Mas, por esse motivo, quero ter um cuidado especial com a configuração do daemon, para evitar vulnerabilidades óbvias. Com isso, quero dizer aspectos como os usuários e grupos necessários, scripts de início/parada, jail/chroot e minimização/desativação/negação dos principais acessos/recursos não essenciais que um invasor poderia pivotar.
(Devo mencionar que posso instalar o tinydns "normalmente" em um sistema de teste e criar o .conf
arquivo necessário, então é puramente como executá-lo de maneira segura, o que está faltando)
Não tenho experiência em configurar software para executar chroot/jailed, ou revisar um pacote chrooted/jailed para práticas de segurança apropriadas, e esta também será a primeira vez que tento fazer algo assim, embora eu tenha escolhido o Pacote de servidor DNS especificamente por sua aparente simplicidade de configuração.
Ignorando o .conf
arquivo, como seria uma "receita" para configurar o TinyDNS para funcionar corretamente como um serviço e, idealmente, com acesso minimizado a "outras coisas não essenciais para o daemon, mas úteis para um invasor"?
Isso é bastante longo, então a versão muito curta para aqueles que não podem se incomodar em ler tudo:
Eu normalmente classificaria esta pergunta como "muito ampla" e encaminharia as pessoas diretamente para o Manual do FreeBSD . Mas eu mesmo acho essa seção muito mal escrita e confusa. Está tudo lá - mas as coisas são muito mais fáceis do que parecem! Eu só gostaria que eles se concentrassem mais nos conceitos em vez de listar os comandos. E você pode se divertir lendo Jails – Virtualização de alto valor, mas uma merda
O que farei em vez disso é descrever humildemente o que faço pessoalmente e quais obstáculos encontrei. Minhas falhas podem não ser suas, mas como eu já estive na mesma situação que você, espero que minha jornada possa ajudar. Quanto melhor você entender o FreeBSD em geral, mais fáceis serão as prisões.
O que é uma prisão?
Muitas descrições encobrem a parte importante do que é uma prisão. Ajuda imensamente entender o que o kernel faz. Ele "executa" o código e acompanha o PID (ID do processo) e o UID (ID do usuário). Este é então um conhecimento comum para muitos usuários de Unix. O kernel do FreeBSD então adicionou o conceito de JID (Jail ID). O kernel é então capaz de particionar processos em jails. Isso significa que o kernel do FreeBSD é capaz de "virtualizar" sistemas sem nenhuma sobrecarga. Você ainda tem apenas um kernel, mas pode ter vários sistemas. Isso foi fundamental para minha compreensão do conceito.
Se você executar uma caixa de baunilha "sem" jails. Então todos os processos pertencem ao JID 0. Quando você começa a jogar com jails nós chamamos isso de "jail host".
Com isso em mente, o próximo passo para mim foi entender a conexão com como o FreeBSD realmente funciona. Se você tem experiência com Linux, provavelmente sabe que o Linux é "apenas" o kernel. O que faz o sistema é então a área de usuário fornecida com a distribuição (Ubuntu, Debian, Slackware etc.). O FreeBSD é a combinação do kernel e do userland. É o sistema operacional completo (sistema operacional).
Portanto, um resumo muito grosseiro do Capítulo 12. O processo de inicialização do FreeBSD é:
Você pode saber como o FreeBSD é modular e que você pode substituir o sistema rc por algo como o OpenRC , mas ignoramos isso por enquanto para mantê-lo simples.
Quando você inicia (inicializar) uma jail, o kernel então inicia com um novo JID (ou seja, 1). Tudo aqui é então confinado à prisão 1. O que o init precisa tocar deve estar dentro do sistema de arquivos chroot'ed. Se você quiser manter as coisas simples, essa é a área de usuário completa . Mas queremos manter a prisão separada do sistema host, então esta é uma cópia completa do userland!
A importância de como essas coisas estão interconectadas não pode ser subestimada. Quando você grok completamente, você notará que as jails são suportadas diretamente por muitas ferramentas do FreeBSD. Não apenas coisas simples como
ps -J
masbsdinstall
,freebsd-update
epkg
! Se manter um sistema FreeBSD é uma segunda natureza para você, então as prisões serão um passeio no parque!Mas para a maioria de nós estamos em algum lugar no meio desse caminho para o Nirvana e podemos ter que lutar com alguns dos conceitos para fazê-lo "certo".
hier
Eu sou um grande fã dele . Dá uma visão clara e consistente sobre onde as coisas devem ser colocadas. Infelizmente, os poderes que nunca tomaram nenhuma decisão sobre qual seria um bom local padrão para prisões. Quando você combina isso com muitos tutoriais diferentes que usam locais diferentes e misturam vários jargões como "instalação básica" e "modelos", as coisas ficam confusas rapidamente!
O Manual não discute isso e apenas se refere a
/here/is/the/jail
. E no exemplo final eles usam/home/j
e/home/j/mroot
. Eu prefiro manter diretórios de usuários e apenas diretórios de usuários em arquivos/home
. E simplesmente usar uma notação abreviada comoj
é um grande não-não no meu livro.Eu diria que o local mais comum e "correto" usado é
/usr/local/jails
. Um forte concorrente principalmente para pessoas que usam ZFS é/jails
Neste local eu colocaria os chroots para minhas prisões. Assim tenho falado. As prisões de Forte serão encontradas aqui.
Achei isso muito confuso quando comecei. Dar-me liberdade para colocá-lo em qualquer lugar me deixou mais insegura, pois não entendia as consequências.
Para aumentar essa confusão, muitos tutoriais estavam usando "basejail", "diretórios de esqueleto", "modelos". Isso aumentou a confusão do que realmente é uma prisão e a confundiu com muito gerenciamento.
Sistema de arquivo
Nós realmente não nos importamos com o sistema de arquivos que estamos usando. Pode ser UFS ou ZFS. Por causa da jail, precisamos apenas de um diretório para nosso chroot.
Ao usar o UFS, o importante a observar é como você organizou suas fatias. O iniciante muitas vezes não deu tanta atenção. Qual fatia tem espaço suficiente para acomodar os chroots. É por isso que eu especificamente não gosto de usar
/home
para essa finalidade. Talvez você crie uma fatia para esse propósito ou apenas crie um diretório em algum lugar e depois descubra se tem espaço suficiente.Se você estiver usando o ZFS, os problemas são realmente os mesmos. Devido à forma como o ZFS está estruturado, você pode argumentar que é melhor criar um novo conjunto de dados do que apenas fazer
mkdir
. Mas para o iniciante você não deve se preocupar. Fazer um ´mkdir´ com ZFS é melhor para você. Isso torna as coisas mais simples e você pode seguir em frente sem o ZFS.O próximo problema é que muitos tutoriais também operam com um "basejail" que é um sistema vanilla completo pronto para copiar para criar uma nova jaula. Alguns tutoriais lhe dirão para fazer um clone do ZFS em vez de fazer uma cópia. De longe, você atualizará o basejail e, naturalmente, fará instantâneos dele. Mas então você percebe que não pode excluir nenhum instantâneo que tenha clones deles. Então, no uso real, prefiro usar zfs send/receive.
Na minha opinião, os tutoriais só devem tocar no ZFS como um adendo. O ZFS é um tópico enorme por si só e deve ser tratado assim. Quando você estiver confortável com as prisões e o ZFS, poderá combinar o conteúdo do seu coração e colher os benefícios. Caso contrário, você acaba construindo uma torre muito frágil, sem nenhuma capacidade de consertar as coisas quando elas quebram.
gordo/grosso vs magro
O Manual do FreeBSD fala sobre jails “completas” e jails de “serviço”. A maioria dos outros lugares usa os termos cadeias grossas (gordas/completas) e finas. As jaulas grossas e finas são ambos sistemas FreeBSD virtualizados "completos" que o Manual do FreeBSD chama de jaulas "completas". A prisão de "serviço" é, no entanto, muito mais evasiva
Uma prisão espessa é então uma cópia do sistema operacional completo. Mas quanta gordura é essa? O FreeBSD 11.2 com base/lib32/ports pesa 1,4G, mas para uma prisão, "base" sozinha provavelmente o manteria em 512M relativamente esbeltos (comparado com os 20G de C:\Windows para Windows 10).
Uma prisão fina é então um saco de truques para minimizar o uso em disco de uma prisão "completa". Ao usar nullfs (uma subárvore do sistema de arquivos de loopback) para montar um sistema de arquivos somente leitura e alguns links simbólicos bem colocados para habilitar partes de leitura/gravação, você reduz o uso do disco. Infelizmente não tenho nenhum número em mãos. Quando você tiver a estrutura em disco, basta adicionar
mount.fstab
ao seujail.conf
para montar o sistema de arquivos ao iniciar a prisão.Eu tenho as idéias de como fazer isso do FreeBSD Jails da maneira mais difícil . Isso me ensinou a lidar com jails sem nenhum utilitário de terceiros e finalmente fez as peças clicarem para mim. E apesar do título - é realmente o caminho mais fácil. No entanto, eles erraram uma coisa. Você não deve fazer um clone do zfs, mas sim um envio/recebimento do zfs descrito em Unadlterated Jails, the Simple Way . Ambos provavelmente encontraram inspiração nas Jails Múltiplas do FreeBSD ligeiramente desatualizadas com nullfs . Outra fonte que vale a pena é o FreeBSD Thin Jails . Finalmente, uma fonte mais recente que também cobre VNET (voltaremos a isso!) é Como configurar uma Jail do FreeBSD com vnet e ZFS
O acima é comumente referido como uma prisão fina, mas pode ser feito de outras maneiras . Todos os caminhos levam a Roma e você decide por si mesmo como deseja implementá-lo localmente.
Tudo isso nos leva à elusiva prisão "de serviço". Uma prisão que executa apenas um serviço específico no cenário mais bloqueado. Apenas a aplicação real e apenas uma camada fina para apoiá-la. Isso pode ser feito, mas eu não vi muito trabalho sobre isso.
O típico
jail.conf
conteria:Isso é o que garante que o sistema rc execute uma prisão quando iniciar/parar. Se você tiver um executável extremamente simples, basta apontar para ele. Portanto, a pergunta é: a quanto do sistema operacional meu serviço precisa acessar? Quais bibliotecas compartilhadas são necessárias e você executa scripts?
Não conheço nenhum trabalho que tenha feito isso por você. Então você começa com uma prisão completa e depois remove o que não é necessário para o seu serviço específico. Muitos utilitários de linha de comando, como
top
,ps
etail
são seguros para remover, pois normalmente não são usados por um daemon. Mas você pode perdê-los se estiver depurando dentro da prisão. Se você iniciar um daemon diretamente comexec.start
você não precisarc.subr
e amigos.Se você seguir esse caminho e iniciar uma matança para determinar quanto pode ser removido do sistema operacional (para reduzir a superfície de ataque) enquanto o serviço permanece funcional, você deve estar ciente do nanobsd . Isso pode ajudá-lo a adaptar a instalação às suas necessidades.
Então - definitivamente factível. Mas não conheço nenhuma obra pública. A maioria das pessoas vai com prisões grossas ou finas e apenas executa seu serviço designado lá.
Inferno de dependência
Ao fazer jails finas, você precisa ter muito cuidado para fazer tudo corretamente ou as coisas vão quebrar. Ao atualizar o sistema, você precisa se lembrar de atualizar todas as diferentes partes. O basejail ou fontes de onde você começou. Os modelos e as prisões reais. Isso é um monte de rodas em movimento, o que torna o gerenciamento mais difícil. Isso pode ser feito, mas você deve pesar o esforço contra o prêmio. O espaço em disco é muito barato - então você precisaria de alguns serviços para fazer valer a pena o esforço.
Eu recomendaria, então, ter prisões simples e gordas com um sistema operacional completo.
Se você está muito confortável com o ZFS, então vá à loucura. Mas se não, sugiro fortemente ter o chroot em um diretório simples. Quando você se sentir confortável trabalhando com uma prisão, então você pode começar a adicionar o creme.
A chave é então tratar a prisão como um sistema separado. Se você mantiver seu sistema corretamente hoje você já deve ter o hábito de usar
freebsd-update fetch install
e saberá que ele atualiza o kernel e a userland.Ao adicionar jails ao mix, você só precisa se lembrar de atualizá-los também:
Se você estiver fazendo atualizações - lembre-se também das prisões:
Da mesma forma que você mantém seus pacotes frescos
E aí cara! Eu só queria prender um serviço!
OK! Com todos os emptores de advertência, vamos fazer isso da maneira mais fácil em um sistema totalmente vanilla. TinyDNS é um mau exemplo, então vamos instalar o nginx
/etc/jail.conf
lib32
/ports
)nginx
o pacote à jaula.Feito!
1 e 2 apenas para se preparar para as prisões. 3 - 6 para cada nova prisão. 7 - 9 para cada serviço.
Isso é o que eu diria ser a maneira "correta" de fazer uma prisão e um gerenciamento simples. Existem muitas variações - a última linha pode ser substituída por
service jail restart testjail
. Neste ponto, sou capaz de navegar na página da Web na minha instância nginx presa.Alguns padrões do FreeBSD não se prestam tão bem às prisões. Portanto, considere defini-los também:
Remover uma prisão
Para excluir uma prisão:
O acima é para mostrar que não é difícil gerenciar jails com as ferramentas em mãos e sem a necessidade de uma ferramenta de gerenciamento de jail de 3ª parte.
E aí cara! Eu só queria prender TinyDNS!
Você escreve que pode instalar o tinydns "normalmente" - portanto, deixarei isso para você. Para outros que possam estar seguindo, eles provavelmente imaginariam que deveria ser tão simples quanto:
Mas quem criou esse pacote não foi legal o suficiente para criar um wrapper de serviço para tinydns em
/usr/local/etc/rc.d
. Você então precisa descobrir como executá-lo como um daemon. Você pode optar por usar o gerenciamento de serviço alternativo, como supervisor ou um hack simples, adicionando-o ao /etc/rc.local . Ou para pontos de brownie, crie um script rc e contribua de volta para todos nós aproveitarmos!Isso nos leva aos dois únicos comandos específicos de jail que você realmente precisa saber: jls que lista as jails em execução e jexec que permite que você execute coisas dentro da jail.
Para obter uma linha de comando como root, simplesmente executamos o shell root (lembre-se que é tcsh!)
Ao trabalhar dentro desse shell, tudo está dentro do seu jail/chroot.
O que não te contam!
Até agora não me afastei muito do que a maioria dos tutoriais lhe dirá. Depois de perder muito tempo no sistema de arquivos, eles pulam a parte emocionante. Hoje não há muita diversão com computadores sem acesso à rede. No exemplo acima, compartilhamos a pilha de rede com o host. Isso significa que você não pode executar nada no host da jail que utilize as mesmas portas que uma jail. No meu exemplo, esta era a porta 80 para o servidor web.
Por outro lado, agora é muito fácil configurar um firewall. Você simplesmente trata todas as portas como locais. Se você estiver usando IPv6, as coisas são fáceis. Mas a maioria (todos?) de nós ainda precisa lutar com o IPv4. O IPv4 é bastante simples, mas você provavelmente não tem os endereços que precisa e então precisamos recorrer a algum tipo de NAT.
If you want to get really fancy with networking we have virtual network interfaces VNET. It has matured over the years but to use it you need to compile a kernel with VIMAGE support. This is enabled in the generic kernel from FreeBSD 12.0 and onwards.
When using VNET you have a nice virtual interface where you can run your firewall inside the jail.
I do currently not use VNET as a unified firewall on the jail host is enough for me and what I want. With this I control which traffic goes to and from the jail. This makes it even harder break things from the jail.
On the jail host I often allow some outbound traffic (http/ftp/nameresolution). But all traffic in my jails I specifý exactly which ports are allowed in both directions and between jails.
The trick is to move the traffic to another interface. The local loopback interface
lo0
is a great candidate. But to keep the rules better seperated it is even better to clone it to a new interface namelo1
. You can set this up and prepopulate the IP addresses for this in the jail host usingifconfig
. There is however no need as the jail subsystem handles all this for you automatically.To do this our
/etc/jail.conf
now looks like this:Notice how
ip4/6 = inherit;
has changed tointerface="lo1"
. Notice alsomount.fstab
- this is how I add my nullfs mounts but I will not go further into this now. Then I have added the internal IP I want to use to testjail.We then clone the by adding
lo1
to/etc/rc.conf
:You need to reboot for this. If you want to try it out now without a reboot you need to create the interface yourself:
This has the same effect as setting
cloned_interfaces="lo1"
in/etc/rc.conf
. You do not need to create aliases for the IP addresses as this is handled automaticly when the jail starts.This is however boring as traffic gets nowhere.
To get the traffic going we need to set up the firewall and get some NAT going. My poison of choice is pf. You have your ruleset in
/etc/pf.conf
To NAT from the outside to a jail IP for http do like this:
Many services do not like to start if they are not able to connect to themselves. Hence I add a rule for that as well.
The NAT rule is only needed if you want someone from the outside to connect. When you start to have multiple jails you often just want one jail to be able to connect to another.
With these simple firewall setting you can have a very nice network isolation between your jails and the outside.
Summary
From what I have experienced myself I would suggest the following path to understand how to use jails:
That is my recipe. Probably not quite what you hoped for :-)
If you do not want to handle the gritty bits with the supplied tools then have a look at some of the 3rd party tools:
Bastille
ezjail
iocage
From all this you can see that your question was rather broad and depends heavily on your preferred setup. I believe I have shown a receipe for a well behaved package such as
nginx
but maybe you need to ask some other questions:But then I would leave the jail parts out of it.