Mostrando postagens com marcador administração. Mostrar todas as postagens
Mostrando postagens com marcador administração. Mostrar todas as postagens

domingo, 27 de fevereiro de 2011

Perl - Realizando consultas SNMP com o módulo Net::SNMP

O SNMP é um protocolo bastante utilizado em sistemas voltados para gerência e administração permitindo coletar as mais variadas informações de servidores, equipamentos de telecomunicações ou qualquer outro equipamento que o implemente. De maneira geral quando o equipamento implementa pelo menos duas RFCs já é suficiente para coletarmos a maioria das métricas básicas. São elas a RFC1213 ou MIBII e a RFC2790 ou Host Resources MIB. Estas duas RFCs permitem o monitoramento de informações relativas a rede e aos recursos do equipamento como cpu, memória, disco, entre outras.

Com tantas métricas e possibilidades de monitoramento utilizando este protocolo, algumas vezes me deparo (acredito que não só eu) com solicitações para criações de scripts para coleta de informações. Antes eu simplesmente os criava me utilizando da facilidade de jogar o conteúdo de um comando executado para dentro de uma variável. Isso pode ser feito sem problemas, porém você fica dependente de que aquele aplicativo esteja instalado no sistema. 

Pensando em criar algo utilizando uma forma mais elegante, comecei a tentar utilizar o módulo do Perl chamado de Net::SNMP. Este módulo você também precisa instala-lo, mas eu penso que o resultado final de um script fica bem mais profissional. Pois bem, no link acima você poderá dar uma olhada em suas possibilidades.

Quando eu fiz minhas primeiras tentativas de utilizar este módulo não consegui faze-lo da forma correta e nem entender corretamente seu funcionamento. Após comprar os livros que citei no meu artigo anterior, principalmente o primeiro que já esta comigo a algum tempo, consegui ter um entendimento melhor sobre a linguagem e por fim consegui usa-lo. Vi que esta dificuldade não foi somente comigo, inclusive amigos de trabalho acabaram por optar pela velha e tradicional forma de coletar estas informações, jogar o conteúdo de um comando para dentro de uma variável.

Então vamos por a mão na massa. Vamos começar a criar nosso script em Perl para coletar algumas informações:

use strict;
use Data::Dumper;
use Net::SNMP;

Estas linhas irão compor a parte inicial do seu script. Gosto de usar a primeira (use strict;) pois ela te obriga a ter uma forma de programar mais organizada. A segunda (use Data::Dumper;) permite analisarmos a estrutura de um hash e a terceira é o módulo que iremos utilizar para trabalhar aqui. Caso alguma destes módulos não exista você receberá uma mensagem de erro no momento de executar o script. Agora vamos criar uma lista de OIDs que vamos coletar e criar a sessão para coleta SNMP:

my @oids = qw/1.3.6.1.2.1.1.3.0 1.3.6.1.2.1.1.5.0 1.3.6.1.2.1.1.6.0/;
my ($session, $error) = Net::SNMP->session(
-hostname  => 'localhost',
-port      => '161',
-community => 'public',
);

Neste bloco fizemos o seguinte. Definimos os OIDs que vamos coletar (que são respectivamente sysUpTime, sysName e sysLocation) e definimos de quem iremos coletar. Agora vamos executar nossa leitura nos OIDs que definimos na lista no passo anterior e visualizar os resultados:

my $result = $session->get_request( -varbindlist => \@oids,);
$session->close();
print Dumper \%{$result};

Com estes comandos você deverá ver algo como o seguinte:

$VAR1 = {
          '1.3.6.1.2.1.1.6.0' => 'Qualquer Lugar',
          '1.3.6.1.2.1.1.5.0' => 'andre-sti',
          '1.3.6.1.2.1.1.3.0' => '51 minutes, 30.01'
        };

Com isso podemos ver os resultados que coletamos via SNMP nos OIDs que definimos no primeiro passo. Aquele "print Dumper \%{$result}" mostra este resultado pois quando executamos o "$session->get_request" ele retorna um hash, porém a única informação que temos deste hash é sua referencia que fica guardada dentro da variável $result. Se você executar um print na variável $result verá algo assim:

HASH(0x304a4a4)

Esta é a referencia do hash criado pelo Net::SNMP. Para de fato imprimirmos os resultados em um laço foreach por exemplo, temos que fazer o seguinte:

foreach my $oid (@oids) {
chomp($oid);
print "$result->{$oid}\n";
}

Com isso você imprime o resultado da requisição SNMP criada! Acho que este foi o "pulo do gato" que antes não conseguia entender para poder de fato utilizar todo o potencial deste módulo. Este foi um exemplo simples mas espero que com ele quem teve alguma dificuldade em usa-lo agora consiga dar seus passos para criar seus scripts, coletando as métricas SNMP diretamente, sem o uso de aplicativos do sistema operacional. Neste link você pode acessar o script completo que fizemos aqui!

Espero que estas dicas ajudem a quem precisar começar a utilizar este módulo muito útil que o Perl possui. Como sempre, caso existam dúvidas, sugestões, elogios ou críticas podem escrever ou postar aqui mesmo no blog!

sábado, 26 de fevereiro de 2011

Perl vs Shell Script

Desde que comecei a trabalhar com sistemas operacionais, principalmente o Linux, tive a necessidade de começar a usar scripts. Acredito que para uma grande parcela, como foi no meu caso, o início se deu usando Shell Script em bash. Penso que para uma "linguagem", se é que se pode chamar assim, é bastante poderosa permitindo fazer tarefas com certa complexidade.

Recentemente por uma mudança de emprego meu maior foco de contato deixou de ser o Linux e passei a usar bastante a plataforma Microsoft e um pouco Solaris. O primeiro impacto que isso me causou foi o problema de que os scripts criados anteriormente já não poderiam ser utilizados na maioria dos casos. 

Sempre passei perto do perl, mas nunca me enveredei a ponto de aprender a usa-lo. Mas depois de algum tempo e de muitas necessidades por causa do meu novo ambiente de trabalho não teve jeito, precisei começar a usar o perl. Confesso que foi uma experiência bastante positiva. Claro que para sair da inércia não utilizei somente da internet, adquiri um livro e este foi de extrema importância para meu aprendizado inicial. O livro que comprei foi este Learning Perl, quinta edição.

