Usando Mandos com OpenVPN para decriptar Linux com LUKS

mandos-client_1.7.15-1_amd64.debVocê quer proteger o HD de seu computador ou servidor Linux totalmente com criptografia. Para isso, você faz uma FDE (Full Disk Encryption/Encriptação Completa de Disco) do tipo LUKS (Linux Unified Key Setup). Então toda vez que este computador for desligado e reiniciado você precisará digitar pelo teclado a senha para decriptar o HD.

Isso é um problema. E se este computador for um servidor? E se você não tiver sempre próximo para digitar a senha todas as vezes que o computador desligar ou reiniciar?

Pra isso existe um programa chamado Mandos. O Mandos são 2 softwares:

  • Mandos Client - para ser instalado no computador encriptado
  • Mandos Server - para ser instalado num servidor (que precisa estar sempre ligado) que enviará a senha para decriptar os Mandos Clients

Quando você encripta um computador Linux usando o LUKS, ao ligá-lo ele inicia um mini Linux chamado initramfs. Esse initramfs cria a tela para digitarmos a senha e decriptar o HD. Ao instalar o Mandos Client normalmente no seu Linux (via apt install mandos-client) ele também será instalado no initramfs. No momento em que o computador for reiniciado, ele procurará um Mandos Server na rede e pedir para ele a senha para decriptar o HD.

Em meu caso, não tenho certeza de como é a infraestrutura do lugar onde o computador com Mandos Client será instalado. Para driblar isso preciso que o OpenVPN inicie junto com Mandos. O Mandos por si só não é suficiente. O envio da chave entre o Mandos Client e o Mandos Server é encriptado, porém

Este tutorial foi feito em um Ubuntu Server 18.04 x64 (mas também deve funcionar normalmente em x32)

Instalando e configurando o Mandos Client

Antes de instalar o Mandos Client é interessante instalar um pacote gerador de números randômicos, isso agilizará a instalação Mandos Client. A que sugiro é a haveged, ela é leve e razoavelmente randômica para computadores sem hardware especial para gerar números randômicos. O sugerido por Boyeau é a rng-tools, é uma biblioteca muito pesada, ocupa aproximadamente 120mb de disco e é o software padrão do Linux para gerar números randômicos gerados por hardware (ou seja, você precisa de uma placa/usb geradora de números randômicos para usar a rng-tools apropriadamente).

[code lang="bash"]# Para instalar o rng-tools:#sudo apt-get install rng-tools#sudo rngd -r /dev/urandom# Para instalar o havegedsudo apt install haveged -y[/code]

Instalando o Mandos Client

[code lang="bash"]#No Ubuntu 16.04 não funciona, instalar o pacote manualmente#sudo apt install mandos-clientsudo dpkg -i mandos-client_1.7.15-1_amd64.deb#Para corrigir erros de dependênciasudo apt -f install[/code]

O pacote presente no repositório do Ubuntu 16.04 está com problemas, então o autor do blog Boyeau compilou uma versão mais atualizada e funcional que fé este aqui: mandos-client_1.7.15-1_amd64.deb

Agora é preciso gerar o certificado do cliente. Esse certificado é gerado pelo Mandos Client mas deverá ser transferido ao Mandos Server. Esse certificado faz com que o Server confie no Client e envie a senha para ele com segurança.

[code lang="bash"]sudo mandos-keygen --password --type RSA --force[/code]

Usando o Mandos Client para iniciar uma conexão com a internet usando DHCP (caso queira definir o IP do servidor manualmente)

Isso é importante porque para nos conectarmos à rede OpenVPN precisamos de conexão com a internet. O seguinte script faz o computador se conectar a rede automaticamente para nós.

*** Pelos testes que fiz, o DNS não funciona direito! ***

[code lang="bash"]sudo nano /etc/mandos/network-hooks.d/ethernet-interface-hook[/code]

Nele coloque o seguinte script:

[code lang="bash"]#!/bin/sh## This is an example of a Mandos client network hook. This hook# brings up an interface as specified in a separate# configuration file. To be used, this file and any needed# configuration file(s) should be copied into the# /etc/mandos/network-hooks.d directory.## Copying and distribution of this file, with or without modification,# are permitted in any medium without royalty provided the copyright# notice and this notice are preserved. This file is offered as-is,# without any warranty.# Exit immediately if a command exits with a non-zero statusset -edo_start(){ip link set enp1s0 upsleep 10ipconfig -c dhcp -d enp1s0sleep 10}do_stop(){ip link set enp1s0 down}case "${MODE:-$1}" instart|stop)do_"${MODE:-$1}";;esac[/code]

Esse script utiliza o software ipconfig para fazer a conexão com DHCP (quem disse que o Linux não tem ipconfig?). Acredito que a documentação é esta aqui. E possivelmente o código fonte é este aqui.

Veja abaixo como configurar um IP por DHCP ou estático

[code language="bash"]#Modelo da configuração de IP estático no ipconfigipconfig endereco_ip:dns_server:gateway:netmask:interface:proto#Exemplo da configuração com IP estáticoipconfig -d enp0s3 192.168.1.200:8.8.8.8:192.168.1.1:255.255.255.0:enp0s3:none#Exemplo da configuração com IP DHCPipconfig -c dhcp -d enp0s3[/code]

Usando o Mandos Client para inserir o OpenVPN no initramfs

Até poderíamos inserir o OpenVPN por fora do Mandos no initramfs, mas pode ser um pouco complexo. Por sorte, o Mandos Client têm um facilitador, ele também nos deixa definir hooks de instalação no initramfs. Se usarmos o Mandos para isso, também teremos controle da ordem em que os scripts serão iniciados, o que é bom pois evita erros.

Descobri o script na documentação que é instalada junto com o Mandos. Há alguns outros exemplos de scripts na pasta. Caso tenha interesse de criar o seu ou fazer modificações, é só abrir:

[code language="bash"]cd /usr/share/doc/mandos-client/examples/network-hooks.d[/code]

Voltando à configuração, crie um gancho de rede (network hook) chamado openvpn:

[code lang="bash"]sudo nano /etc/mandos/network-hooks.d/openvpn[/code]

Coloque o seguinte script:

[code lang="bash"]#!/bin/sh## This is an example of a Mandos client network hook. This hook# brings up an OpenVPN interface as specified in a separate# configuration file. To be used, this file and any needed# configuration file(s) should be copied into the# /etc/mandos/network-hooks.d directory.## Copyright © 2012-2018 Teddy Hogeborn# Copyright © 2012-2018 Björn Påhlsson## Copying and distribution of this file, with or without modification,# are permitted in any medium without royalty provided the copyright# notice and this notice are preserved. This file is offered as-is,# without any warranty.set -eCONFIG="openvpn.conf"# Extract the "dev" setting from the config fileVPNDEVICE=`sed -n -e 's/[[:space:]]#.*//' \-e 's/^[[:space:]]*dev[[:space:]]\+//p' \"$MANDOSNETHOOKDIR/$CONFIG"`echo "$MANDOSNETWORKHOOKDIR"echo "$CONFIG"PIDFILE=/run/openvpn-mandos.pid# Exit if no device set in configif [ -z "$VPNDEVICE" ]; thenexitfi# Exit if DEVICE is set and it doesn't match the VPN interfaceif [ -n "$DEVICE" ]; thencase "$DEVICE" in*,"$VPNDEVICE"*|"$VPNDEVICE"*) :;;*) exit;;esacfiopenvpn=/usr/sbin/openvpndo_start(){echo "Starting OpenVPN""$openvpn" --cd "$MANDOSNETHOOKDIR" --daemon 'OpenVPN(Mandos)' --writepid "$PIDFILE" --config "$CONFIG"sleep "$DELAY"}do_stop(){PID="`cat \"$PIDFILE\"`"if [ "$PID" -gt 0 ]; thenecho "Killing OpenVPN process"kill "$PID"echo "OpenVPN process killed"fi}case "${MODE:-$1}" instart|stop)do_"${MODE:-$1}";;files)echo "$openvpn";;modules)echo tun;;esac[/code]

Coloque o arquivo de configuração da conexão do OpenVPN:

[code lang="bash"]sudo mv seu-arquivo-vpn.conf /etc/mandos/network-hooks.d/openvpn.conf[/code]

Mude a permissão do arquivo openvpn, permitindo que ele possa ser executado:

[code lang="bash"]sudo chmod 660 /etc/mandos/network-hooks.d/openvpn[/code]

Atenção! Prefira colocar o IP de seu servidor VPN ao invés do DNS. Nos testes que fiz, o DNS não funciona no initramfs do Ubuntu 16.

Inserindo o IP no initramfs para permitir que o OpenVPN funcione

O OpenVPN usa o comando IP para criar e destruir interfaces de rede. Este comando não vem por padrão dentro do initramfs, por isso, é preciso colocá-lo à mão. Para isso, basta criar um "hook" do initramfs, que nada mais é um script em bash que é executando quando a imagem do initramfs é gerada pelo comando update-initramfs -u. A pasta /etc/initramfs-tools/hooks é onde o Ubuntu guarda por padrão os scripts do usuário que serão executados na hora de montar a imagem initramfs. Crie um novo hook chamado ip-hook digitando:

[code lang="bash"]sudo nano /etc/initramfs-tools/hooks/ip-hook[/code]

Com esse comando você criará um arquivo chamado ip-hook. Coloque nele o seguinte script bash:

[code lang="bash"]#!/bin/bash -e# Copy the compatibility symlinks until initramfs-tools will be converted# to use the ip program.if [ "$1" = "prereqs" ]; then exit 0; fi. /usr/share/initramfs-tools/hook-functionscopy_exec /sbin/ip[/code]

Agora mude a permissão do arquivo e permita que ele seja executado pelo root ou pelo seu grupo:

[code language="bash"]sudo chmod 550 /etc/initramfs-tools/hooks/ip-hook[/code]

Agora você já poderia atualizar a imagem do initramfs. Mas como ainda serão feitas mudanças no initramfs, vale a pena esperar mais um pouco, vamos às configurações do Mandos Client.

Configurando o Mandos Client

O mandos tem 2 arquivos de configuração.

O plugin-runner.conf para definir os parâmetros de inicialização do Mandos quando estiver em initramfs, é principalmente usado para definir um IP estático de um Mandos Server.

Para editá-lo:

[code language="bash"]sudo nano /etc/mandos/plugin-runner.conf[/code]

O plugin-runner.conf te permite escolher os parâmetros de inicialização do mandos client. A lista completa destes parâmetros está aqui. Vamos ao conteúdo do arquivo:

[code language="bash"]#Caso queira que mensagens de debug#apareçam no initramfs#--options-for=mandos-client:--debug#Caso queira que o mandos se conecte#num servidor com IPV6 estático--options-for=mandos-client:--connect=bddd::1234:5555#Onde o bddd::1234 é o IPV6 do servidor#E o 5555 é a porta onde o Mandos Server está escutando[/code]

O arquivo de configuração do Mandos Client.

[code language="bash"]sudo nano /etc/mandos/mandos.conf[/code]

Atualizando a initramfs

Atualize a imagem do initramfs digitando:

[code lang="bash"]sudo update-initramfs -u[/code]

Observe a saída do comando. Pode demorar um pouco, a imagem estará sendo montada. Se não ocorrer erros, tudo jóia. Se ocorrer alguma mensagem de erro, pela experiência que tive, os casos podem ser o seguinte:

  • Erro de programação do script
  • Binários usados nos scripts não existem na imagem do initramfs
  • Dependências dos binários não encontradas

Pronto, toda vez que o computador for reiniciado, o initramfs vai iniciar, criar uma conexão DHCP, iniciar o cliente OpenVPN e pedir a senha para o Mandos Server.

Instalando e configurando o Mandos Server

Instalando o Mandos Server

[code language="bash"]sudo apt install mandos[/code]

Configurando o Mandos Server

Usando o Mandos Server

Verificando o estado das conexões

Verificando o estado atual das conexões e quanto tempo falta para elas serem desativadas

[code lang="bash"]sudo mandos-monitor[/code]

Verificando as senhas dos computadores que o Mandos Server está controlando

[code lang="bash"]sudo mandos-ctl[/code]

Habilitando um computador que foi desativado por timeout

[code lang="bash"]sudo mandos-ctl -e nome_do_computador[/code]

Testando conectividade entre o Mandos Client e o Mandos Server

