Servidor de logs CGNAT

De ISPUP!
Ir para navegação Ir para pesquisar

Introdução

Com a escassez do recurso IPv4 no mundo, a resistência de muitas organizações que ainda não incluíram o IPv6 em seus sistemas, de muitos Provedores de Internet que ainda não entregam IPv6 nos seus clientes, Clouds que ainda operam sem IPv6, tudo isso torna lenta a mudança de uma Internet antiga e legada, para uma Internet melhor e mais moderna. Mas por que toquei nesse assunto? Porque enquanto usarmos o IPv4 nessa situação, todos nós Operadoras ISP teremos que utilizar um recurso para continuarmos crescendo chamado de CGNAT (Carrier Grade Network Address Translation), que não trás nenhuma qualidade para nossos assinantes ou benefício para o crescimento da Internet. Para mim, CGNAT ou também conhecido como CGN, é uma muleta para a Internet continuar funcionando enquanto o IPv6 não se prevalece no mundo.

O CGNAT tem o objetivo principal de compartilhar IPv4 público e existem diversas soluções comerciais e não comerciais no mercado, mas que não vem ao caso aqui. O que importa para o nosso artigo, é a maneira como ele é implementado e que precisaremos armazenar os logs de conexão por pelo menos 1 ano, segundo o Marco Civil da Internet. Sempre que precisarmos identificar um cliente atrás de um CGNAT para uma Quebra de Sigilo Tecnológico, faremos uso dos logs armazenados.

Nesse artigo abordaremos a montagem de um servidor de logs de CGNAT utilizando um sistema Debian GNU/Linux, softwares livres e uma configuração que nos permita armazenar esses logs de forma organizada para facilitar consultas futuras.

Tipos de implementação do CGNAT

  • Determinístico: onde usamos uma tabela de associação estática entre os IPv4 públicos, suas portas lógicas de origem e os IPs privados usados pelos clientes. Podemos encontrar por exemplo configurações de compartilhamento de 1/16, 1/32, etc, onde por exemplo: 1/32 seria compartilhar 1 IPv4 público com 32 clientes. Essa relação está associada à quantidade de portas lógicas alocadas para o cliente e que no caso de 1/32 seriam algo em torno de 2000 portas para cada cliente. Existe uma ideia errada de que se estamos usando Determinístico, então não precisamos armazenar logs. Em certo ponto está certo porque existe uma associação estática que não deveria mudar, mas se em algum momento você precisar reorganizar sua tabela de associação estática, você precisará ter um controle de quando isso foi alterado, de como era a tabela antes e de como ficou, porque senão você acabará identificando o cliente errado. Minha humilde sugestão: sempre armazene os logs, não importando se é Determinístico ou não.
  • BPA (Bulk Port Allocation): nessa modalidade podemos economizar mais os recursos IPv4 públicos, porque as portas são alocadas dinamicamente e conforme a necessidade de uso do cliente. Se você parar para analisar o perfil dos seus clientes descobrirá que a grande maioria utiliza poucas portas durante o acesso à Internet e por isso, no modelo BPA, você consegue colocar mais clientes utilizando o mesmo IP público. Existe um certo medo nesse modelo de CGNAT, porque muitos acreditam que será necessário gastar rios de dinheiro comprando ou contratando espaço em disco de servidores, para armazenar todos os logs por 1 ano. O que posso dizer é: dependendo da implementação do BPA, sim isso irá acontecer. Um exemplo que vi isso ocorrer foi com um BPA que enviava logs a cada vez que um cliente utilizava uma porta, ou seja, um log por porta. Realmente essa seria a pior configuração ao meu ver, porque embora esteja fazendo a alocação dinâmica das portas, está coletando dados de forma excessiva e sem necessidade. Procure configurar seu BPA para trabalhar com blocos de portas alocadas e aí sim terá logs bem pequenos. Um exemplo real que tenho para dar: uma caixa CGNAT que atende uns 20.000 assinantes, gerando um log diário menor que 10Mb compactado.

Formatos de envio de logs