Minhas primeiras linhas de código foram bastante simples mas já consegui vislumbrar que seu potencial é muito grande e consegui fazer coisas de forma mais eficiente, sem contar que existe módulos preparados para comunicações especializadas como leituras SNMP (sem precisar usar o snmpget ou snmpwalk enviando sua saída para uma variável), conexão com banco de dados, sem ter que fazer mirabolancias. O mais legal é pensar em sua portabilidade. Você pode criar um script em um ambiente Linux e com poucas alterações pode te-lo rodando em outro ambiente, como no meu caso em Windows!

Tenho que confessar que minha transição não foi fácil pois já estava "viciado" em Shell Script. Com um pouco de esforço posso dizer que migrei para perl, e digo, foi bastante positivo. Quero começar a postar algumas coisas que venho aprendendo nesta linguagem. Aprendizado este que tem sido fruto de pesquisa na internet, no livro que mencionei acima e na prática constante, errando e acertando. Pensando em me aperfeiçoar um pouco mais fiz a compra de mais um livro, este agora voltado para administração de sistemas e mostrando técnicas de como faze-lo, o livro que comprei foi este Automating System Administration with Perl: Tools to Make You More Efficient. Estes livros foram adquiridos no Amazon pois não os encontrei aqui no Brasil. O legal é que eles entregam aqui no Brasil por um custo de frete bastante acessível.

Bom, esta sendo legal voltar a postar aqui neste blog. Caso alguém tenha alguma idéia sobre o assunto que estou escrevendo aqui sinta-se a vontade para conversarmos e trocarmos experiências. Acho isso muito produtivo e é uma forma de aprendizado!

Um grande abraço a quem passar por aqui!

quarta-feira, 24 de setembro de 2008

OpenVPN - grafico de usuarios conectados e trafego VPN com Cacti, SNMP e Shell Script

Faz algum tempo fiz um artigo sobre como instalar a OpenVPN (OpenVPN para acesso remoto (road-warrior)) para acesso remoto e até então, eu não tinha visto nada para estar monitorando minha VPN, onde fosse possível ter informações de quantos usuários estão conectados em um determinado momento ou ainda quanto tráfego passou por ela. Não estou dizendo o tráfego da interface eth0, eth1, e sim o que é transmitido dentro dos túneis criptografados onde representará realmente o que um usuário utilizou.

Pensando neste cenário iniciei uma busca por alternativas, a interface de gerenciamento da OpenVPN não é muito amigável e também não ajuda muito para tirar informações utilizando algum script. Acabei encontrando que a própria OpenVPN escreve um arquivo seu status atual a cada determinado tempo. Em minha instalação encontrei este arquivo executando um ps para visualizar os processos e verifiquei o parâmetro abaixo:
--status /var/run/openvpn.openvpn.status 10
Isso indica que o arquivo será escrito no diretório acima e atualizado a cada 10 segundos. Creio que é tempo suficiente para ter um arquivo que possa refletir o estado atual da nossa VPN! Ele é assim:

OpenVPN CLIENT LIST
Updated,Tue Sep 23 14:17:25 2008
CN,Real Addr,Bytes Rece,Bytes Sent,Connected Since
andre,216.106.173.161:1772,24215,26619,Tue Sep 23 13:27:50 2008
ROUTING TABLE
Virtual Address,Common Name,Real Address,Last Ref
10.10.20.2,andre,216.106.173.161:1772,Tue Sep 23 13:27:59 2008
GLOBAL STATS
Max bcast/mcast queue length,0
END

A linha que nos interessa é a 4 (de cima para baixo) onde estão descritas informações sobre os usuários conectados. Ali é possível encontrar os bytes enviados/recebidos e podemos também saber quantos usuários estão conectados em um determinado momento, ou seja, temos as informações que necessitamos. Minha necessidade era a de disponibilizar esse gráfico da maneira mais fácil, e como aqui temos uma instalação do Cacti essa foi a melhor opção, porém ele não está instalado no mesmo servidor da VPN, obviamente, então eu precisava transmitir esses dados através da rede. A topologia neste caso era a seguinte:


Pesquisando na internet encontrei uma funcionalidade do agente snmpd onde é possível executar um Shell Script e retornar essas informações em um OID (Object IDentifier ou Identificador de Objeto) reservado para uso privado. Como meu servidor OpenVPN já possuía este instalado não foi necessário nenhum software adicional, só era necessário ajustar a configuração. O arquivo final ficou dessa forma:
rocommunity public
syslocation Brasil
syscontact Andre Zenun
extend .1.3.6.1.4.1.2021.50 vpnstats /bin/bash /etc/snmp/openvpn_statistics.sh
A linha responsável por fazer a transferência do resultado do script para o agente é a extend. O OID que está ali foi utilizado em um exemplo dentro do arquivo de configuração e sempre deve ser este. Após o identificador é necessário dar um nome, que no meu caso foi vpnstats um programa a ser executado, /bin/bash, e um parâmetro para ele /etc/snmp/openvpn_statistics.sh. É muito importante disponibilizar este arquivo em um local onde o usuário do daemon snmp possa executar. No meu caso precisei acrescentar uma entrada no arquivo sudoers para que fosse possível a execução do comando egrep. O script utilizado está disponibilizado neste link. A entrada no arquivo de configuração /etc/sudoers é muito simples:
snmp ALL = NOPASSWD:/bin/egrep
Muito bem, temos o script, configuramos o sudoers, acrescentamos a linha no arquivo de configuração do snmp e reiniciamos nosso agente. Com isso é possível executar um comando snmp verificando a saida do nosso script que será mais ou menos assim:
andre@linux:~$ snmpwalk -v2c -c public ipvpn -On .1.3.6.1.4.1.2021.50

.1.3.6.1.4.1.2021.50.2.1.2.8.118.112.110.115.116.97.116.115 = STRING: "/bin/bash"

.1.3.6.1.4.1.2021.50.2.1.3.8.118.112.110.115.116.97.116.115 = STRING: "/etc/snmp/openvpn_statistics.sh"

.1.3.6.1.4.1.2021.50.3.1.1.8.118.112.110.115.116.97.116.115 = STRING: "1 180156 986279"
Essa saída esta resumida porém a informação importante está em vermelho que é o OID que iremos utilizar e a resposta que iremos obter (número de usuários e bytes trafegados)! Bom, com isso feito, terminamos com a parte do lado do servidor OpenVPN, agora precisamos ir para o servidor onde está instalado o Cacti. Naquele lado criei outro script que irá executar a consulta SNMP e retornará a resposta. Eu disponibilizei o script neste link. No meu servidor eu o coloquei neste diretório /usr/share/cacti/site/scripts, verifique onde esta este diretório em sua instalação. Com tudo no lugar você pode fazer um teste executando o script na mão:
andre@linux:~#./vpn_stats.sh 10.10.10.1 public 1
vpnUsers:1 vpnBytesIn:180156 vpnBytesOut:986279
Essa será a resposta que o Cacti receberá. Para adicionar o script siga este tutorial disponível no site do Cacti onde é ensinado como partir de um Shell Script até chegar no gráfico. Algumas recomendações na hora de criar a base de dados rrd no Cacti é para o DS de usuários utilizar Gauge e para os bytes utilizar Derive com valor mínimo em zero. Com os procedimentos feitos, você poderá ter gráficos de sua vpn como esses:



Esses gráficos foram retirados do meu servidor Cacti mostrando trafego de testes em minha VPN e eu conectado ali! O Shell Script que é utilizado pelo Cacti pode facilmente ser adaptado para alimentar uma base de dados rrd. Não é necessário utilizar este front-end para o RRDTools. Caso você tenha alguma dificuldade com essa ferramenta não deixe de conferir este artigo RRDTool - Você sabe trabalhar com ele? para aprender um pouco mais sobre ele!

Caso você tenha alguma sugestão, dúvida, crítica por favor não deixe de entrar em contato! Sua opinião é importante! Espero que com este artigo tenha conseguido contribuir com idéias úteis para a administração de seu servidor!

sexta-feira, 19 de setembro de 2008

RRDTool - você sabe trabalhar com ele?

Esta é uma ferramenta que acredito eu ser uma das mais utilizadas em todo o mundo! Vemos sua utilização em muitos aplicativos open-source como Cacti, Munin, Zenoss, Torrus, Smokeping entre muitos outros. Você pode ver uma lista deles aqui! RRDTools foi desenvolvido por Tobias Oetiker.

Basicamente é possível criar uma base de dados onde serão armazenadas informações como temperatura ou os bytes trafegados por uma interface ao longo do tempo. Qualquer coisa que possui um valor numérico você pode guardar aqui. Primeiramente é necessário instalar esta ferramenta, caso ela já não esteja. Atualmente eu tenho servidores baseado em Debian, então minha instalação é feita com a ferramenta aptitude. Consulte a ferramenta de sua distribuição (yast, emerge, rpm) por este pacote!
aptitude install rrdtool
Com este comando será instalado o aplicativo e suas dependencias serão satisfeitas. Depois da instalação você verá que ele possui algumas funções. Aqui iremos falar de algumas somente que são:
  • create: cria uma nova base de dados rrd
  • update: atualiza com novos valores uma base de dados rrd
  • graph: cria um grafico apartir de uma base de dados rrd
  • fetch: possibilita extrair informação de uma base de dados rrd
  • info: mostra informações sobre uma base de dados rrd
Existem outras funções e elas estão descritas (em inglês) neste site. Uma característica muito importante deste tipo de base de dados é que possui um comportamento cíclico, isso faz com que ela mantenha seu tamanho fixo e permite um planejamento de espaço em disco. Claro que com isso se faz necessário a definição de quanto tempo se deseja guardar uma informação, pois quando não existir mais espaço disponível, automaticamente as informações mais antigas serão sobrescritas. Em minha opnião acredito ser uma forma bastante escalonável de se manter dados armazenados por um período.

A forma que você utilizará para "alimentar" esta base de dados de informações (Data Sources) depende do que você possui e da forma que você julgar mais prático. O mais comum creio eu é por consultas SNMP (Simple Network Management Protocol) onde é possível verificar a memória utilizada por um sistema, quantos usuários estão conectados em um sistema operacional, e muitas outras possibilidades. Para isso pode-se usar um Script Shell, Perl, PHP. O fato é você conseguir passar valores para esta ferramenta, a forma você decide! :D

Tudo muito simples e muito bonito, porém as diversas informações que você possui em geral podem representar tipos de dados distintos, como por exemplo, temperatura de uma cpu e os bytes trafegados em uma interface! Isso é muito importante no momento de criar uma base de dados rrd pois definirá o comportamento de como esses dados serão interpretados e consolidados dentro dela. Com isso em mente, temos disponível para trabalhar os seguintes tipos de dados com características específicas:
  • COUNTER - Este tipo espera que o valor sempre aumente, ou seja, a diferença do valor atual e o anterior é maior que zero, e salva a variação deste sobre o tempo.
  • DERIVE - Este é muito similar ao comportamento do COUNTER porém ele permite valores negativos.
  • ABSOLUTE - Este tambem salva a variação de valores porém ele sempre considera que o anterior é zero.
  • GAUGE - Este possui um comportamento diferente e não faz nenhum tipo de matematica com o valor recebido, ele simplesmente insere o valor como ele chega!
  • COMPUTE - Este armazena um valor oriundo de uma fórmula que usa valores de outros dados definidos dentro de um arquivo rrd.
As informações dentro de um arquivo rrd são armazenadas efetivamente em arquivos RRA (Round Robing Archive). São estas estruturas que terão os espaços para armazenar dados. Antes de avançarmos um pouco mais é necessário entender duas definições utilizadas pelo RRDTools que são os PDPs (Primary Data Point) e CDPs (Consolidated Data Point). Quando um novo valor é inserido ele recebe a classificação de PDP, ou seja, enviamos um determinado valor para essa base de dados e se cria um PDP, porém um CDP é composto por um número pré determinado de PDPs. Uma nova informação só é inserida quando se torna um CDP!

Com estas informações que temos até agora podemos entender um pouco sobre essa poderosa ferramenta de armazenamento de dados, porém, existem alguns detalhes importantes que são utilizados antes de inserir definitivamente uma nova informação dentro de um arquivo rrd que são as funções de consolidação, o fator xff, steps e rows:
  • step: aqui é definido quantos PDPs são necessários para formar um CDP.
  • função de consolidação: é uma função aplicada nos valores quando atingir o número necessário de PDPs para criar um CDP. Ela pode ser AVERAGE, MIN, MAX, LAST.
  • fator xff: é a razão entre a quantidade de informação desconhecida (UNKN) e a de conhecida em um determinado intervalo (step), ou seja, quantos PDPs podem ser desconhecidos para formar um CDP.
  • rows: aqui é informado quantos CDPs serão armazenados.
