
Injetor de opções DHCP
Você já quis interceptar pedidos DHCP e introduzir algumas opções DHCP extras, sem que o remetente soubesse? Provavelmente não. No entanto, se a necessidade surgir, dhcpoptinj irá (espero) ajudar você.
Pode haver muitas razões para alterar pedidos DHCP, embora seja provável que você deva procurar um método muito melhor para resolver o seu problema. Talvez você não tenha acesso ao servidor/clientes DHCP e precise modificar as opções DHCP deles, talvez o software DHCP seja difícil de configurar (ou não suporte o que você quer fazer), talvez você tenha uma configuração muito complexa e/ou incomum, ou talvez você só queira experimentar enviar opções exóticas ou malformadas? Existe uma pequena chance de que o dhcpoptinj possa ser realmente útil.
O dhcpoptinj aguarda que pacotes cheguem a uma fila do netfilter. Ele garante que um pacote seja de fato um pacote BOOTP/DHCP e, se for, prossegue para injetar opções. Ele recalcula o checksum do cabeçalho IPv4, desativa o checksum UDP (para uma implementação mais simples) e então devolve o pacote ao netfilter.
Você precisa de uma regra de iptables para interceptar pacotes e enviá-los ao dhcpoptinj. Digamos que você tenha duas interfaces em ponte, eth0 e eth1. Digamos que você queira interceptar todos os pedidos BOOTP vindos de eth0 e injetar a opção relay agent information (82/0x52). Vamos inventar um payload bobo: uma sub-opção agent circuit ID com o valor "Fjas".
Adicione uma regra à tabela mangle do iptables:sudo iptables -t mangle -A PREROUTING -m physdev --physdev-in eth0 -p udp --dport 67 -j NFQUEUE --queue-num 42.
Em seguida, execute o dhcpoptinj (vamos executá-lo em primeiro plano com saída de depuração extra):
sudo dhcpoptinj -d -f -q 42 -o'52 01 04 46 6A 61 73'. Observe que o dhcpoptinj
deve ser executado por um usuário com a capacidade CAP_NET_ADMIN. Você não precisa, e
realmente não deve, executar o dhcpoptinj como root. Em vez disso, você pode, por exemplo,
conceder a capacidade CAP_NET_ADMIN ao binário (usando setcap) e limitar
os direitos de execução a apenas um usuário ou grupo específico. Este é um método usado para
executar o wireshark como não-root, então você encontrará vários guias que ajudam você a
fazer isso.
Agora envie um pacote DHCP para a interface eth0 e observe-o (usando uma ferramenta como wireshark) tendo sido modificado quando ele atingir a interface em ponte. Ele deve ter a opção injetada no final da lista de opções. Se você capturar o pacote DHCP de entrada com o Wireshark, ele parecerá inalterado, embora na verdade tenha sido modificado.
Observe o formato do argumento da opção -o: Deve ser uma string hexadecimal começando com o código da opção DHCP, seguido pelo payload da opção. O comprimento da opção (o byte que normalmente segue o código da opção) é calculado automaticamente e não deve ser especificado. A string hexadecimal pode ser delimitada por caracteres não hexadecimais para facilitar a leitura. Todas as opções devem ter um payload, exceto a opção pad especial (código 0).
O layout da opção sem sentido usada neste exemplo (primeiro o layout de opções DHCP, depois o layout da sub-opção da opção relay agent information) é o seguinte:
| Código | Comprimento | Dados |
|---|---|---|
| 52 | (automático) | 01 04 46 6A 61 73 ("Fjas") |
| Sub-opção | Comprimento | Dados |
|---|---|---|
| 01 | 4 | 46 6A 61 73 ("Fjas") |
Observe que o dhcpoptinj não se importa com o que você escreve nos payloads das opções, nem verifica se o código da opção existe. No entanto, ele proíbe o uso do código de opção 255 (a opção final de terminação). O dhcpoptinj insere essa opção como a última opção automaticamente.
dhcpoptinj -f -d -q42 -r -o'0C 66 6A 61 73 65 68 6F 73 74' -o'52 01 04 46 6A 61 73' -o 320A141E28
3 DHCP option(s) to inject (with a total of 25 bytes): 12 (0x0C) (Hostname), 82 (0x52) (Relay Agent Information), 50 (0x32) (Address Request)
Existing options will be removed
Initialising netfilter queue
Initialising signal handler
Initialisation completed. Waiting for packets to mangle on queue 42
Received 416 bytes
Inspecting 328-byte DHCP packet from B6:40:FE:41:30:DC to 255.255.255.255:67
Mangling packet
Found option 53 (0x35) (DHCP message type) DHCPREQUEST (copying)
Found option 54 (0x36) (DHCP Server Id) with 4-byte payload 0A 14 1E 01 (copying)
Found option 50 (0x32) (Address Request) with 4-byte payload 0A 14 1E 28 (removing)
Found option 12 (0x0C) (Hostname) with 12-byte payload 33 31 36 64 65 39 31 34 64 61 62 34 (removing)
Found option 55 (0x37) (Parameter List) with 13-byte payload 01 1C 02 03 0F 06 77 0C 2C 2F 1A 79 2A (copying)
Found END option (removing)
Injecting option 12 (0x0C) (Hostname) with 9-byte payload 66 6A 61 73 65 68 6F 73 74
Injecting option 82 (0x52) (Relay Agent Information) with 6-byte payload 01 04 46 6A 61 73
Injecting option 50 (0x32) (Address Request) with 4-byte payload 0A 14 1E 28
Inserting END option
Padding with 10 byte(s) to meet minimal BOOTP payload size
Sending mangled packet
O dhcpoptinj está disponível no Debian/Ubuntu. O pacote deb está sob controle de versão no salsa. Instalar o dhcpoptinj a partir do pacote deb é recomendado em vez do procedimento de instalação manual a seguir, porque ele também inclui uma página de manual, regras de conclusão bash, arquivos de exemplo etc.
Você precisa de cmake e
libnetfilter_queue
(e de um compilador C que suporte C99). Esperamos que você esteja usando um sistema
similar ao Debian, caso em que você pode executar o seguinte para instalá-los: sudo apt-get install cmake libnetfilter-queue-dev.
git clone git://github.com/misje/dhcpoptinjcd dhcpoptinjmkdir build && cd buildcmake .. (ou cmake -DCMAKE_BUILD_TYPE=Debug .. se você quiser um
build de depuração)make -j4sudo make installsudo make uninstall a partir do seu diretório de buildO diretório de build com todo o seu conteúdo pode ser removido com segurança. Se você não
usou um diretório de build, pode se livrar de toda a sujeira do cmake executando git clean -dfx. No entanto, observe que isso remove tudo no diretório do projeto
que não está sob controle de versão.
O dhcptopinj tentará analisar /etc/dhcpoptinj.conf ou o arquivo passado com -c/--conf-file. A sintaxe do arquivo de configuração é
Espaços em branco são opcionais. Qualquer coisa depois do caractere #, incluindo ele, é considerada um comentário. As opções DHCP são listadas uma a uma como option=01:02:03. Aspas ao redor da string hexadecimal da opção são opcionais, e os bytes podem ser separados por qualquer número de caracteres não hexadecimais.
As opções version, help e conf-file não são aceitas em um arquivo de configuração.
Exemplo:
# Run in foreground:
foreground
# Enable debug output:
debug
# Override hostname to "fjasehost":
option = '0C 66 6A 61 73 65 68 6F 73 74'
# Send agent ID "Fjas":
option = "52:01:04:46:6A:61:73"
# Override address request to ask for 10.20.30.40:
option=320A141E28
# Use queue 12:
queue = 12
remove-existing-opt # Remove options before inserting
Este README deve ter dado a você um ponto de partida. Consulte também a página de manual (no
pacote deb) e a saída de ajuda (dhcpoptinj -h), que deve cobrir
tudo o que o utilitário tem a oferecer.
Para bugs e sugestões, por favor crie uma issue.
O dhcpoptinj é simples e esperamos que continue assim. Ainda assim, os seguintes recursos estão ausentes e, esperamos, serão adicionados algum dia:
Failed to bind queue handler to AF_INET: Operation not permitted
Provavelmente você não tem a capacidade CAP_NET_ADMIN ou há outro processo (talvez outra instância do dhcpoptinj?) vinculado ao mesmo número de fila do netfilter.
Vazamento de memória em saída não normal.
Isso não é considerado um vazamento. No entanto, não deve haver vazamento de memória em uma saída normal (capturando SIGTERM, SIGINT ou SIGHUP).
Ao criar regras de iptables para usar com o dhcpoptinj, as seguintes opções podem ser úteis:
--queue-bypass
Não descarte pacotes, mas deixe-os passar se o dhcpoptinj não estiver em execução (ou não estiver ouvindo no número de fila correto).
Se você tiver alguma sugestão, por favor abra uma issue, e eu entrarei em contato com você. Você é bem-vindo para contribuir, e pull requests são muito apreciados.
Se você acha o dhcpoptinj útil, adoraria saber para que você está usando. Atualize a página da wiki e descreva seu uso.
Escolhi usar GPL para este projeto. Se isso não for adequado para você, entre em contato comigo, e podemos concordar com uma licença diferente.