Os formatos que trabalharemos neste artigo, são os mais utilizados nos equipamentos de Redes:

  • Syslog: é um serviço muito utilizado para armazenar logs sejam eles quais forem; mensagens de outros serviços, erros de sistema, um acesso indevido ou tentativas de se burlar um sistema, enfim, qualquer coisa que possa dar uma informação útil para uma análise da situação. Além de tudo isso podemos utilizar esse recurso para armazenar logs de CGNAT. O problema é que o syslog não é tão robusto e não lida muito bem com muitas requisições simultâneas, aumentando em muito o uso do processamento e dependendo da situação pode ocorrer alguma falha no registro do dado. O que vemos é que para registrar logs de sistemas e processos de um servidor, ele se sai muito bem mas quando temos diversos BNGs enviando logs de CGNAT, ele não seria a melhor opção.
  • Netflow: o envio de flow é utilizado em muitos ambientes para análise por amostragem e com diversas aplicações como por exemplo: sistemas de detecção e mitigação DDoS, sistemas que geram estatísticas úteis para análise de tráfego de Redes, dando informações valiosíssimas para o pessoal da Engenharia de Redes, consumos de determinados conteúdos para avaliar se pode ser solicitado algum Cache de CDN para a sua Operação, detecção de Botnets, enfim, muita coisa pode ser feita usando Netflow inclusive tem uma função especialmente elaborada para logs de CGNAT. Sem falar que ao contrário do nosso amigo syslog, esse sistema se mostra muito mais robusto, preparado para receber muitas requisições simultâneas e com menor consumo de CPU.

Neste artigo configuraremos o nosso servidor para receber ambos os formatos mas por experiência própria, quando falamos de logs de CGNAT, procure sempre que puder, utilizar o Netflow em detrimento ao Syslog.

Diagrama

Antes de iniciar, sim sempre que eu tiver a chance irei utilizar IPv6 em meus exemplos e diagramas para mostrar que não é um bicho de 7 cabeças e que se quisermos crescer e fazer crescer a Internet, precisamos nos conscientizar que isso é importante.

Como base para a nossa configuração usaremos o diagrama ao lado e para poder visualizar o que ocorre em um ambiente com CGNAT. Nesse exemplo temos um cliente, que ao se conectar no Provedor de Internet, recebeu um IPv4 100.64.10.50 (RFC6598) e um Prefix Delegation IPv6 2001:0db8:b010:c000::/56. Todos os acessos a conteúdos em IPv6 não passarão pelo CGNAT, seguindo diretamente para a Internet e sendo registrado o log da conexão no seu servidor Radius, por exemplo. Já para o cliente acessar os conteúdos em IPv4, será necessário que os pacotes passem pela Caixa CGNAT, seja feita uma tradução do IP 100.64.10.50 para um IPv4 público, que no nosso exemplo é o 198.51.100.230.

Sempre que eu tiver que passar pela Caixa CGNAT e for feita uma tradução, será necessário armazenar esses dados através de logs que serão enviados para o nosso servidor de logs CGNAT em 2001:db8:c0ca:c01a::2.

Se você já tem IPv6 rodando em sua Operação, procure utilizar esse protocolo para se comunicar entre seus sistemas, não precisa ser um IPv6 Global, pode ser um endereço ULA (Unique Local Address) que utiliza o prefixo FC00::/7, dessa forma você vai inclusive economizar seus IPv4 públicos. O ULA seria o equivalente a usarmos prefixos IPv4 privados da RFC1918: 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12 e 192.168.0.0/16.

Lembre-se que segurança também é importante e se for usar IPs públicos, tanto em IPv4 quanto em IPv6, você precisa filtrar os acessos e garantir que só a sua gerência tenha acesso. Nesse nosso artigo não irei falar sobre filtro de pacotes e outros programas que juntos compõe um Firewall; Firewall não é um programa e sim um conceito, mas entenda que isso é muito importante para a saúde da sua Operação.








Definição do Sistema

Como comentei anteriormente nosso servidor de logs CGNAT irá utilizar softwares livres como solução e os principais estão listados abaixo:

  • Debian GNU/Linux 12 (Bookworm) amd64 com LVM (Logical Volume Manager).
  • Nfdump (Netflow).
  • Syslog-ng.
  • Pigz (compactação dos logs).

Hardware