Passando por tudo isso, uma informação consegue ser armazenada em um RRA e posteriormente plotada em um gráfico. Com isto entendido podemos passar dois novos conceitos usados nesta ferramenta que é o step (não é o mesmo que o anterior) e o heart beat. Como explicamos acima, esta é uma base de dados que guarda informação ao longo do tempo e ela recebe informações em intervalos de tempo pré determinados, o mais comum são 300 segundos (5min). Este step é utilizado na hora da criação da base de dados e é definido em segundos. O heart beat é utilizado no momento de se definir um DS (Data Source) e ele representa o tempo máximo que se esperará por um valor antes de inserir um valor desconhecido (UNKN) e geralmente esta configurado para 600 segundos (10min). Abaixo esta um exemplo para criar uma base de dados rrd que irá armazenar valores das variáveis SNMP ifInOctets e ifOutOctets:
rrdtool create interface.rrd \
--step 300 \
DS:in:COUNTER:600:0:U \
DS:out:COUNTER:600:0:U \
RRA:AVERAGE:0.5:12:24 \
RRA:MAX:0.5:12:24
Com este comando estamos dizendo algumas coisas:
  1. Crie (rrdtool create) um arquivo chamado interface.rrd
  2. Receberá informações a cada 300 segundos (--step 300)
  3. Com um Data Source chamado in, de tipo COUNTER, receberá informações com no máximo 600 segundos (se não UNKN), com valor mínimo em 0 e o valor máximo é desconhecido (U). O mesmo ocorrerá com o Data Source chamado out.
  4. Crie um RRA com função de consolidação AVERAGE, com um xff de 0.5%, forme um CDP quando acumular 12 PDPs e armazene 24 vezes.
  5. Crie um RRA com função de consolidação MAX com um xff de 0.5%, forme um CDP quando acumular 12 PDPs e armazene 24 vezes.
Ok!!!! Vamos traduzir um pouco isso ai, criaremos um arquivo com aquele nome, irá receber novos valores a cada 5 minutos e esperará no máximo até 10 minutos. Não recebendo nenhum valor novo irá colocar um valor especial chamado UNKN. Estamos criando dois arquivos RRA com funções de consolidação diferentes. Com o xff configurado para 0.5 e o step em 12, estamos dizendo que até 6 valores (12*0.5) podem conter UNKN. Com estes 12 valores aplicaremos uma função de média (AVERAGE) e armazenarei o resultado e com outra aplicarei a função de máxima (MAX) e também armazenarei o resultado. Os dois armazenarão 24 valores. Fazendo as contas 300*12*24 chegamos ao valor 86400 segundos ou 1 dia. Será necessário um dia completo para encher este arquivo rrd. Se você criar uma base de dados com esta configuração levará uma hora (300*12) para que seja possível ter alguma informação dentro da base de dados e que apareça em um gráfico.

Bom já temos bastante informação sobre as base de dados rrd até agora, porém ainda não vimos como inserir informações nela. É um procedimento bem simples e iremos usar a segunda função que apresentamos acima que é a update. Com esta função iremos inserir novos dados a cada 5 minutos (nossa base de dados espera isso, mas pode ser diferente). O comando para fazer isso é o seguinte:
rrdtool update interface.rrd N:32378634:U
O que isto fará é o seguinte, atualizará o arquivo interface.rrd com um valor conhecido e outro desconhecido (fiz assim só para dar um exemplo) e a hora de atualização será a atual (N). Com isso teremos um novo PDP dentro desta base de dados. Cada RRA irá receber estes valores e acumulará até alcançar o número de steps configurado, aplicando então sua função de consolidação.

Se você quiser criar uma base de dados para armazenar um tempo específico são necessários alguns passos e cálculos. Vamos simular aqui que precisamos de uma base de dados que guarde informação por um ano completo e que antes de criar uma entrada nova (CDP) dentro do nosso RRA serão necessários 4 PDPs (steps) e a coleta será a cada 300 segundos ou 5 minutos. Vamos primeiro descobrir quantos segundos possui um ano:
1 ano -> 365 dias -> 8760 horas -> 525600 segundos
Um ano é isso ai, 525600 segundos, então podemos chegar na seguinte fórmula:
((525600)/(4*300)) = 438
O resultado desta fórmula nos permite criar uma base de dados para nossa necessidade:
rrdtool create interface2.rrd \
--step 300 \
DS:in:COUNTER:600:0:U \
DS:out:COUNTER:600:0:U \
RRA:AVERAGE:0.5:4:438
Este é um assunto bastante comprido e só estamos no começo de sua abordagem porém acredito que o básico e o início teórico são muito importantes para se avançar. Espero estar mostrando mais desta ferramenta pois é muito poderosa e útil para o dia a dia de um administrador de sistemas.

Como sempre, se existir qualquer sugestão, crítica, dúvida ou ainda uma correção, podem entrar em contato comigo!

terça-feira, 9 de setembro de 2008

Iptables - marcação de pacotes para qos e/ou roteamento

Neste artigo irei mostrar como utilizar o iptables para marcar pacotes (qualquer um que você consiga enquadrar em uma regra de iptables) para usar uma determinada tabela de roteamento do linux, no caso de você ter mais de um link, ou ainda que use algumas regras definidas de QoS. Com este documento não tenho o objetivo de mostrar como criar as regras de qualidade de serviço, este será tema de um outro artigo.

Existe um tutorial muito bom que foi escrito em inglês e hospedado no site Linux Advanced Routing and Traffic Control onde ele ensina técnincas de roteamento, manipulação das tabelas e a criação de regras para alocar um certo tipo de trafego a um link específico. É uma excelente fonte de pesquisa e foi deste site onde aprendi muito do conteúdo que sei hoje sobre este tema.

O linux permite que você coloque uma marcação no pacote para posterior uso como roteamento, qos ou ainda os dois juntos! Esta marca só esta presente a nível de kernel, ou seja, quando o pacote é enviado para o meio de rede ela já não existe! Então não adianta querer marcar os pacotes com a técnica que vamos explicar aqui para identificar o pacote em um outro servidor em sua rede. Uma marca que persiste no meio de rede é o do ToS.

Com o iptables podemos fazer uma serie de comparações nos pacotes como já vimos em outros artigos e as marcas que usaremos podem ser verificadas ou "escritas" em um determinado pacote. Quando queremos verificar qual marca um pacote possui é possível faze-lo em qualquer tabela do iptables, porém para marca-lo só na mangle como veremos a seguir:
iptables -t mangle -A PREROUTING -i eth0 -j MARK --set-mark 0x1
iptables -t filter -A FORWARD -m mark --mark 0x1 -j ACCEPT

Se alguma tentativa de marcar um pacote fora da tabela mangle for feito um erro de argumento inválido será emitido. Fiz alguns testes para tentar descobrir qual o número máximo de marcas que se pode utilizar e cheguei a conclusão de que não pode ter mais do que 8 dígitos, ou seja 0x99999999 seria um valor máximo! Acho que é suficiente! Hehehe

