====== DHCP com opção 82 ====== O que é a opção 82 do serviço DHCP? Eu confesso que no começo não entendi muito bem ai montei um laboratório para verificar o funcionamento e utilidade. Abaixo desenhei a topologia do laboratório. {{ :infra-estrutura:linux:dhcp:dhcp_option82.png?direct&600 |}} A opção 82 trabalha com campos especificos do pacote DHCP, o processo de obtenção de um ip em uma rede onde temos um servidor DHCP a grosso funciona o dispositivo solicitando um endereço IP para uso e o servidor DHCP fornecendo este endereço IP. A opção 82 funciona somente com dhcp relay. Mas o que é dhcp relay? outro termo novo, pense da seguinte forma: em uma rede de computadores bem segmentada eu possua uma segmento de rede com uma vlan para os setores: * administrativo * financeiro * engenharia * serviços oferecidos pela rede * recursos humanos * etc E que cada um desses segmentos eu possua em torno de uns 100 computadores. Pense em gerenciar os endereços desses equipamentos, e ainda temos que pensar em ter um servidor DHCP em cada segmento. Bom além de ser desgastante não é prático. O que seria uma solução eficiente e prática concentrar todos os escopos DHCP em um único servidor. Ótimo isso e possível, mas como fazer esse servidor estar em todos os segmentos? aí que entra o relay agente ou ainda dhcp relay. Ele fica escutando os DHCP request na porta UDP 67 (broadcast) e faz um unicast para o servidor DHCP centralizado. Aí você me pergunta mas se tem tantos escopos como o servidor DHCP sabe para qual escopo enviar o reply? baseado no DHCP request um campo do campo "Relay Agent IP Address" o qual informa o endereço IP da interface que recebeu o broadcast ou o DHCP request o qual o relay agent ira redirecionar para o servidor DHCP. {{ :infra-estrutura:linux:dhcp:dhcpoption82.png?direct&600 |}} ===== Configuração Servidor DHCP ===== A configuração do servidor DHCP e simples e necessário somente criar os escopos e qualquer configuração especifica adicional. Segue abaixo um exemplo: default-lease-time 600; max-lease-time 7200; authoritative; subnet 192.168.10.0 netmask 255.255.255.0 { range 192.168.10.160 192.168.10.200; option domain-name-servers 192.168.10.1, 8.8.8.8; option domain-name "capsula.corp"; option routers 192.168.10.1; option broadcast-address 192.168.10.255; default-lease-time 600; max-lease-time 7200; } subnet 192.168.1.0 netmask 255.255.255.0 { range 192.168.1.160 192.168.1.200; option domain-name-servers 192.168.10.1, 8.8.8.8; option domain-name "rede1.capsula.corp"; option routers 192.168.1.1; option broadcast-address 192.168.1.255; default-lease-time 600; max-lease-time 7200; } subnet 192.168.2.0 netmask 255.255.255.0 { range 192.168.2.160 192.168.2.200; option domain-name-servers 192.168.10.1, 8.8.8.8; option domain-name "rede2.capsula.corp"; option routers 192.168.2.1; option broadcast-address 192.168.2.255; default-lease-time 600; max-lease-time 7200; } No caso da distribuição Ubuntu 18.04 LTS que estou utilizando preciso definir no arquivo /etc/default/isc-dhcp-server. INTERFACES="enp0s8" Vamos visualizar a saída do comando ifconfig do endereço IP 192.168.10.1. root@cerberus:~# ifconfig enp0s8: flags=4163 mtu 1500 inet 192.168.10.1 netmask 255.255.255.0 broadcast 192.168.10.255 inet6 fe80::21a:3fff:fe79:f237 prefixlen 64 scopeid 0x20 ether 00:1a:3f:79:f2:37 txqueuelen 1000 (Ethernet) RX packets 30788480 bytes 4879501361 (4.8 GB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 50909049 bytes 62704009094 (62.7 GB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1000 (Local Loopback) RX packets 21141 bytes 2222310 (2.2 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 21141 bytes 2222310 (2.2 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 root@cerberus:~# É interessante o servidor DHCP possuir rotas para as redes que o DHCP Relay atende. root@cerberus:~# route add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.10.171 root@cerberus:~# route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.10.171 root@cerberus:~# root@cerberus:~# route -nv Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.1.0 192.168.10.171 255.255.255.0 UG 0 0 0 enp0s8 192.168.2.0 192.168.10.171 255.255.255.0 UG 0 0 0 enp0s8 root@cerberus:~# ===== Configuração DHCP Relay ===== Para uso do dhcp relay temos que instalar o pacote isc-dhcp-relay. root@nemesis:~# apt search isc-dhcp-relay Sorting... Done Full Text Search... Done isc-dhcp-relay/bionic,now 4.3.5-3ubuntu7 amd64 [residual-config] ISC DHCP relay daemon root@nemesis:~# Vamos instalar root@nemesis:~# apt install isc-dhcp-relay Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed: isc-dhcp-relay 0 upgraded, 1 newly installed, 0 to remove and 132 not upgraded. Need to get 192 kB of archives. After this operation, 608 kB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu bionic/universe amd64 isc-dhcp-relay amd6 4 4.3.5-3ubuntu7 [192 kB] Fetched 192 kB in 2s (118 kB/s) Preconfiguring packages ... Selecting previously unselected package isc-dhcp-relay. (Reading database ... 107673 files and directories currently installed.) Preparing to unpack .../isc-dhcp-relay_4.3.5-3ubuntu7_amd64.deb ... Unpacking isc-dhcp-relay (4.3.5-3ubuntu7) ... Processing triggers for ureadahead (0.100.0-20) ... ureadahead will be reprofiled on next reboot Setting up isc-dhcp-relay (4.3.5-3ubuntu7) ... Processing triggers for systemd (237-3ubuntu10) ... Processing triggers for man-db (2.8.3-2) ... root@nemesis:~# Porém em meus testes com o dhcrelay do repositorio Ubuntu não é possível alterar as strings circuit-id e remote-id da opção 82. O dhcrelay envia essas opções de forma automática e você não consegue altera-los. Porém se você quiser existe um patch para fazer isso em [[https://github.com/jpereira/isc-dhp-relay]]. Basicamente a instalação código fonte com o patch aplicado consiste nos comandos: root@nemesis:~# git clone https://github.com/jpereira/isc-dhp-relay isc-dhcp-relay.git root@nemesis:~# cd isc-dhcp-relay.git/dhcp-4.3.1 root@nemesis:~# ./configure --prefix=/usr/local/dhcrelay root@nemesis:~# make root@nemesis:~# make install Na nossa topologia o dhcp relay e o endereço IP 192.168.10.171 na interface ligada ao mesmo segmento do servidor DHCP as outras interfaces fazemos uso de vlans e utilizamos as interfaces vlan10 e vlan11. root@nemesis:~# cat /proc/net/vlan/config VLAN Dev name | VLAN ID Name-Type: VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD vlan11 | 11 | enp3s0 vlan10 | 10 | enp3s0 root@nemesis:~# A interface pai das subinterfaces é a interface física enp3s0 e as subinterfaces vlan10 e vlan11. root@nemesis:~# ifconfig enp0s25: flags=4163 mtu 1500 inet 192.168.10.171 netmask 255.255.255.0 broadcast 192.168.10.255 inet6 fe80::21a:4dff:fe97:7921 prefixlen 64 scopeid 0x20 ether 00:1a:4d:97:79:21 txqueuelen 1000 (Ethernet) RX packets 4161 bytes 2655582 (2.6 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 1670 bytes 170958 (170.9 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 20 memory 0xf2200000-f2220000 enp3s0: flags=4163 mtu 1500 inet6 fe80::210:eaff:feea:177f prefixlen 64 scopeid 0x20 ether 00:10:ea:ea:17:7f txqueuelen 1000 (Ethernet) RX packets 1523 bytes 140888 (140.8 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 49 bytes 3490 (3.4 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1000 (Local Loopback) RX packets 134 bytes 10690 (10.6 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 134 bytes 10690 (10.6 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 vlan10: flags=4163 mtu 1500 inet 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80::210:eaff:feea:177f prefixlen 64 scopeid 0x20 ether 00:10:ea:ea:17:7f txqueuelen 1000 (Ethernet) RX packets 164 bytes 56396 (56.3 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 26 bytes 1356 (1.3 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 vlan11: flags=4163 mtu 1500 inet 192.168.2.1 netmask 255.255.255.0 broadcast 192.168.2.255 inet6 fe80::210:eaff:feea:177f prefixlen 64 scopeid 0x20 ether 00:10:ea:ea:17:7f txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 8 bytes 600 (600.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 root@nemesis:~# A interface enp0s25 e a interface conectada no segmento do servidor DHCP. Com o ambiente preparado vamos executar o daemon do dhcrelay, informado o circuit-id e remote-id. root@nemesis:~# ./dhcrelay -a "exemplo-circuit-id" "exemplo-remote-id" 192.168.10.1 Internet Systems Consortium DHCP Relay Agent 4.3.1 Copyright 2004-2014 Internet Systems Consortium. All rights reserved. For info, please visit https://www.isc.org/software/dhcp/ Listening on LPF/vlan11/00:10:ea:ea:17:7f Sending on LPF/vlan11/00:10:ea:ea:17:7f Listening on LPF/enp0s25/00:1a:4d:97:79:21 Sending on LPF/enp0s25/00:1a:4d:97:79:21 Listening on LPF/vlan10/00:10:ea:ea:17:7f Sending on LPF/vlan10/00:10:ea:ea:17:7f Sending on Socket/fallback root@nemesis:~# Agora a partir de uma estação na vlan 10 vou utilizar o dhclient e tentar obter endereço IP e utilizar o tcpdump no servidor DHCP para ver se o pacote DHCP request chegam com a opção 82. Abaixo visualizamos via wireshark {{ :infra-estrutura:linux:dhcp:dhcpoption82-01.png?direct&600 |}} Repare que no wireshark a informação esta em hexa decimal vamos visualizar via follow->udp stream e também copiar o valor do campo 'Agent Circuit ID' que está em hexa e converter para ASCII. Repare que o valor em hexa esta sem o 0x na frente vamos colocar e depois converter no shell do Linux mesmo root@nemesis:~# VAR=$( echo -e "65:78:65:6d:70:6c:6f:2d:63:69:72:63:75:69:74:2d:69:64\n" | sed 's/:/ 0x/g' | xxd -r -p ) root@nemesis:~# echo $VAR exemplo-circuit-id root@nemesis:~# Abaixo a imagem via follow->udp stream do wireshark {{ :infra-estrutura:linux:dhcp:dhcpoption82-02.png?direct&600 |}} Abaixo o log no servidor DHCP. Mar 21 10:15:29 cerberus dhcpd[31577]: exemplo-circuit-id Mar 21 10:15:29 cerberus dhcpd[31577]: DHCPDISCOVER from 00:e0:4c:51:3c:82 via 192.168.1.1 Mar 21 10:15:30 cerberus dhcpd[31577]: DHCPOFFER on 192.168.1.160 to 00:e0:4c:51:3c:82 (bumblee) via 192.168.1.1 Mar 21 10:15:30 cerberus dhcpd[31577]: exemplo-circuit-id Mar 21 10:15:30 cerberus dhcpd[31577]: DHCPREQUEST for 192.168.1.160 (192.168.10.1) from 00:e0:4c:51:3c:82 (bumblee) via 192.168.1.1 Mar 21 10:15:30 cerberus dhcpd[31577]: DHCPACK on 192.168.1.160 to 00:e0:4c:51:3c:82 (bumblee) via 192.168.1.1 Mar 21 10:15:32 cerberus dhcpd[31577]: exemplo-circuit-id Mar 21 10:15:32 cerberus dhcpd[31577]: DHCPDISCOVER from 00:e0:4c:51:3c:82 via 192.168.1.1 Mar 21 10:15:33 cerberus dhcpd[31577]: DHCPOFFER on 192.168.1.161 to 00:e0:4c:51:3c:82 via 192.168.1.1 Mar 21 10:15:33 cerberus dhcpd[31577]: exemplo-circuit-id Mar 21 10:15:33 cerberus dhcpd[31577]: DHCPREQUEST for 192.168.1.161 (192.168.10.1) from 00:e0:4c:51:3c:82 via 192.168.1.1 ===== Configuração Servidor DHCP ===== Agora você me pergunta, praque tudo isso? rs bom este recurso de circuit-id e remote-id e utilizado muito em redes DOCSYS e GPON/EPON. Um exemplo em uma rede EPON, normalmente temos um ONU que não é router trabalha em modo bridge, ou seja precisa de um roteador conectada na ONU para receber um endereço IP válido e normalmente realizar o roteamento ou ainda um estação de trabalho. Veja o desenho abaixo: {{ :infra-estrutura:linux:dhcp:redeepon.png?direct&600 |}} Na topologia acima temos um servidor DHCP fornecendo endereços IP's válidos aos clientes numa rede EPON/FTTX. O problema nessa topologia e que se algum cliente mais espertinho colocar um switch e colocar vários hosts rapidamente vamos exaurir o escopo dhcp do servidor. Como tratar isso? na verdade preciso conceder apenas um endereço IP para cada ONU/ONT como fazemos isso? com as informações de circuit-id e remote-id que e repassado pela ONU, então vamos as configurações dhcpd.conf default-lease-time 600; max-lease-time 7200; authoritative; # Utilizado para enviar os logs dhcp para o syslog e no nivel local7 # depois pode no syslog.conf criar uma entrada para jogar tudo que for local7 para um arquivo dedicado log-facility local7; # aqui falamos para o daemon do dhcp printar o circuit-id nos logs se houver. log ( info, option agent.circuit-id ); subnet 192.168.10.0 netmask 255.255.255.0 { range 192.168.10.160 192.168.10.200; option domain-name-servers 192.168.10.1, 8.8.8.8; option domain-name "capsula.corp"; option routers 192.168.10.1; option broadcast-address 192.168.10.255; default-lease-time 600; max-lease-time 7200; } # Somente irei mostrar a configuração de um escopo o outro e igual subnet 192.168.1.0 netmask 255.255.255.0 { range 192.168.1.160 192.168.1.200; option domain-name-servers 192.168.10.1, 8.8.8.8; option domain-name "rede1.capsula.corp"; # aqui vem o pulo do gato vamos criar um classe para combinar com a opção 92 chegar no DHCP request # com a string "exemplo-circuit-id" class "class01" { match if option agent.circuit-id = "exemplo-circuid-id"; } # agora criamos um pool para que toda vez que combinar com a class "class01" ativar o pool e fornecer # o range informado pool { range 192.168.1.40; allow members of "class01"; } option routers 192.168.1.1; option broadcast-address 192.168.1.255; default-lease-time 600; max-lease-time 7200; } Com isso o cliente precisa obter o endereço ip 192.168.1.40. Ja deixei comentário no arquivo dhcpd.conf mas vou explicar novamente. Resumindo, criamos uma classe DHCP para combinar com o option 82 que contiver a string de circuit-id "exemplo-circuit-id" depois criamos um pool que fornecerá o range com o endereço IP 192.168.1.40 para o fluxo que combinar com "Agent circuit id" igual a "exemplo-circuit-id". Testei e funcionou perfeitamente, mas isso não impede ainda que o cliente coloque um switch e acabe com nosso escopo. Sendo assim a idéia e criar uma classe para cada circuit-id gerado pela ONU/ONT, além disso podemos deixar um range maior e utilizar a opção "lease limit". A opção "lease limit" permite você especificar um limite para o número de clientes nessa classe que podem ser designado na concessão DHCP. Com isso dificultando que novos clientes nessa classes obtenham endereços IP's. Uma vez que uma classe com tal limite tenha sido atingido seu limite, a única maneira de um novo cliente nessa classe obter uma concessão é para um cliente existente renunciar a sua concessão, deixando expirar ou enviando um pacote DHCPRELEASE. Abaixo como ficaria a definição da nossa classe permitindo apenas 1 lease ou concessão para um endereço IP apenas. class "class01" { match if option agent.circuit-id = "exemplo-circuit-id"; lease limit 1; } pool { range 192.168.1.100 192.168.1.200; allow members of "class01"; } Quando um novo DHCP request chega vindo do mesmo circuit-id nos logs vemos que não possui mais concessões disponivéis. Mar 21 10:13:22 cerberus dhcpd[27585]: DHCPDISCOVER from 00:e0:4c:51:3c:82 via 192.168.1.1: network 192.168.1.0/24: no free leases Mar 21 10:13:07 cerberus dhcpd[27585]: message repeated 3 times: [ DHCPDISCOVER from 00:e0:4c:51:3c:82 via 192.168.1.1: network 192.168.1.0/24: no free leases] Mar 21 10:13:22 cerberus dhcpd[27585]: DHCPDISCOVER from 00:e0:4c:51:3c:82 via 192.168.1.1: network 192.168.1.0/24: no free leases Mar 21 10:13:39 cerberus dhcpd[27585]: message repeated 4 times: [ DHCPDISCOVER from 00:e0:4c:51:3c:82 via 192.168.1.1: network 192.168.1.0/24: no free leases] ===== Funcionamento com lease limit ===== Abaixo os testes com duas máquinas ligada e um obtem o endereço 192.168.1.40 e o segundo computador não consegue. Mar 21 12:44:38 cerberus dhcpd[32593]: exemplo-circuit-id Mar 21 12:44:38 cerberus dhcpd[32593]: DHCPDISCOVER from 00:1d:ba:19:5a:3e via 192.168.1.1 Mar 21 12:44:39 cerberus dhcpd[32593]: DHCPOFFER on 192.168.1.40 to 00:1d:ba:19:5a:3e via 192.168.1.1 Mar 21 12:44:39 cerberus dhcpd[32593]: exemplo-circuit-id Mar 21 12:44:39 cerberus dhcpd[32593]: DHCPREQUEST for 192.168.1.40 (192.168.10.1) from 00:1d:ba:19:5a:3e via 192.168.1.1 Mar 21 12:44:39 cerberus dhcpd[32593]: DHCPACK on 192.168.1.40 to 00:1d:ba:19:5a:3e via 192.168.1.1 Mar 21 12:44:58 cerberus dhcpd[32593]: DHCPDISCOVER from 00:e0:4c:51:3c:82 via 192.168.1.1: network 192.168.1.0/24: no free leases Mar 21 12:45:01 cerberus dhcpd[32593]: DHCPDISCOVER from 00:e0:4c:51:3c:82 via 192.168.1.1: network 192.168.1.0/24: no free leases Mar 21 12:45:05 cerberus dhcpd[32593]: DHCPREQUEST for 192.168.1.161 from 00:e0:4c:51:3c:82 via 192.168.1.1: unknown lease 192.168.1.161. Mar 21 12:45:05 cerberus dhcpd[32593]: DHCPDISCOVER from 00:e0:4c:51:3c:82 via 192.168.1.1: network 192.168.1.0/24: no free leases Mar 21 12:45:10 cerberus dhcpd[32593]: DHCPDISCOVER from 00:e0:4c:51:3c:82 via 192.168.1.1: network 192.168.1.0/24: no free leases Mar 21 12:45:14 cerberus dhcpd[32593]: DHCPREQUEST for 192.168.1.161 from 00:e0:4c:51:3c:82 via 192.168.1.1: unknown lease 192.168.1.161. Mar 21 12:45:16 cerberus dhcpd[32593]: DHCPDISCOVER from 00:e0:4c:51:3c:82 via 192.168.1.1: network 192.168.1.0/24: no free leases Com isso não precisamos vincular o endereço MAC do equipamento cliente ligado a ONU/ONT. Um dos problemas que acontece também com o vinculo do endereço MAC do cliente, caso a placa de rede do equipamento do cliente sofra um problema e queime, o cliente precisaria ligar ao provedor e alterar o vinculo do MAC da placa queimada para um novo MAC fazendo assim um processo não automatizado. Att.