Quando o computador com encriptação LUKS é ligado, ele executa um programa que faz solicitação de senhas ao(s) servidor(es) Mandos. Você pode simular esta solicitação para verificar e solucionar erros de conexão de rede do Mandos Client com o Mandos Server.

Se o seu servidor está configurado para zeroconf

basta usar o seguinte comando:

[code language="bash"]#O retorno desse comando poderá ser:# a senha de decriptação, caso tudo ocorra bem# ficar em branco por algum tempo, enquanto o programa tenta localizar os servidores# um erro, indicando qual o motivo de não ter conseguido se conectar com os servidores mandossudo /usr/lib/x86_64-linux-gnu/mandos/plugins.d/mandos-client --pubkey=/etc/keys/mandos/pubkey.txt --seckey=/etc/keys/mandos/seckey.txt; echo#Caso queira mais informações sobre os erros, você pode informar na chamada o --debug#com isso, várias mensagens serão mostradas na tela, mostrando cada passo das tentativas de conexãosudo /usr/lib/x86_64-linux-gnu/mandos/plugins.d/mandos-client --pubkey=/etc/keys/mandos/pubkey.txt --seckey=/etc/keys/mandos/seckey.txt --debug; echo[/code]

Se o seu servidor está configurado para IPV6 direto com link global unicast

basta usar o mesmo comando (do zeroconf) adicionado do IPV6 pelo argumento --connect=IPV6_DO_MANDOS_SERVER:PORTA_DO _MANDOS_SERVER

[code language="bash"]#Exemplo de comando genérico para IPV6 com link globalsudo /usr/lib/x86_64-linux-gnu/mandos/plugins.d/mandos-client --pubkey=/etc/keys/mandos/pubkey.txt --seckey=/etc/keys/mandos/seckey.txt --connect=[ServerIP]:[ServerPort]; echo#Exemplo de comando com IPV6 com link globalsudo /usr/lib/x86_64-linux-gnu/mandos/plugins.d/mandos-client --pubkey=/etc/keys/mandos/pubkey.txt --seckey=/etc/keys/mandos/seckey.txt --connect=fdaa::1234:1234; echo#Exemplo de comando com IPV6 e porta de exemplo e debugsudo /usr/lib/x86_64-linux-gnu/mandos/plugins.d/mandos-client --pubkey=/etc/keys/mandos/pubkey.txt --seckey=/etc/keys/mandos/seckey.txt --connect=fdaa::1234:1234 --debug; echo[/code]

Se o seu servidor está configurado para IPV6 direto com link local

basta usar o mesmo comando (do link global unicast), informando também a interface de rede pelo argumento --interface=INTERFACE

[code language="bash"]#Exemplo de comando genérico para IPV6 com link localsudo /usr/lib/x86_64-linux-gnu/mandos/plugins.d/mandos-client --pubkey=/etc/keys/mandos/pubkey.txt --seckey=/etc/keys/mandos/seckey.txt --connect=[ServerIP]:[ServerPort] --interface[Interface]; echo#Exemplo de comando para IPV6 com link localsudo /usr/lib/x86_64-linux-gnu/mandos/plugins.d/mandos-client --pubkey=/etc/keys/mandos/pubkey.txt --seckey=/etc/keys/mandos/seckey.txt --connect=fe80::1234:1234 --interface=enp0s3; echo#Exemplo de comando para IPV6 com link local e debugsudo /usr/lib/x86_64-linux-gnu/mandos/plugins.d/mandos-client --pubkey=/etc/keys/mandos/pubkey.txt --seckey=/etc/keys/mandos/seckey.txt --connect=fe80::1234:1234 --interface=enp0s3 --debug; echo[/code]

Quais os riscos do Mandos?

Confs Específicas

Mandos Client

Exemplo de script configurador automático para o Mandos Client.

Este script pode ser executado como usuário normal, pois todos os comandos estão com sudo.

Configurações do script:

  • Configura o Mandos Client para pedir a senha ao Mandos Server no IPV6 fdbb:bb na porta 4545
  • Configura  o initramfs para inicia a interface enp1s0 com DHCP client
  • Salva o arquivo de permissão de envio de chave (para ser enviado ao Mandos Server e inserido no /etc/mandos/clients.conf de lá) em ~/nome-do-host.mandos-client-pass
  • Move e renomeia o arquivo de configuração do OpenVPN que será executado no initramfs ~/initram-client.conf para a pasta adequada (então salve o arquivo do OpenVPN do initramfs com este nome!).
  • Move e renomeia arquivo de configuração do OpenVPN que será executado no sistema normal em ~/client.conf para a pasta /etc/openvpn/client.conf (então salve o arquivo do OpenVPN do sistema normal com este nome!).