Com essas possibilidades você pode criar uma estrutura de roteamento e/ou qos para sua rede podendo priorizar pacotes de serviços como http, smtp/pop, ftp, voip e deixar outros com menor prioridade utilizar regras mais restritas. Um comando importante neste cenário é o ip. Este comando faz parte do pacote iproute do linux e esta presente por padrão em quase todas as distribuições, se não estiver procure por este pacote! Com ele temos a possibilidade de mudar/configurar a tabela de roteamento do kernel do linux.

Como vimos, com o ip podemos trabalhar com as regras de roteamento do nosso linux e para gerenciarmos as regras de qos temos o tc. Com ele podemos criar filas de qos especializadas, diferentes da padrão utilizada pelo linux que é a pfifo_fast:
2: eth1: mtu 1500 qdisc pfifo_fast
Utilizando a marcação acima (0x1) podemos dizer que este pacote use uma tabela de roteamento específica e que use uma configuração de qos especial:
ip rule add from all fwmark 0x1 table link1
tc filter add dev eth1 protocol all parent 1:0 handle 0x1 fw classid 1:112
Eu tenho usado este tipo de configuração para ajustar regras de qos em minha rede pois aqui temos vários clientes usando um mesmo link de internet. Claro que aqui estou usando muitas regras e até scripts para gerar um bloco grande automaticamente. Este comando ip é muito poderoso e você pode fazer roteamento baseado na origem, destino, campo ToS e conseguir um controle bastante interessante em sua rede!

Outra forma de classificar os pacotes e aloca-los em uma regra de qos específica é utilizando o próprio iptables! Ele possui um alvo (target) especial que já coloca os pacotes em uma fila especial de qos que você criou! O comando é assim:
iptables -t mangle -A POSTROUTING -p tcp --dport 80 -j CLASSIFY 1:112
Uma ressalva é importante de ser feita aqui, esta regra só pode ser utilizada na tabela mangle na chain POSTROUTING! Este comando é bastante explicativo e irá se enquadrar com pacotes que usem tcp e tenham por destino a porta 80 (web) colocando este em uma regra de qos. Eu já fiz testes das duas formas, usando mark e classify, e obtive resultados melhores quando usando a primeira técnica (mark) para realizar qos.

Com participo do fórum da Under-linux.org, sempre vejo pessoas perguntando se é possível realizar qos para um determinado computador e/ou serviço que ele esta servindo, com estas técnicas é possível garantir/limitar banda, alocar tráfego em um determinado link para recursos em sua rede, ai é só questão de criatividade para estar criando as regras e fazer algo bem interessante!

Como sempre, se existir alguma dúvida, crítica ou sugestão por favor postem aqui neste fórum ou mesmo no meu perfil no site da Under-linux.org.


terça-feira, 2 de setembro de 2008

Iptables - compartilhando seu link de internet com SNAT ou MASQUERADE (Atualizado)

Como temos visto nos artigos anteriores o iptables é uma ferramenta muito poderosa e com conhecimento é possível criar regras melhores com o intuito de melhorar a segurança de sua rede interna. O que vou descrever aqui neste artigo não é muita novidade para pessoas que já estão acostumadas com seu uso, porém para aqueles que estão iniciando nesta poderosa ferramenta podem se sentir um pouco perdidos na hora de ter que implementar um firewall para compartilhar a internet. Espero que com este artigo possa abrir um pouco mais o horizonte dessas pessoas e mostrar que não é difícil criar seus próprios scripts de iptables que possam cumprir com todos os requisitos que necessitem!

Antes de tudo gostaria de mostrar aqui que existe um padrão para os endereços que podem ser utilizados dentro de uma rede interna! Já vi pessoas que usaram redes destinadas a uso na internet em suas redes locais. Pode ser que no inicio não tenha problema, mas pode ser que em um determinado momento você necessite de um recurso da internet que está presente nesta rede que esta sendo usada em sua lan, e como resultado, não irá conseguir acessa-lo! O documento guia para isto é a RFC1918 (procure por Private Address Space) e esta disponível para pesquisas. Para aqueles que querem saber de uma vez, o padrão é este:
10.0.0.0 - 10.255.255.255 (10/8 prefix)
172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
Com isto podemos nos guiar para criar nossa rede interna e saber que fora deste escopo estaremos usando uma rede que está disponível para uso na internet!

Se estamos falando aqui de compartilhar uma conexão de internet estamos falando de NAT (Network Address Translation), ou seja, queremos que endereços privados possam acessar recursos que geralmente estão fora da nossa rede local. Neste link está uma animação feita pela cisco onde descreve todo o processo! Bem interessante de se ver!

No iptables existe uma tabela específica para fazer este tipo de trabalho e ela tem um nome bem sugestivo que é nat! Nela é possível utilizar uma chain para fazer o serviço que é a POSTROUTING com dois possíveis alvos: SNAT e MASQUERADE! Cada um destes alvos pode ser utilizado para uma determinada necessidade.

O SNAT é muito útil para quando você tem por exemplo um ip público fixo ou ainda uma classe de ips públicos que foi dado a você pelo seu provedor! Por exemplo:
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j SNAT --to 200.200.200.200
Desta forma estamos dizendo que a rede de origem 192.168.0/24 terá o ip público 200.200.200.200! Com isso é possível ter vários ips válidos na interface externa de seu Linux (eth0:1, eth0:2) e poder escolher por onde sairá algum pacote que você possa enquadrar em uma regra de iptables! Como por exemplo, você poderia ter seus servidores (web, ftp, e-mail) saindo por um ip válido enquanto que sua rede local usaria outro! As regras ficariam mais ou menos assim:
# Servidores usam este ip 200.200.200.200
iptables -t nat -A POSTROUTING -m iprange --src-range 192.168.0.2-192.168.0.5 -j SNAT --to 200.200.200.200

