O bootpc e o bootpd atuais do Debian (do bootp ) não parecem realmente funcionar juntos no ambiente do kernel Linux de hoje. Parece haver um problema 🐔/🥚; bootpd
envia as respostas como pacotes UDP unicast para o endereço IP ainda não configurado. O kernel do cliente então os descarta sem entregar ao bootpc
soquete do cliente, porque esse endereço IP não é (ainda) um endereço local válido no host.
Como isso funcionou?
- Existe algum parâmetro do kernel ou outra modificação que pode fazer com que o kernel envie esses pacotes ao
bootpc
processo? - Existe uma configuração
bootpd
que fará com que ele use todos os endereços IP de destino 1 ou 0 em vez do endereço IP unicast do cliente ainda não configurado?
Temos um cliente em potencial com uma grande infraestrutura bootp não-DHCP. Suporte bootp old-school é um dos requisitos deles.
Detalhes do problema
bootpd
envia seus pacotes de resposta como pacotes unicast para o endereço MAC do cliente bootpc, usando um valor de endereço IP de destino do endereço que também está na carga útil, informando ao cliente para se configurar.- O kernel então descarta esses pacotes, em vez de entregá-los ao
bootpc
processo que os solicitou. bootpc
abriu corretamente um soquete de escuta para0.0.0.0:68 0.0.0.0:*
(veja a saída netstat abaixo)- Verifiquei essa análise de várias maneiras:
- Eu corri
tcpdump
e posso ver as respostas chegando ao NIC - Eu executei
dropwatch
e vi os pacotes sendo descartados com o motivoIPINADDRERROR
, que basicamente significa "endereço IP inválido" - Posso enganar
bootpd
para usar 0.0.0.0 como o endereço IP de destino omitindo uma atribuição de IP real; quando faço isso,bootpc
obtenho as respostas e as processa. No entanto, isso não ajuda porque o cliente não obtém um endereço IP - Eu tentei adicionar o endereço IP à interface enquanto
bootpc
ela faz requisições. Depois que eu adiciono, a próxima resposta chega ao processo.
- Eu corri
- Eu também tentei a
bootpc --serverbcast
opção. Isso falha por um motivo similar:bootpd
envia as respostas para o endereço de transmissão da sub-rede (por exemplo, 10.0.43.255)- Como o endereço IP e a máscara de sub-rede ainda não estão configurados em uma interface, o kernel não tem motivos para considerar isso um endereço válido para si mesmo.
- Aqui está nossa
bootptab
configuração atual:
.vs-default:\
:sm=255.255.254.0:\
:gw=10.0.42.1:\
:ds=10.0.42.1:\
:hn:
client-ad02-vs:\
ht=1:\
ha=0xea4a1fad0002:\
ip=10.0.42.31:\
tc=.vs-default:
Saída do Netstat mostrando bootpc's listening socket
:
$ sudo netstat -unlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
udp 0 0 0.0.0.0:68 0.0.0.0:* 2295/bootpc
Solução alternativa para o Hacky
Eu inventei uma solução alternativa que parece hackeada. Em particular, acho que ela aproveita um comportamento não intencional, talvez não possamos contar com ela para funcionar no futuro:
- o módulo iptables conntrack tem uma correspondência
ctstate
com um valor deDNAT
. - Isso pode ser usado para aceitar pacotes que tenham um endereço IP de destino não reconhecido
- Não creio que a intenção seja corresponder a IPs de horário de verão arbitrários:
- Ele só pode ser usado com pacotes que foram NAT'd pelo kernel do mesmo host
- Acredito que seu propósito seja corresponder a pacotes que tiveram seus endereços reescritos (o que não estamos fazendo), mas é uma implementação "barata" que ignora a tabela de mapeamento NAT em vez de verificar se há uma entrada que corresponde a esse pacote específico.
- Estou preocupado que isso seja removido ou reescrito para ser menos promíscuo no futuro
- Para que isso funcione, preciso mapear a porta desses pacotes para a porta DST existente, apenas para obter dados de estado da conexão NAT no pacote. Caso contrário,
--ctstate DNAT
não se aplica ao pacote.
Histórico/Due Diligence
- Nosso ambiente de testes usa o Debian 12 no Linux 6.1.0.
- Nossos hosts de teste são de imagens de VM prontas para uso do UTM Debian 12
bootpd
tem muito poucas opções de cli, nenhuma das quais envolve respostas, portas ou endereços. A página do manual não menciona "broadcast" ou "unicast", e referências a "address" ou "destination" são poucas e não relevantes.- Nosso produto atual é o Debian 12 em um kernel Linux 5.19.9 personalizado (e se comporta da mesma maneira)
- A conectividade IP está funcionando totalmente entre o cliente e o servidor do ambiente de teste
bootpc
se recusa a enviar solicitações, a menos que o seguinte seja verdadeiro:- Não há nenhum endereço IP roteável na interface (169.254/16 é permitido, embora eu tenha tentado sem ele)
- Há uma rota padrão 0/0 apontando para a interface onde o servidor bootp é esperado
- Caso contrário, diz
network unreachable
- Nota: especificar
--dev <iface>
nabootpc
linha de comando não ajuda com isso
- Caso contrário, diz
- Ainda estou trabalhando na avaliação de
bootptab
opções de configuração para ver se há alguma que afete isso. Não encontrei uma boa referência para elas, abootptab
página man do man é muito concisa sobre elas.
Solução alternativa
Consegui fazer isso funcionar com uma iptables
solução menos complicada: adicionei uma regra NAT que corresponde à porta UDP 68 (bootpc) e mapeia o endereço IP de destino para 255.255.255.255 (e mantém a mesma porta UDP).
Isso funciona, mas considero isso hacky. Claramente não é assim que o protocolo deve funcionar, então eu preferiria uma solução "real", se possível.