[code language="bash"]#Instalando OpenVPNsudo apt install openvpn#Configurando o OpenVPN#sudo echo '## This is the configuration file for plugin-runner(8mandos).  This## file should be installed as "/etc/mandos/plugin-runner.conf", and## will be copied to "/conf/conf.d/mandos/plugin-runner.conf" in the## initrd.img file.#### After editing this file, the initrd image file must be updated for## the changes to take effect!Example:--options-for=mandos-client:--connect=fdbb::bb:4545' > /etc/mandos/plugin-runner.conf[/code]

Mandos Server

Exemplo de configurador automático para o Mandos Server.

Este script pode ser executado sem ser super usuário, pois todos os comandos já estão chamando sudo.

Antes de executar o script, coloque o arquivo de configuração do cliente do OpenVPN na pasta home do usuário com o nome client.conf. Por exemplo: ~/client.conf

Este script fará o Mandos Server escutar pacotes IPV6 na porta 4545 sem usar zeroconf (que é o padrão do Mandos).

Ele primeiramente pergunta se você quer instalar alguns pacotes. Responda Y.

Depois ele começa a gerar chaves randômicas. Essa etapa pode demorar um pouco.

Na sequência ele pergunta a senha da encriptação. Escreva a senha pelo teclado.

[code language="bash"]#Installing the OpenVPNapt install openvpn &&#Instalando the DNS fix for OpenVPN in Linuxapt install resolvconf &&#Setting file permissionschown root:root ~/client.conf &&chmod 550 ~/client.conf &&mv ~/client.conf /etc/openvpn &&#Appending the DNS configurations fix in the OpenVPN .conf client fileecho '#Isso permite que os scripts up e down possam ser executadosscript-security 2#Segundo a documentação: 2 -- Allow calling of built-in executables and user-defined scripts#Scripts que arrumam o DNSup /etc/openvpn/update-resolv-confdown /etc/openvpn/update-resolv-conf' >> /etc/openvpn/client.conf &&#Installing Mandos Serverapt install mandos &&#Installing fping for allowing Mandos Server to check client connectivityapt install fping &&#Creating a service that restarts OpenVPN connection if the server is not connected properly#Creating the bashecho '#!/bin/bashOPENVPN_STATUS=$(sudo systemctl status [email protected] | grep "Status: ") &&case "$OPENVPN_STATUS" in*"Pre-connection initialization successful"*)echo "The service is in the Pre-connection state." &&echo "Restarting OpenVPN connection in client.conf." &&systemctl restart [email protected] &&echo "Connection restarted.";;*)echo "The service state is alright.";;esac' > /etc/systemd/system/openvpn-connection-checker.sh &&chown root:root /etc/systemd/system/openvpn-connection-checker.sh &&chmod 751 /etc/systemd/system/openvpn-connection-checker.sh &&#Creating the serviceecho '# /etc/systemd/system/openvpn-connection-checker.service[Unit]Description=Checks periodically if the client.conf defined OpenVPN client has access to 172.22.0.1 IPWants=openvpn-connection-checker.timerAfter=network-online.target[Service]ExecStart=/bin/bash /etc/systemd/system/openvpn-connection-checker.sh[Install]WantedBy=multi-user.target' > /etc/systemd/system/openvpn-connection-checker.service &&chown root:root /etc/systemd/system/openvpn-connection-checker.service &&chmod 751 /etc/systemd/system/openvpn-connection-checker.service &&#Creating the timerecho '# /etc/systemd/system/openvpn-connection-checker.timer[Unit]Description=Run openvpn-connection-checker.sh every 1 minuteRequires=openvpn-connection-checker.service[Timer]Unit=openvpn-connection-checker.serviceOnUnitInactiveSec=1mRandomizedDelaySec=5sAccuracySec=1s[Install]WantedBy=timers.target' > /etc/systemd/system/openvpn-connection-checker.timer &&chown root:root /etc/systemd/system/openvpn-connection-checker.timer &&chmod 751 /etc/systemd/system/openvpn-connection-checker.timer &&systemctl daemon-reload &&systemctl enable openvpn-connection-checker.timer &&# Creating the Mandos Server config file (mandos.conf) that# listens for IPV6 mandos client requests on port 4545# and do not use zeroconfecho '# This file must have exactly one section named "DEFAULT".[DEFAULT]# These are the default values for the server, uncomment and change# them if needed.# If "interface" is set, the server will only listen to a specific# network interface.;interface =# If "address" is set, the server will only listen to a specific# address. This must currently be an IPv6 address; an IPv4 address# can be specified using the "::FFFF:192.0.2.3" syntax. Also, if this# is a link-local address, an interface should be set above.;address =# If "port" is set, the server to bind to that port. By default, the# server will listen to an arbitrary port.port = 4545# If "debug" is true, the server will run in the foreground and print# a lot of debugging information.;debug = False# GnuTLS priority for the TLS handshake. See gnutls_priority_init(3).;priority = SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA:+SIGN-DSA-SHA256# Zeroconf service name. You need to change this if you for some# reason want to run more than one server on the same *host*.# If there are name collisions on the same *network*, the server will# rename itself to "Mandos #2", etc.servicename = Mandos# Whether to provide a D-Bus system bus interface or not;use_dbus = True# Whether to use IPv6. (Changing this is NOT recommended.);use_ipv6 = False# Whether to restore saved state on startuprestore = True# The directory where state is saved;statedir = /var/lib/mandos# Whether to run in the foreground;foreground = False# File descriptor number to use for network socket;socket =# Whether to use ZeroConf; if false, requires port or socketzeroconf = False' > /etc/mandos/mandos.conf &&chown root:root /etc/mandos/mandos.conf &&chmod 644 /etc/mandos/mandos.conf[/code]