# A lan usa este 200.200.200.201
iptables -t nat -A POSTROUTING -m iprange --src-range 192.168.0.20-192.168.0.80 -j SNAT --to 200.200.200.201
Este exemplo funciona muito bem no caso de você ter mais de um endereço ip publico e não usar um proxy, como o Squid. Se você estiver usando o squid, é necessário acrescentar umas linhas ao seu arquivo de configuração. No meu caso eu fiz o seguinte:
acl MinhaLAN src 10.10.10.0/255.255.255.0
acl Cliente1 src 10.10.11.0/255.255.255.0
acl Cliente2 src 10.10.12.0/255.255.255.248
http_access allow MinhaLAN
http_access allow Cliente1
http_access allow Cliente2
tcp_outgoing_address seuIpPublico MinhaLAN
tcp_outgoing_address seuOutroIpPublico Cliente1 Cliente2
O que faz o trabalho de usar diferentes endereços ip para as requisições http são as linhas tcp_outgoing_address. Este é um exemplo totalmente funcional e estou usando aqui em minha empresa! O funcionamento do MASQUERADE por outro lado é útil para quando você não sabe seu endereço ip público, como por exemplo, em uma rede onde a atribuição seja automática (DHCP)! Por exemplo:
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o ppp0 -j MASQUERADE
Com esta regra você não precisa se preocupar com o endereço ip externo do seu Linux. O iptables se encarregará de fazer o trabalho de NAT! Lendo no tutorial do IpSysctl eles fazem uma recomendação para que o parâmetro ip_dynaddr esteja habilitado evitando problemas em uma possível troca de ip de origem (por terminar o tempo de aluguel de um endereço)! Muito importante também não esquecer de habilitar o encaminhamento de ips no seu linux em ambos os casos:
echo "1" > /proc/sys/net/ipv4/ip_forward
É muito importante saber qual dessas opções melhor satisfaz seus requerimentos! Com essas instruções em mente podemos criar um script de iptables para compartilhar a internet:

#!/bin/bash
#
# Um firewall statefull com MASQUERADE
#

#=========================
# variaveis
#-------------------------
cmd=iptables
lan=eth1
wan=eth0

#=========================
# 1 - limpando iptables
# 2 - politica padrao
#-------------------------
$cmd -t filter -F
$cmd -t nat -F
$cmd -t mangle -F

$cmd -t filter -P INPUT DROP
$cmd -t filter -P FORWARD DROP
$cmd -t filter -P OUTPUT DROP

#=========================
# conexões filter - input
#-------------------------
$cmd -t filter -A INPUT -i $wan -m state --state RELATED,ESTABLISHED -j ACCEPT
$cmd -t filter -A INPUT -i lo -j ACCEPT
$cmd -t filter -A INPUT -i $lan -j ACCEPT

#==========================
# conexões filter - forward
#--------------------------
$cmd -t filter -A FORWARD -i $wan -m state --state RELATED,ESTABLISHED -j ACCEPT
$cmd -t filter -A FORWARD -i $lan -o $wan -j ACCEPT

#==========================
# conexões filter - output
#--------------------------
$cmd -t filter -A OUTPUT -i lo -j ACCEPT

#===========================
# conexões nat - postrouting
#---------------------------
$cmd -t nat -A POSTROUTING -o $wan -j MASQUERADE

Caso você tenha ficado em dúvida sobre algum conceito do iptables aqui aprensentado não deixe de visitar os outros artigos neste mesmo blog que estão nos seguintes links:

Iptables - Descrição das chains e seu uso na prática
Iptables - Um firewall statefull

Se tiverem dúvidas, críticas ou sugestões não hesitem em posta-las!

segunda-feira, 1 de setembro de 2008

Mantendo atualizada a hora de seus servidores com ntpd e openntpd

Um servidor NTP é um software que implementa o protocolo Network Time Protocol sendo extremamente útil para manter a data e hora correta nas estações de trabalho e principalmente no servidores! É de grande importancia para arquivos de log pois de nada serve ter um horário errado! Caso seja necessário realizar alguma auditoria nestes arquivos por invasão, acesso a determinados recursos ou qualquer informação na qual se necessite saber com precisão a hora de acesso, a data contida ali é crucial!

Recentemente implementei um servidor NTP em minha rede e consegui ter uma consistencia de horários em meus servidores! Eu tenho alguns servidores Debian e Ubuntu e cada um sincronizava com o servidor que vinha por padrão no programa ntpdate, e sempre existia uma diferença de tempo (as vezes de alguns minutos) entre eles.

A implementação do servidor é simples e não tive problemas com ela. Para meu servidor NTP usei um Debian que tinha ai fazendo outras funções em minha rede e instalei o pacote da seguinte forma:
aptitude install ntp
A instalação ocorreu sem problemas! O arquivo de configuração no Debian esta localizado em /etc/ntp.conf. Acrescentei algumas linhas no padrão que ele usa e esta funcionando muito bem. As linhas acrescentadas foram as seguintes:
restrict 10.11.12.0 mask 255.255.255.0 nomodify notrap
restrict 13.14.15.0 mask 255.255.255.0 nomodify notrap
Estas linhas basicamente permitem o acesso ao servidor a estas redes! É uma proteção que vai além das regras de firewall que você tiver no seu servidor! Depois de adicionar essas linhas inicie o servidor e com o comando ntpdc você poderá ver a lista de servidores que ele utilizará para se sincronizar! O comando exato é: ntpdc -s. Atento aos logs você verá mensagens do software como esta:
ntpd[6381]: ntpd 4.2.2p4@1.1585-o Sun Mar 4 13:21:35 UTC 2007
ntpd[6382]: precision = 2.000 usec
ntpd[6382]: Listening on interface wildcard, 0.0.0.0#123 Disabled
ntpd[6382]: Listening on interface lo, 127.0.0.1#123 Enabled
ntpd[6382]: Listening on interface eth1, 13.14.15.16#123 Enabled
ntpd[6382]: kernel time sync status 0040
ntpd[6382]: frequency initialized 0.000 PPM from /var/lib/ntp/ntp.drift
Se você encontrar essas linhas em seu servidor, ele está iniciando o processo de se sincronizar com os servidores que estão no arquivo de configuração. Aqui meu servidor precisou de aproximadamente 5 minutos até que ele estivesse pronto para receber requisições. Quando isso acontecer você verá uma mensagem assim em seu log:
ntpd[6382]: synchronized to 208.75.88.4, stratum 2
ntpd[6382]: kernel time sync enabled 0001
Isso esta indiciando o ip do servidor escolhido para se sincronizar e qual o nivel (stratum) deste na hierarquia NTP. Com isto seu servidor está pronto para receber requisições de seus servidores ou computadores de sua rede interna.

Com o servidor instalado, agora é a fase da instalação do cliente ntp nos seus servidores ou computadores com linux! A instalação é tão simples quanto a do servidor e fiz da seguinte maneira:
aptitude install openntpd
Este programa é em minha opnião, muito melhor do que o ntpdate, pois ele verifica constantemente o horário do seu servidor evitando ter uma hora errada! O que você pode fazer se o horário dos seus servidores estiverem com uma grande diferença é utilizar o ntpdate para a primeira atualização e o openntpd para manter ele sincronizado!