Um servidor de logs não precisa ter uma alta capacidade de processamento, se você não estiver abusando dos recursos como por exemplo: muitas caixas de CGNAT enviando milhares de conexões via syslog. Agora uma coisa é certa de que você vai precisar: espaço em disco e que tenha uma ótima performance de I/O. Disco é de fato o ponto chave na solução e por isso não utilize discos usados de outros servidores e monitore sempre a saúde dos discos para não ser pego de surpresa. O hardware que você vai precisar, dependerá do tamanho da sua Organização e do volume de dados que você enviará para o seu servidor ou até mesmo servidores. Você poderia ter, por exemplo, um servidor de logs CGNAT em cada cidade que atender.

Outro detalhe importante: pense no crescimento do armazenamento dos dados e que em determinado momento você precisará expandir isso, seja adicionando mais um disco ou aumentando o uso em uma Cloud. Se você for montar uma infraestrutura própria, virtualizada e utilizando um storage, já é um bom começo.

Esse é um htop de um servidor virtualizado, que recebe milhares de requisições de envio de logs por segundo tanto de syslog, quanto de netflow:

Quanto à armazenagem desse sistema acima:

Esse é um sistema novo, com armazenamento de 6 meses de logs de CGNAT e sabendo-se que precisaremos armazenar pelo menos 1 ano de log sempre. Sim, esse espaço precisará de um novo aumento em breve através do uso do LVM. A sua realidade pode não ser essa e você pode necessitar de muito menos recurso que isso, então comece por baixo mas pensando em possível expansão de espaço de disco:

Hardware do servidor
CPU Memória Disco
2.4Ghz 4 cores 8G DDR4 8Tb

Preparando o Servidor

Quando for instalar o Debian, não esqueça de configurar o LVM na área de armazenagem dos logs e instalar o mínimo de pacotes que puder, deixando apenas os pacotes básicos e o servidor ssh para acesso remoto. Na imagem abaixo deixe tudo desmarcado e selecione apenas os 2 últimos itens.

Após a instalação vamos deixar o nosso /etc/apt/sources.list da seguinte forma:

deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware
deb http://deb.debian.org/debian-security/ bookworm-security main contrib non-free non-free-firmware
deb http://deb.debian.org/debian bookworm-updates main contrib non-free non-free-firmware

Eu costumo instalar alguns pacotes além dos necessários para ter algumas ferramentas à mão:

# apt install net-tools htop iotop sipcalc tcpdump curl gnupg rsync wget host dnsutils mtr-tiny bmon sudo tmux whois syslog-ng nfdump nfdump-sflow pigz chrony irqbalance
# systemctl enable irqbalance
# echo "vm.swappiness=10" >> /etc/sysctl.conf
# sysctl -p

Acertando o horário do servidor

Caro leitor, não existe nada tão importante em um sistema de armazenagem de logs, do que a data e horário estarem devidamente certos e sincronizados. Se isso estiver errado, seu sistema será impreciso e não conseguirá identificar corretamente quando os eventos ocorreram realmente. Por isso vou deixar uma dica de como eu trabalho, mas fica apenas como dica.

Eu utilizo sempre horário UTC nos servidores de logs, isso porque podemos trabalhar com sistemas espalhados em diversos lugares, em fusos horários diferentes e também forço no syslog-ng para registrar o log sempre no horário do servidor de logs, ao invés do horário enviado pelo equipamento remoto. Isso porque o equipamento remoto pode estar com data e hora errados, mas no momento que os logs são enviados para o nosso servidor de logs, ele fica registrado corretamente, mesmo que em horário UTC.

Edite o arquivo /etc/chrony/chrony.conf e comente a linha com "pool 2.debian.pool.ntp.org iburst" e na sequência adicione as linhas conforme abaixo:

#pool 2.debian.pool.ntp.org iburst
server a.st1.ntp.br iburst nts
server b.st1.ntp.br iburst nts
server c.st1.ntp.br iburst nts
server d.st1.ntp.br iburst nts

Salve o arquivo e reinicie o serviço chronyd:

# systemctl restart chronyd.service

Agora vamos configurar o tzdata para horário UTC:

# timedatectl set-timezone UTC

Configurando o Syslog-ng

Todas as configurações que faremos nesse artigo será para armazenar os logs de forma estruturada e que facilite mais as buscas e limpeza do sistema quando necessário.

A estrutura de armazenamento que utilizo para o syslog é esta abaixo:

/var/log/cgnat/syslog/<HOSTNAME>/<ANO>/<MES>/<DIA>/server-<HORA>.log

# mkdir -p /var/log/cgnat/syslog

Onde:

  • <HOSTNAME> é o nome do host, recebido do equipamento que estamos coletando nossos dados.
  • <ANO>, <MES>, <DIA> e <HORA> são usados pelo syslog-ng para automaticamente criar essa estrutura de diretórios e arquivos de forma organizada.

Dessa forma fica mais rápido de localizar quem usou determinado IP e em que data e hora. Repare que os arquivos são criados por hora de 00 até 23 facilitando a localização da informação:

Observação: o /var/log/cgnat precisa estar dentro do volume LVM conforme comentamos porque é nele que serão armazenados todos os logs recebidos.

Para configurarmos essa estrutura vamos alterar primeiramente o arquivo /etc/syslog-ng/syslog-ng.conf e mudar o options para esse abaixo:

options { chain_hostnames(off); flush_lines(0); use_dns(no); use_fqdn(no); keep_hostname (yes);
          dns_cache(no); owner("root"); group("adm"); perm(0640); dir_perm(0700); create_dirs (yes);
          stats_freq(0); bad_hostname("^gconfd$"); keep-timestamp(off);
};

Vamos criar um arquivo de configuração que vai ser o responsável por receber e criar a estrutura acima. Crie o seguinte novo arquivo /etc/syslog-ng/conf.d/isp.conf com o conteúdo de exemplo abaixo:

source s_net {
   udp6(ip("2001:db8:c0ca:c01a::2") port(514));
};

destination d_ce { file("/var/log/cgnat/syslog/${HOST}/${YEAR}/${MONTH}/${DAY}/server-${HOUR}.log"); };

filter f_ce { facility(daemon) and not message(".*SSH.*"); };
filter f_ce_ipv6 { facility(syslog); };

log { source(s_net); filter(f_ce); destination(d_ce); };
log { source(s_net); filter(f_ce_ipv6); destination(d_ce); };

Agora reiniciamos o serviço e o sistema começará a tratar os dados recebidos conforme especificamos acima:

# systemctl restart syslog-ng.service

Compactando os logs de syslog diariamente

Abaixo deixo um script que irá varrer diariamente seus arquivos de logs e compactá-los automaticamente. Não se preocupe se quiser rodá-lo manualmente algumas vezes, ele só compacta o que ainda não tiver sido compactado e sempre os logs do dia anterior.

# mkdir -p /root/scripts

Daremos o nome do script de /root/scripts/compacta_syslog.sh e o seu conteúdo está logo abaixo:

#!/bin/bash
 
