Ferramentas do usuário

Ferramentas do site


infra-estrutura:linux:dhcp:dhcp_option_82

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.

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.

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<UP,BROADCAST,RUNNING,MULTICAST>  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<link>
        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<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        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<UP,BROADCAST,RUNNING,MULTICAST>  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<link>
        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<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::210:eaff:feea:177f  prefixlen 64  scopeid 0x20<link>
        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<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        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<UP,BROADCAST,RUNNING,MULTICAST>  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<link>
        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<UP,BROADCAST,RUNNING,MULTICAST>  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<link>
        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

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

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:

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.