Após concluída a instalação, aqui em meus servidores existia uma falha no script de inicialização do serviço que não especificava o arquivo de PID, acarretando em erros na hora de reinicializar o processo ou mesmo de parar-lo. Para arrumar isso é necessário agregar este parâmetro "--pidfile /var/run/openntpd/openntpd.pid" junto ao comando start-stop-daemon! Você pode fazer isso editando o arquivo na mão ou pode usar o sed para mudar isso para você:
sed -e 's/start-stop-daemon /start-stop-daemon --pidfile \/var\/run\/openntpd\/openntpd.pid /g' openntpd > openntpd.novo
Depois é só mover o novo para o antigo e iniciarlizar o processo! Caso você tenha algum erro na inicialização, pode ser que exista algum processo preso e será necessário executar um kill em seu PID! Com isso tudo no lugar vamos configurar agora nosso cliente para se autenticar no servidor que acabamos de criar! Como no servidor não foi necessário mudar muito para que ele funcionasse, o meu arquivo está assim:
listen on 10.11.12.13
server 10.11.12.14
Ao iniciar o processo você deve ficar atento aos logs para verificar se não existe nenhuma mensagem de erro, você deve ver algo parecido com isto em seus arquivos:
ntpd[779]: listening on 10.11.12.13
ntpd[779]: ntp engine ready
ntpd[779]: peer 10.11.12.14 now valid

Neste ponto você já possui sua estação se sincronizando com seu servidor NTP local! Essa é uma ferramenta muito importante em uma rede! Espero que este artigo ajude a implementar o de vocês!




sexta-feira, 29 de agosto de 2008

Iptables - Um firewall statefull

No artigo anterior foi descrito as chains e qual o caminho que o pacote percorre dentro do iptables até chegar no sistema operacional e sair pela interface de rede. Agora neste artigo quero falar um pouco sobre uma característica interessante do iptables que é a capacidade do iptables em verificar o estado de um pacote ou não. Você pode me perguntar "Mas o que é isso de verificar o estado do pacote?". Um pacote que chega ao seu firewall pode ser uma resposta para uma conexão web, ftp, dns que tem origem dentro de sua rede ou uma conexão que se originou sem ser requisitada (e possivelmente pode ser uma tentativa maliciosa)! Para ser capaz de distinguir isso o iptables possui uma tabela interna onde verifica esta informação!

Informações dinâmicas como esta estão guardadas em um diretório especial que que se chama proc. É ai que o iptables possui este arquivo. Talvez o nome possa mudar de uma distribuição a outra, mas ele geralmente estará relacionado com conntrack. Tenho um livro comprado a algum tempo e ali ele cita o nome como sendo ip_conntrack_max! Buscando em meu firewall/proxy encontrei 3 ocorrências porém todas elas possuem o mesmo valor (que vamos explicar já já o que ele significa), mantendo uma coerência! Para encontrar esse arquivo executei o seguinte comando:

find /proc -iname *conntrack_max
/proc/sys/net/ipv4/netfilter/ip_conntrack_max
/proc/sys/net/netfilter/nf_conntrack_max
/proc/sys/net/nf_conntrack_max

Caso você mude o valor em qualquer um desses arquivos ela se refletirá nos outros! Então não se dê o trabalho de criar um script para mudar nos três lugares! Estes arquivos só existirão após estar carregado no sistema os módulos de rastreamento de conexão (nf_conntrack, nf_conntrack_ipv4, xt_state, que são carregados automaticamente quando se usa o módulo do iptables state). Os valores contidos nestes arquivos representam o número máximo de conexões que poderão ser rastreadas pelo firewall. Caso você chegue ao valor máximo você verá uma mensagem como esta em seu log:

ip_conntrack: maximum limit of xyz entries exceeded

E novas conexões serão rejeitadas! Você pode mudar esse valor mas geralmente o padrão é algo aceitável. Se você precisa mudar ele existe um arquivo que esta disponível no site da wallfire.org! Ali é explicado os valores padrão e como são calculados.

Um firewall capaz de fazer este tipo de inspeção nos pacotes é de grande auxilio e irá economizar muitas linhas de código para criar algo mais seguro. Sem isso as regras de seu firewall seriam muito mais complexas, além de ter que imaginar inumeras possibilidades de pacotes maliciosos! Claro que essas vantagens vem a um custo, cada nova conexão rastreada por este sistema necessita de 224 bytes de memória adicional! Essa informação você pode verificar ao momento em que os módulos são carregados e será algo como isso aqui:

ip_conntrack version 2.4 (960 buckets, 7680 max) - 224 bytes per conntrack

Se não fosse o valor do arquivo conntrack_max uma rede com muitos usuários de p2p poderia facilmente lotar a memória do servidor! Porém mesmo com este limite redes ponto-a-ponto podem impedir que conexões importantes sejam efetuadas! Por isso use o módulo ipp2p do POM e limite as conexões p2p!

Na prática o comando que permite o iptables verificar o estado de um pacote que chega a interface do firewall é este:

iptables -t tabela -A chain -m state --state ESTABLISHED,RELATED -j ação
Caso você queira que o iptables não tenha esse comportamento não use o módulo state (-m state)! Com isso você precisará escrever regras bem detalhadas para não correr risco de aceitar alguma conexão maliciosa.

Eu espero que este tipo de informação seja útil para esclarecer bem como funciona este poderoso firewall que o linux possui! O que estou explanando até agora é somente teoria de como ele funciona, espero logo chegar na parte mais prática com exemplos interessantes.

quinta-feira, 28 de agosto de 2008

Iptables - Descrição das chains e seu uso na prática

Pretendo que esse seja o primeiro artigo de uma serie que estarei tentando explicar o uso do iptables. Iniciarei explicando as chains padrão do iptables e seu uso na prática. Mostrarei o fluxo que o pacote percorre dentro do iptables até chegar ao sistema operacional ou ao meio de rede. Minha intenção ao criar esse tipo de postagem foi ver que muitas pessoas que me pedem ajuda as vezes não conhecem bem o funcionamento desta ferramenta. Este primeiro post não tem o intuito de mostrar comandos.

A definição que esta no manual do iptables é esta:

Iptables é utilizado para criar, manter e inspecionar as tabelas de filtro de pacotes ip no kernel do linux.

