Nomes de clientes OpenVPN no dnsmasq: script ou entradas estáticas?
Os endereços dos clientes mudam, os nomes dos serviços não. Gere os nomes dos clientes a partir da sessão VPN, fixe os nomes dos serviços num ficheiro drop-in e depois faça com que os clientes o usem.
Dois problemas de nomes aparecem em quase todos os gateways OpenVPN pequenos. Não consegue chegar a um portátil ligado pelo nome do seu certificado, e os serviços atrás do túnel não têm nome nenhum. Parecem um só problema e exigem tratamentos opostos, porque um endereço muda a cada sessão e o outro não. Decida que tipo de nome está a acrescentar antes de editar o que quer que seja.
Decida por nome, não por gateway
O teste é simples: este endereço muda quando um cliente se volta a ligar? Se sim, o nome tem de ser gerado a partir da sessão VPN. Se não, pertence a uma entrada estática que pode ler e rever.
| Name kind | Source of truth | Where it lives |
|---|---|---|
| Connected client | The address OpenVPN just assigned | Generated hosts file, rewritten per session |
| Service behind the tunnel | A fixed address you chose | Static address= drop-in |
| Anything with a certificate name | The certificate, not the pool | Either, but the name must match the certificate |
Misturá-los é a falha habitual. Um serviço fixado no ficheiro gerado desaparece na primeira vez que o script o reescreve, e um cliente escrito numa entrada estática aponta para quem tinha esse endereço por último. Ambos os erros ficam invisíveis até um nome resolver para a máquina errada. A essa altura, quem depura assume que o DNS está avariado e não o ficheiro.
O caminho dinâmico: learn-address e o pool
O OpenVPN conhece a atribuição, por isso deixe que lhe diga. Estas opções do servidor tornam a atribuição duradoura e programável:
client-config-dir /etc/openvpn/ccd
ifconfig-pool-persist /etc/openvpn/ip-pool 60
script-security 2
learn-address /etc/openvpn/learn-address.sh
learn-address executa o seu script sempre que um endereço é adicionado, atualizado ou removido, e passa a operação, o endereço e o nome comum. Um script mínimo acrescenta uma linha por cliente e remove-a ao apagar:
#!/bin/sh
HOSTS=/etc/openvpn/hosts.lan
case "$1" in
add|update) echo "$2 $3" >> "$HOSTS" ;;
delete) sed -i "/^$2 /d" "$HOSTS" ;;
esac
kill -HUP $(cat /var/run/dnsmasq.pid)
Num dispositivo tun o segundo argumento é o endereço de túnel do cliente, por isso a linha é diretamente utilizável. Num dispositivo tap o OpenVPN passa, em vez disso, o endereço MAC do cliente, porque um segmento tap pode transportar protocolos que não o IPv4, e nesse caso tem de procurar o endereço no ficheiro do pool pelo nome comum antes de escrever o que quer que seja.
Seja claro quanto ao que é o ficheiro gerado: uma fotografia de quem está ligado neste momento. Os nomes desaparecem ao desligar, o que é exatamente o que quer para portáteis que passam de rede em rede e exatamente o que não quer para um servidor ligado toda a noite.
O caminho estático: address= e expansão de domínio
Aponte o dnsmasq para o ficheiro gerado em vez do ficheiro hosts do sistema, e dê-lhe um domínio para que os nomes curtos se expandam em nomes plenamente qualificados:
domain=corp.example
no-hosts
addn-hosts=/etc/openvpn/hosts.lan
listen-address=127.0.0.1,10.8.0.1
bind-interfaces
Com domain definido, uma linha como 10.8.0.6 alice responde tanto por alice como por alice.corp.example. Mantenha o listen-address no gateway do túnel e no loopback, porque um resolver publicado por acidente na interface LAN é um serviço que não pretendia oferecer.
Os serviços que nunca vêm do pool têm as suas próprias entradas. Coloque-os num ficheiro drop-in separado no diretório de configuração da distribuição para que uma atualização de pacote não os possa substituir:
address=/files.corp.example/10.8.0.20
address=/db.corp.example/10.9.0.5
Entregue o resolver ou não acontece nada
Um resolver que ninguém consulta não muda nada. O servidor tem de o anunciar:
push "dhcp-option DNS 10.8.0.1"
push "dhcp-option DOMAIN corp.example"
Os clientes Windows aplicam ambas as opções por si próprios. A maioria dos clientes Linux não: precisam de uma integração de resolver suportada, como o gancho update-resolv-conf da distribuição ou o tratamento de DNS do NetworkManager, ou de um domínio de pesquisa e servidor de nomes manuais. Verifique o resolver real do cliente em vez de assumir que o push foi respeitado, porque um push ignorado parece exatamente um servidor que não responde.
Verifique em três camadas
Pergunte primeiro ao servidor diretamente, depois a um cliente e depois à aplicação:
dig +short @10.8.0.1 alice.corp.example
getent hosts files.corp.example
Se as consultas diretas respondem e a aplicação não, a culpa é da entrega ao cliente e não da zona. Se o nome resolve e a ligação continua a falhar, o nome está bem e o próximo ponto a ver é a rota ou a firewall.
Anote as duas categorias ao lado da configuração: que nomes são gerados, quais estão fixados e com que certificado cada um tem de coincidir. A próxima pessoa que acrescentar um servidor vai copiar o primeiro padrão que encontrar.