
Firewall unikernel mínimo para QubesOS que filtra tráfego de rede, implementa NAT e comunica-se via Qubes DB e qrexec.
Um unikernel que pode executar como ProxyVM do QubesOS, substituindo o sys-firewall.
Ele usa a biblioteca mirage-qubes para implementar os protocolos do Qubes.
Consulte A Unikernel Firewall for QubesOS para mais detalhes.
Binários pré-compilados estão disponíveis na página de lançamentos. Consulte a secção Implantação abaixo para instruções de instalação.
Nota: A forma mais fiável de compilar é usando Docker ou Podman. Fedora 42 funciona bem para isto; Debian 12 também funciona, mas precisará de seguir as instruções em docker.com para obter o Docker (não use a versão do Debian).
Crie uma nova AppVM Fedora-42 (ou reutilize uma existente). Nas Definições da Qube (Básico / Armazenamento de disco), aumente o tamanho máximo do armazenamento privado de 2048 MiB predefinido para 8192 MiB. Abra um terminal.
Clone este repositório Git e execute o script build-with.sh com docker ou podman como argumento (Nota: A chamada chcon é obrigatória no Fedora com as novas políticas SELinux que não permitem manter normalmente as imagens docker no diretório pessoal):
mkdir /home/user/docker
sudo ln -s /home/user/docker /var/lib/docker
sudo chcon -Rt container_file_t /home/user/docker
sudo dnf install docker
sudo systemctl start docker
git clone https://github.com/mirage/qubes-mirage-firewall.git
cd qubes-mirage-firewall
sudo ./build-with.sh docker
Ou
sudo systemctl start podman
git clone https://github.com/mirage/qubes-mirage-firewall.git
cd qubes-mirage-firewall
./build-with.sh podman
Isto levou cerca de 15 minutos no meu portátil (será muito mais rápido se o executar novamente). O passo do link simbólico no início não é necessário se a sua VM de compilação for standalone. Dá ao Docker mais espaço em disco e evita perder a cache de imagens Docker quando reinicia a Qube. Não é necessário com Podman, pois os contentores vivem no seu diretório pessoal por predefinição.
Nota: os ficheiros de objeto são armazenados no diretório _build para acelerar compilações incrementais.
Se alterar as dependências, precisará de eliminar este diretório antes de recompilar.
Não há problema em instalar o pacote Docker ou Podman numa VM de template se quiser que permaneça após um reinício, mas a compilação do firewall em si deve ser feita numa AppVM normal.
Também pode compilar sem esse script, como para qualquer unikernel Mirage normal; consulte as instruções de instalação do Mirage para detalhes.
O script de compilação fixa as versões das bibliotecas que usa, garantindo que obterá exatamente o mesmo binário que está no lançamento. Se compilar sem ele, será compilado contra as versões mais recentes (e o hash provavelmente não corresponderá). No entanto, deverá funcionar bem na mesma.
Se quiser implantar manualmente, só precisa de transferir qubes-firewall.xen e
qubes-firewall.sha256 na domU e verificar se o ficheiro .xen tem uma hashsum
correspondente. qubes-firewall.xen é o próprio unikernel e deve ser copiado para
vmlinuz no diretório /var/lib/qubes/vm-kernels/mirage-firewall na dom0, por exemplo
(se dev for a AppVM onde o compilou):
[tal@dom0 ~]$ mkdir -p /var/lib/qubes/vm-kernels/mirage-firewall/
[tal@dom0 ~]$ cd /var/lib/qubes/vm-kernels/mirage-firewall/
[tal@dom0 mirage-firewall]$ qvm-run -p dev 'cat mirage-firewall/qubes-firewall.xen' > vmlinuz
Execute este comando na dom0 para criar uma VM mirage-firewall usando o kernel mirage-firewall que adicionou acima
qvm-create \
--property kernel=mirage-firewall \
--property kernelopts='' \
--property memory=32 \
--property maxmem=32 \
--property netvm=sys-net \
--property provides_network=True \
--property vcpus=1 \
--property virt_mode=pvh \
--property audiovm='' \
--label=green \
--class StandaloneVM \
mirage-firewall
qvm-features mirage-firewall qubes-firewall 1
qvm-features mirage-firewall no-default-kernelopts 1
qvm-features mirage-firewall skip-update 1
Se estiver familiarizado com a execução de estados salt no Qubes, também pode usar o script SaltScriptToDownloadAndInstallMirageFirewallInQubes.sls para implantar automaticamente a versão mais recente do mirage firewall no seu Qubes OS. Uma introdução pode ser encontrada aqui e aqui. Seguindo as instruções do primeiro link, pode executar o script na dom0 com o comando sudo qubesctl --show-output state.apply SaltScriptToDownloadAndInstallMirageFirewallInQubes saltenv=user. O script verifica a checksum do servidor de integração e compara com a versão mais recente fornecida nos lançamentos do github. Pode ser necessário ajustar os templates de VM no script que são usados para transferir o unikernel mirage, se os seus templates predefinidos não tiverem as ferramentas curl e tar instaladas por predefinição. Também não se esqueça de alterar as VMs em que o unikernel deve ser usado ou ajustar as "Definições Globais do Qubes".
Para atualizar a partir de um lançamento anterior, basta sobrescrever /var/lib/qubes/vm-kernels/mirage-firewall/vmlinuz com a nova versão e reiniciar a VM do firewall.
Pode executar o mirage-firewall juntamente com o seu sys-firewall existente e pode escolher quais AppVMs usam qual firewall usando a GUI.
Para configurar uma AppVM para o usar, vá às definições da app VM na GUI e altere a sua NetVM de default (sys-firewall) para mirage-firewall.
Também pode configurá-lo executando este comando na dom0 (substitua my-app-vm pelo nome da AppVM):
qvm-prefs --set my-app-vm netvm mirage-firewall
Alternativamente, pode configurar o mirage-firewall para ser a sua VM de firewall predefinida.
Note que, por predefinição, a dom0 usa o sys-firewall como a sua "UpdateVM" (um proxy para transferir atualizações). O mirage-firewall não pode ser usado para isto, mas qualquer VM Linux deve servir. https://www.qubes-os.org/doc/software-update-dom0/ diz:
O papel de UpdateVM pode ser atribuído a qualquer VM no Gestor de VMs do Qubes, e não há implicações de segurança significativas nesta escolha. Por predefinição, este papel é atribuído ao firewallvm.
O OpenBSD atualmente não pode ser usado como netvm, por isso, se quiser usar um BSD como a sua VM sys-net, precisará de definir a sua netvm para qubes-mirage-firewall (consulte https://github.com/mirage/qubes-mirage-firewall/issues/146 para mais informações).
Isso significa que terá AppVMs -> qubes-mirage-firewall <- OpenBSD com a seta a representar a definição da propriedade netvm.
Nesse caso, terá de dizer ao qubes-mirage-firewall qual cliente AppVM deve ser usado como uplink:
qvm-prefs --set mirage-firewall -- kernelopts '--ipv4=X.X.X.X --ipv4-gw=Y.Y.Y.Y'
com X.X.X.X o endereço IP para o mirage-firewall e Y.Y.Y.Y o endereço IP do seu HVM OpenBSD.
Este diagrama mostra os principais componentes (cada caixa corresponde a um ficheiro fonte .ml com o mesmo nome):
As frames Ethernet chegam das qubes clientes (como work ou personal) ou do sys-net.
Os pacotes Internet (IP) são enviados para firewall, que consulta a tabela NAT e as regras do QubesDB para decidir o que fazer com o pacote.
Se deve ser reencaminhado, usa router para o enviar para o destino escolhido.
client_net observa a base de dados XenStore fornecida pela dom0
para descobrir quando os clientes precisam de ser adicionados ou removidos.
O processo de arranque:
config.ml descreve as bibliotecas usadas e as definições de configuração estática (tamanho da tabela NAT).
A ferramenta mirage usa isto para gerar main.ml.main.ml inicializa os drivers selecionados por config.ml
e chama a função start em unikernel.ml.unikernel.ml liga os agentes do Qubes, configura os componentes de rede,
e depois aguarda um pedido de encerramento.Para desenvolvimento, use os scripts test-mirage para implantar o unikernel (qubes-firewall.xen) a partir da sua AppVM de desenvolvimento.
Isto requer um pouco mais de configuração na primeira vez, mas será muito mais rápido depois disso. Por exemplo:
[user@dev ~]$ test-mirage dist/qubes-firewall.xen mirage-firewall
Waiting for 'Ready'... OK
Uploading 'dist/qubes-firewall.xen' (7454880 bytes) to "mirage-test"
Waiting for 'Booting'... OK
Connecting to mirage-test console...
Solo5: Xen console: port 0x2, ring @0x00000000FEFFF000
| ___|
__| _ \ | _ \ __ \
\__ \ ( | | ( | ) |
____/\___/ _|\___/____/
Solo5: Bindings version v0.7.3
Solo5: Memory map: 32 MB addressable:
Solo5: reserved @ (0x0 - 0xfffff)
Solo5: text @ (0x100000 - 0x319fff)
Solo5: rodata @ (0x31a000 - 0x384fff)
Solo5: data @ (0x385000 - 0x53ffff)
Solo5: heap >= 0x540000 < stack < 0x2000000
2022-08-13 14:55:38 -00:00: INF [qubes.rexec] waiting for client...
2022-08-13 14:55:38 -00:00: INF [qubes.db] connecting to server...
2022-08-13 14:55:38 -00:00: INF [qubes.db] connected
2022-08-13 14:55:38 -00:00: INF [qubes.db] got update: "/mapped-ip/10.137.0.20/visible-ip" = "10.137.0.20"
2022-08-13 14:55:38 -00:00: INF [qubes.db] got update: "/mapped-ip/10.137.0.20/visible-gateway" = "10.137.0.23"
2022-08-13 14:55:38 -00:00: INF [qubes.rexec] client connected, using protocol version 3
2022-08-13 14:55:38 -00:00: INF [unikernel] QubesDB and qrexec agents connected in 0.041 s
2022-08-13 14:55:38 -00:00: INF [dao] Got network configuration from QubesDB:
NetVM IP on uplink network: 10.137.0.4
Our IP on uplink network: 10.137.0.23
Our IP on client networks: 10.137.0.23
DNS resolver: 10.139.1.1
DNS secondary resolver: 10.139.1.2
2022-08-13 14:55:38 -00:00: INF [net-xen frontend] connect 0
2022-08-13 14:55:38 -00:00: INF [net-xen frontend] create: id=0 domid=1
2022-08-13 14:55:38 -00:00: INF [net-xen frontend] sg:true gso_tcpv4:true rx_copy:true rx_flip:false smart_poll:false
2022-08-13 14:55:38 -00:00: INF [net-xen frontend] MAC: 00:16:3e:5e:6c:00
2022-08-13 14:55:38 -00:00: INF [ethernet] Connected Ethernet interface 00:16:3e:5e:6c:00
2022-08-13 14:55:38 -00:00: INF [ARP] Sending gratuitous ARP for 10.137.0.23 (00:16:3e:5e:6c:00)
2022-08-13 14:55:38 -00:00: INF [ARP] Sending gratuitous ARP for 10.137.0.23 (00:16:3e:5e:6c:00)
2022-08-13 14:55:38 -00:00: INF [udp] UDP layer connected on 10.137.0.23
2022-08-13 14:55:38 -00:00: INF [dao] Watching backend/vif
2022-08-13 14:55:38 -00:00: INF [memory_pressure] Writing meminfo: free 20MiB / 27MiB (72.68 %)
Um unikernel que testa o firewall está disponível no subdiretório test/.
Para o usar, execute test.sh e siga as instruções para configurar o ambiente de teste.
Consulte problemas marcados com "security" para avisos de segurança que afetam o firewall.
Consulte LICENSE.md