Para que se possa manipular isso de forma eficiente, o iptables criou uma serie de tabelas e cada uma contém chains (cadeias, rotinas) pré-definidas ou criadas pelo usuário que são executadas a medida que os pacotes chegam ao sistema operacional. Abaixo elas estão definidas:

  1. raw - Essa eu nunca usei e por isso não tenho muito conhecimento, porém lendo na documentação disponível on-line da iptables-tutorial eles descrevem que ela tem uma única finalidade que é a de marcar pacotes que não devem ser manipulados pelo sistema de rastreamento de conexões (conntrack). Ela possui duas chains disponíveis que são prerouting e output.
  2. mangle - Esta aqui é muito utilizada para a manipulação de pacotes. Geralmente se usa para mudar (mangle) algum valor como ToS, as marcações FW, TTL entre outros. É aqui que eu por exemplo marco os pacotes para um tratamento diferenciado de QoS em meu proxy/gateway! É altamente recomendado NÃO REALIZAR NENHUM FILTRO nesta tabela, já que existe uma com essa finalidade! Ela possui cinco chains disponíveis que são prerouting, input, forward, output e postrouting.
  3. nat - A função desta tabela é bem sugestiva e ela deve ser utilizada para as necessidades de tradução de endereços de rede (Network Address Translation). É nesta tabela que iremos colocar as regras para compartilhar uma conexão de internet (Masquerade, SNAT) com uma LAN, aqui iremos criar a possibilidade de alguém localizado na internet acesse um recurso interno da DMZ (como um servidor web) e coisas desse genero. Ela possui três chains disponíveis que são prerouting, postrouting e output.
  4. filter - E finalmente temos a tabela filter! Essa é a que deve ser usada para filtrar pacotes, ou seja, permitir ou restringir o acesso! É aqui que você irá verificar a direção de um pacote, o que ele contém e tomar uma ação com ele, seja aceitar ou rejeitar. Ela possui três chains dispoíveis que são input, forward e output.

Agora você me pergunta "e isso tudo que você esta falando ai de prerouting, postouring, forward, para que serve?". Bom essas chains são utilizadas para propósitos específicos dentro do ciclo de vida de um pacote dentro do iptables e das decisões de roteamento do linux, e irei explica-lo agora:

  1. prerouting - Esta chain é a primeira a ser processada pelo iptables em qualquer tabela! Ela tem esse nome pois ela é utilizada antes mesmo do kernel do linux tomar alguma decisão de roteamento baseado em seu endereço de origem/destino, marcas FW, etc. Então se você precisa fazer algo desse genero, aqui é o local!
  2. input - Esta é utilizada ÚNICA e SOMENTE para os pacotes que possuem o endereço de destino o computador/servidor local! Pacotes com outros destinos que não seja esse não serão afetados por essa chain!
  3. forward - Pacotes que passam por aqui possuem endereço de destino que não seja o computador/servidor local! São pacotes destinados por exemplo para a sua LAN, para a internet ou para alguma outra rede que seu linux tenha conectado e que este seja responsável por fazer roteamento. Aqui você pode identificar esses pacotes.
  4. output - Esta chain possui a função de inspecionar os pacotes gerados pelo computador/servidor local! Se você quer proibir que seu computador/servidor local faça ping aqui é o local (tabela filter)!
  5. postrouting - De forma análoga a chain prerouting, esta possui função exatamente oposta a ela. Os pacotes que passam por aqui já tiveram sua decisão de roteamento tomada! Aqui é o local onde se pode aplicar o Masquerade, Snat, Dnat!
Com o fluxograma abaixo eu imagino que esse monte de definições ficará um pouco mais claro:





Bom, eu espero que com essa primeira introdução fique um pouco mais fácil e claro ao momento de criar suas regras de iptables ou quando você estiver procurando solucionar algum problema! Esse é só o primeiro de uma serie em que estarei explicando o funcionamento deste poderoso firewall que é o iptables!

Esta imagem foi retirada do tutorial on-line de iptables hospedado no frozen-tux.

quarta-feira, 27 de agosto de 2008

Usando find + tar para fazer backups

Como todo bom administrador de sistemas, com uma certa regularidade é necessário fazer backup dos arquivos contidos no servidor, ainda mais se for um samba onde pode estar o trabalho de muitos funcionários de sua empresa. É prudente que de tempos em tempos seja feito um backup completo do sistema porém fazer isso de forma regular é muito tedioso, leva tempo e você precisa ter bastante espaço para realizar um backup desse tipo!

Uma forma interessante de realizar backups incrementais é usar a dupla find + tar! O comando find é extremamente poderoso e até pouco tempo comecei a desvendar bem suas funcionalidades e capacidades! Primeiro ele permite que você encontre um arquivo no seu disco com uma variedade de características como:
  • Tempo em horas da última modificação (-mtime n)
  • Tempo em minutos da última modificação (-mmin n)
  • Tempo em minutos desde o último acesso (-amin n)
  • Arquivo pertence a um grupo especifico (-group grupo)
  • Arquivo pertence a um usuário especifico (-user usuário)
  • Arquivo possui um tamanho especifico (-size n[k|M|G])
Existem muitas outras possibilidades e estão todas listadas no manual do find, e com elas é possível encontrar arquivos com características específicas! Com a saída dele é possível usar o tar para criar seu arquivo de backup!

Creio que a parte que pode complicar um pouco em um processo automático de backup usando o find + tar é que arquivos que contém espaços em seus nomes podem não ser guardados corretamente e eu experimentei isso quando fui usar o tar recebendo a saída do find! Ainda bem que existe uma opção que corrige esse problema e o backup é efetuado com sucesso! O comando que utilizei para criar um backup incremental usando o find foi o seguinte:

find /diretorio/de/destino/ -mtime -30 -type f -print0 | xargs -0 tar -rf backup.tar

Com isso eu vou encontrar os arquivos que foram modificados nos últimos 30 dias (-mtime -30) que são arquivos regulares (-type f). O que possibilita a execução deste comando sem erros ao criar o arquivo é "-print0 | xargs -0"! O primeiro argumento, o print0, trata corretamente os espaços em branco nos nomes dos arquivos permitindo o correto processamento destes por programas que utilizam a saída do find. A opção do xargs trata a saída do find exatamente da mesma forma e executa o tar, criando assim um backup dos arquivos encontrados!

O tar por si só possui a funcionalidade de backup incremental, mas eu vejo que usando o find no processo de backup permite uma flexibilidade muito grande para encontrar arquivos específicos em seu disco rígido.

Um passo que nunca esqueço nesse procedimento é o de criar uma verificação de integridade com o md5sum, dessa forma no momento de restaura-lo posso ter a segurança de que os arquivos não foram corrompidos! Essa ferramenta existe em qualquer distribuição moderna de linux.