ANO=$(date -d "-1 day" '+%Y')
MES=$(date -d "-1 day" '+%m')
DIA=$(date -d "-1 day" '+%d')
for lista in /var/log/cgnat/syslog/*; do
   if [ -d $lista/$ANO/$MES/$DIA ]; then
        pigz -p4 --fast $lista/$ANO/$MES/$DIA/*
   fi
done
# chmod 700 /root/scripts/compacta_syslog.sh
# echo "00 4    * * *   root    /root/scripts/compacta_syslog.sh" >> /etc/crontab

Configurando o Netflow

Para receber e armazenar os logs em netflow usaremos o nfcapd do pacote nfdump. O programa possui parâmetros que já facilitam nossa vida criando uma estrutura de diretórios de forma organizada e fácil de buscar o que precisamos. Procure configurar o Netflow do equipamento que enviará os logs para versão 9.

Precisaremos ter em mãos, os seguintes dados do equipamento para liberação da coleta dos dados em nosso servidor:

  • HOSTNAME do equipamento.
  • Porta UDP onde será recebido o flow daquele equipamento. Para cada equipamento que for enviar um flow, você precisa especificar uma porta UDP dedicada para ele.

Com esses dados montamos a linha de comando que ficará escutando o flow. Abaixo um exemplo:

/usr/bin/nfcapd -D -t 3600 -S 1 -B 200000 -z=lz4 -I RJO-DC01-CGNAT-01 -w /var/log/cgnat/flow/RJO-DC01-CGNAT-01 -p 2055

Onde:

HOSTNAME é o RJO-DC01-CGNAT-01

PORTA UDP é 2055

O “-D” diz ao programa rodar como daemon, “-t” dizem de quanto em quanto tempo o arquivo é rotacionado. Nesse caso 3600s, ou seja, de hora em hora. O “-S 1” diz para arquivar os logs no formato year/month/day automaticamente. O “-B 200000” é para aumentar o buffer e não termos problemas com perdas de flow. O “-y” comprime o flow em LZ4. O “-w” é onde passamos o diretório base. O “-p 2055” a especificação da porta udp que irá receber o flow daquele equipamento.

Precisamos sempre antes de executar o comando, criar o diretório base, senão o serviço não ira levantar. No exemplo acima faremos assim:

# mkdir -p /var/log/cgnat/flow/RJO-DC01-CGNAT-01

Com os dados dos equipamentos podemos montar um arquivo /etc/rc.local e colocar uma entrada por linha conforme as regras que passei acima. Então nosso arquivo ficaria assim:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
  
/usr/bin/nfcapd -D -t 3600 -S 1 -B 200000 -z=lz4 -I RJO-DC01-CGNAT-01 -w /var/log/cgnat/flow/RJO-DC01-CGNAT-01 -p 2055
 
exit 0
# chmod +x /etc/rc.local

Podemos fazer um reboot no sistema e checar com um ps afx, se nosso serviço está rodando como configuramos. Como estamos nos baseando no nosso diagrama, só teríamos esse servidor enviando flow e no seu ambiente de produção provavelmente existirão outros equipamentos fazendo CGNAT. Nesse caso só ir adicionando novas linhas do nfcapd mas prestando atenção nos parâmetros e principalmente na porta UDP.

Compactando os logs de netflow diariamente

Assim como fizemos no syslog-ng, configuraremos um script que compactará diariamente os logs armazenados via netflow.

Vamos criar o script /root/scripts/compacta_flow.sh e adicioná-lo também ao nosso cron para rodar diariamente. Abaixo o conteúdo do script:

#!/bin/bash
 
ANO=$(date -d "-1 day" '+%Y')
MES=$(date -d "-1 day" '+%m')
DIA=$(date -d "-1 day" '+%d')
for FOLDER in /var/log/cgnat/flow/*; do
  if [ -d $FOLDER/$ANO/$MES/$DIA ]; then
     cd $FOLDER/$ANO/$MES/$DIA
     echo "Compactando: ${FOLDER}/$ANO/$MES/$DIA/"
     pigz -p4 --fast nfcapd*
  fi
done
# chmod 700 /root/scripts/compacta_flow.sh
# echo "00 4    * * *   root    /root/scripts/compacta_flow.sh" >> /etc/crontab

Fazendo consultas do flow armazenado

A forma de consultar dependerá de como você configurou sua Caixa CGNAT. Lembra que comentei que existe uma configuração de flow que pode ocupar muito espaço em disco e que devemos evitá-la? Abaixo mostro um exemplo. Repare também que estamos usando a mesma estrutura de organização de diretórios e arquivos, que usamos na configuração do syslog:

# cd /var/log/cgnat/flow/RJO-DC05-CGNAT01/2022/08/04
# nfdump -r nfcapd.202208042300
2022-08-04 22:59:59.992     ADD  Ignore TCP     100.64.202.178:50419 ->          0.0.0.0:0      170.XXX.XXX.XXX:50419 ->          0.0.0.0:0            0        0
2022-08-04 23:00:31.369  DELETE  Ignore TCP     100.64.202.178:50419 ->          0.0.0.0:0      170.XXX.XXX.XXX:50419 ->          0.0.0.0:0            0        0
2022-08-04 23:13:34.417     ADD  Ignore UDP     100.64.199.100:50419 ->          0.0.0.0:0      170.XXX.XXX.XXX:50419 ->          0.0.0.0:0            0        0
2022-08-04 23:15:35.908  DELETE  Ignore UDP     100.64.199.100:50419 ->          0.0.0.0:0      170.XXX.XXX.XXX:50419 ->          0.0.0.0:0            0        0
2022-08-04 23:19:48.215     ADD  Ignore TCP     100.64.199.100:50419 ->          0.0.0.0:0      170.XXX.XXX.XXX:50419 ->          0.0.0.0:0            0        0
2022-08-04 23:20:19.283  DELETE  Ignore TCP     100.64.199.100:50419 ->          0.0.0.0:0      170.XXX.XXX.XXX:50419 ->          0.0.0.0:0            0        0
2022-08-04 23:41:02.639     ADD  Ignore UDP      100.64.204.78:50419 ->          0.0.0.0:0      170.XXX.XXX.XXX:50419 ->          0.0.0.0:0            0        0
2022-08-04 23:43:02.435  DELETE  Ignore UDP      100.64.204.78:50419 ->          0.0.0.0:0      170.XXX.XXX.XXX:50419 ->          0.0.0.0:0            0        0

Nesse exemplo acima temos o arquivo nfcapd.202208042300 e esses arquivos são gerados de hora em hora com os dados recebidos. O nome dele é composto pelo ano, mês, dia e a hora de rotação que nesse caso seria 23:00. Podemos reparar que a cada solicitação de conexão do cliente, é enviado um log da porta que foi utilizada, nesse nosso exemplo a porta 50419 TCP e UDP. Isso realmente ocupa muito espaço em disco.

Agora vamos olhar para um BPA que está configurado para trabalhar com alocação dinâmica de blocos de portas. A consulta é um pouco diferente porque precisa ser formatada:

# cd /var/log/cgnat/flow/CGN-BOX1-SPO01/2023/01/15
# nfdump -o "fmt:%ts %nevt %pr %sa %nda %nsa %pbstart %pbend" -r nfcapd.202301151100

Podemos reparar que na imagem temos uma coluna com os IPs privados dos clientes, uma outra com os IPs públicos ofuscados e uma última coluna com os blocos de portas alocados e desalocados. Algumas pessoas me perguntam qual a relação de portas alocadas que costumo utilizar: eu tenho trabalhado com a configuração de blocos de 256 portas, podendo entregar até 16 blocos por cliente (4096 portas). Isso porque na maioria dos casos, nossos clientes não são heavy users e consomem poucas portas durante o acesso à Internet. Dessa forma podemos ter uma boa economia de recursos IPv4 e nos piores casos entregar até 4096 portas para o cliente.

Para consultarmos um arquivo que foi compactado, basta trocarmos no comando o cat pelo comando zcat e o restante segue exatamente igual.

Configurando um Mikrotik RouterOS para envio de logs IPv6

Infelizmente o Mikrotik até a versão 6.x pelo menos, não sei se já corrigiram na versão 7, não enviava para o Radius o registro do IPv6 Prefix Delegation entregue para o cliente e por isso se você receber uma solicitação de Quebra de Sigilo com logs em IPv6, dificilmente você irá conseguir identificar o cliente estando nessa situação. Para isso trago uma solução que veio da contribuição do Bruno Viviani neste artigo dele.

Abaixo exemplos de como configurar via Winbox. Vamos criar uma nova Action chamada servlogs com os exemplos abaixo referentes ao nosso diagrama:

Após isso modificamos a Rule warning e apontamos para o nosso servlogs:

Por último temos que adicionar no profile do PPPoE, na parte de scripts em On Up:

:local interfaceName [/interface get $interface name];
delay 60;
:local WANIPv6 [/ipv6 nd prefix get value-name=prefix [find interface=$interfaceName]];
:local PDIPv6 [/ipv6 dhcp-server binding get value-name=address [find server=$interfaceName]];
:log warning "$interfaceName - WAN: $WANIPv6 - PD: $PDIPv6"

Nos logs aparecerão algo assim:

Jan 25 02:26:56 SPO-SEDE-CE02 <pppoe-jose> - WAN: 2804:0db8:8005:5668::/64 - PD: 2804:0db8:8050:7b00::/56
Jan 25 02:37:08 SPO-SEDE-CE02 <pppoe-maria> - WAN: 2804:0db8:8005:5669::/64 - PD: 2804:0db8:8050:a000::/56

Conclusão

Como podemos perceber é bem simples de localizarmos e consultarmos os logs, mas para isso funcionar precisamos saber onde cada prefixo público está sendo utilizado, em que Caixa CGNAT. Para esse controle eu indico o phpIPAM ou similar mas isso é assunto para um outro artigo.

Essa documentação foi útil? Compartilhe, divulgue e ajude outras pessoas. Meus contatos podem ser vistos aqui.