A partir daqui já pode-se fazer configurações manuais, especialmente no arquivo clients.conf em /etc/mandos/clients.conf

Referências

Site oficial do Mandos https://wiki.recompile.se/wiki/Mandos

Documentação do Mandos Server 1.7.19-1 no Ubuntu 18.04 Bionic http://manpages.ubuntu.com/manpages/bionic/man8/mandos.8.html

Documentação do Mandos Client 1.7.19-1 no Ubuntu 18.04 Bionic http://manpages.ubuntu.com/manpages/bionic/man8/mandos-client.8mandos.html

Melhor tutorial de instalação do Mandos https://blog.boyeau.com/booting-an-unattended-full-disk-encrypted-server-ubuntu-server-16-04-setup-with-mandos/

Bug de DNS no initramfs do Ubuntu 16 https://bugs.launchpad.net/ubuntu/+source/initramfs-tools/+bug/1714308

Criando entropia no gerador de números randômicos do Linux com Haveged https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged

Como o LUKS funciona?

https://askubuntu.com/a/805880/792551

You should also read:

Capturando pacotes de rede para analises no Wireshark

Forma fácil, rápida e roots. Referências boas: BosonTreinamentos http://www.bosontreinamentos.com.br/redes-computadores/tcpdump-capturar-e-analisar-trafego-de-rede-no-linux/ LinuxTechi https://www.linuxtechi.com/capture-analyze-packets-tcpdump-command-linux/#:~:text=In%20tcpdump%20command%20we%20can,ssh%20%3E%20169.144. Outra forma roots. Forma mais gourmet

Verificando débitos do seu veículo no Paraná

http://transito.curitiba.pr.gov.br/processos/consulta-de-andamento-de-processos-renavam/22 http://www.detran.pr.gov.br/servico/extratodebito https://www.governodigital.pr.gov.br/servicos/Veiculo/Guias-para-pagamento-e-certidoes/Emitir-guia-para-pagamento-do-licenciamento-de-veiculos-ERrZWjo6

Troubleshooting conexões via OpenVPN

# Testar via OpenVPN diretamenteopenvpn --config client.conf# Testar via systemdsystemctl start openvpn@clientjournalctl --follow -u openvpn@client# Verificando todas as conexões abertas via systemdsystemctl status…