Mostrando postagens com marcador Dicas. Mostrar todas as postagens
Mostrando postagens com marcador Dicas. Mostrar todas as postagens

terça-feira, 6 de junho de 2017

Personalizando o Idioma da Interface Gráfica do Zabbix

Introdução

Demonstrarei nesse post como realizar a alteração do idioma do Zabbix. Pode-se alterar apenas alguns termos ou todos os termos.

Objetivo

O objetivo desse post é ser uma Prova de Conceito, é fazer com que as pessoas pensem fora da caixa. O Zabbix é uma ferramenta fantástica, que permite coletar dados, exibi-los em forma de gráficos e mapas, reagir às métricas coletadas, seja alterando um ícone no gráfico, enviando uma notificação, executando um comando, etc.

O problema é que as pessoas pensam no Zabbix apenas para redes Ethernet e Aplicações! Há algum tempo vemos algumas iniciativas, como do Luciano Alves (Unirede) expandindo isso para uma visão de negócios, o Norberto Rozas (Syspro) que propôs a ideia de usar o Zabbix como supervisório de redes industriais, O Luiz Sales com seus monitoramentos nada convencionais, etc.

No começo do ano eu iniciei o mestrado em Engenharia Elétrica, trabalhando com Redes de Sensores Sem Fio (RSSF), e claro minha proposta foi a de utilizar o Zabbix como ferramenta para o gerenciamento dessas redes, mas conforme as ideias foram surgindo, fui lendo os artigos, conversando com meu orientador, eu fui percebendo um imenso aumento do uso de conceitos como IoT, Smart Cities, Smart Campus, etc. E com isso novos interesses foram sendo despertados.

O Zabbix pode ser usado como Interface para os usuários finais, independente da área de atuação, porém será preciso fazer algumas modificações, pois cada área possui seu conjunto de jargões, sua definição de ícones, de interface, etc. Personalizar o Zabbix para que o usuário tenha uma visão que lhe seja familiar, é essencial. O que estou propondo é utilizar o que o Zabbix tem de melhor, e adaptar o que for necessário para que o usuário se sinta motivado a utilizá-lo.

O que essa solução é

Um Hack: Tenha isso em mente, o que estou fazendo não servirá para qualquer um, em qualquer ambiente, não é suportado pela Zabbix SIA e pode nem ser interessante no seu ponto de vista.
Uma Prova de Conceito: Esse post está longe de ser a palavra final sobre o assunto, eu tinha uma necessidade, achei uma maneira de executá-la e estou compartilhando com vocês.

O que essa solução não é

Prática: A cada nova versão da ferramenta, será preciso reaplicar o hack.
Universal: Veja que essa solução é ideal para ambientes, onde um ou dois idiomas são utilizados, mas não atende uma empresa global, também não atende dezenas de segmentos ao mesmo tempo.

Entendendo como funcionam os idiomas no Zabbix

Consultando a documentação oficial descobrimos que eles utilizam o GNU/gettext e o conceito de locales, que envolve uma série de normas internacionais e vai muito além da simples tradução de textos. Por isso é muito provável que esse hack nunca seja absorvido oficialmente pela Zabbix SIA.

Entendendo os os arquivos que controlam o idioma que é exibido na Interface Gráfica

Vamos analizar o diretório com o idioma do Brasil (pt_BR):
# ls -l /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/
total 940
-rw-r--r-- 1 zabbix zabbix 309122 Mai 30 17:26 frontend.mo
-rw-r--r-- 1 zabbix zabbix 649043 Mai 30 17:20 frontend.po

Enquanto o arquivo frontend.mo é um arquivo com uma codificação especial, descrita na documentação como uma "foto". E repleto de caracteres especiais:
# head -3 /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo
▒gGl▒▒▒/▒▒9▒5F [|▒▒▒!▒▒▒▒▒%▒,
3>Z
cn


O arquivo frontend.po é descrito na documentação como um arquivo texto, editável e utilizado para a tradução.
# head -3 /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.po
msgid ""
msgstr ""
"Project-Id-Version: Zabbix 3.2\n"


Observe esse trecho do arquivo frontend.po:
   4592 #: include/actions.inc.php:660 include/actions.inc.php:1061
   4593 msgid "Disable host"
   4594 msgstr "Desativar host"
   4595
   4596 #: include/views/configuration.host.list.php:116
   4597 msgid "Disable host?"
   4598 msgstr "Desabilitar host?"
   4599
   4600 #: app/views/administration.proxy.list.php:154
   4601 #: include/views/configuration.hostgroups.list.php:150
   4602 msgid "Disable hosts"
   4603 msgstr "Desativar hosts"
   4604
   4605 #: include/views/configuration.hostgroups.list.php:151
   4606 msgid "Disable hosts in the selected host groups?"
   4607 msgstr "Desabilitar os hosts nos grupos selecionados?"


Ele contém as strings que desejamos alterar, o problema é que alterar esse arquivo não surte efeito algum na interface gráfica. Pois se observarmos o arquivo que é chamado na linha 4596, por exemplo:
# vi /var/www/html/zabbix/include/views/configuration.host.list.php +116
                $confirm_message = _('Disable host?');


Verificamos que ele busca como referência a frase original, e, então aplica a tradução.

Observe esse trecho "^@Desabilitar host^@D" da linha 523 do arquivo /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo

Veja o que acontece se eu troco a frase por outra com o mesmo número de caracteres:
"^@Desabilitar sens^@D"

E reinicio o apache:
# systemctl restart httpd
Hack 01 no arquivo frontend.mo
Agora veja o que acontece e eu troco a frase por outra com um número diferente de caracteres:
"^@Desabilitar sensor^@D"

E reinicio o apache:
# systemctl restart httpd

Hack 02 no arquivo frontend.mo
Lembra que a documentação diz que o arquivo .mo é como uma foto? É nesse sentido. A mensagem aparece correta, mas todo o resto da formatação da interface gráfica se perdeu.

Basta voltar o arquivo ao normal e reiniciar o apache, que a interface gráfica também volta ao normal.
Interface Gráfica intacta após a remoção do Hack

Conclusões Iniciais

Devemos utilizar o arquivo frontend.po para gerar um arquivo frontend.mo atualizado. Mas como?

Observando o diretório /var/www/html/zabbix/locale temos um README e três scripts:
# ls -l *.sh README
-rwxr-xr-x 1 zabbix zabbix  385 Dez 21 05:08 add_new_language.sh
-rwxr-xr-x 1 zabbix zabbix  164 Mai 30 17:29 make_mo.sh
-rw-r--r-- 1 zabbix zabbix  957 Dez 21 05:08 README
-rwxr-xr-x 1 zabbix zabbix 1434 Dez 21 05:08 update_po.sh


No arquivo README encontramos a seguinte instrução:
If you want to update po files with new strings in the sourcefile, run update_po.sh . It will gather translatable strings from all files that end with ".php"

Maravilha é exatamente o que pretendemos fazer!

Vou mover o arquivo frontend.mo para o /root:
# mv /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo /root

E editar o arquivo frontend.po:
# vi /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.po
Alteramos as linhas 4592 até 4607, alterando as ocorrências de "host" para "sensor" e  de "hosts" para "sensores", e executamos o script:
# sh update_po.sh
Generating translation template...
Merging new strings in po files...
.
.
.
pt_BR
............................................................................................................................................................................................................................................................................................................................................. feito.
.
.
.
pt_BR/LC_MESSAGES/frontend.po   3316 mensagens traduzidas, 5 mensagens não traduzidas.
.
.
.


Mas... Não gerou um novo arquivo .mo:
# ls -l  /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.*
-rw-r--r-- 1 zabbix zabbix 649043 Mai 31 09:59 /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.po


Sem ele, mesmo com o idioma setado para Português (pt_BR)
Idioma setado como pt_BR
A interface gráfica fica em Inglês.
Interface Gráfica em Inglês

Basta trazer o arquivo de volta e reiniciar o apache:
# mv /root/frontend.mo /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/
# systemctl restart httpd


Que a interface gráfica volta ao normal.
Intreface Gráfica em pt_BR

Teste 02: Vamos rodar o update_po.sh e ver se ele atualiza o arquivo frontend.mo

# ls -l /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo
-rw-r--r-- 1 zabbix zabbix 309122 Mai 31 09:53 /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo
 

# sh update_po.sh
 

# ls -l /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo
-rw-r--r-- 1 zabbix zabbix 309122 Mai 31 09:53 /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo


E nada :-(

Teste 03: Vamos ver o que esse script faz ;-)

E na última instrução temos:
        # setting output file to /dev/null so that unneeded messages.mo file
        # is not created
        msgfmt --use-fuzzy -c --statistics -o /dev/null $translation

Achei!!! Esse script realmente não cria os arquivos.mo. Agora eu vou alterar ele para gerar os arquivos:
        #msgfmt --use-fuzzy -c --statistics -o /dev/null $translation
        msgfmt --use-fuzzy -c --statistics -o /root/$translation/frontend.mo $translation


Eu fiz a menor alteração possível, apenas substituindo "/dev/null" por "/root/$translation/frontend.mo". Isso poderia ficar bem mais elegante, mas preferi ser didático.

Vou criar apenas o diretório pt_BR, que será utilizado pela variável "$translation", os outros idiomas vão dar erro, mas nesse momento não tem problema:
# mkdir -p /root/pt_BR/LC_MESSAGES/frontend.po/

Vou guardar o antigo frontend.mo no /root
# mv /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo /root/

E rodar o script de update novamente:
# sh update_po.sh
Generating translation template...
Merging new strings in po files...
.
.
.
pt_BR
............................................................................................................................................................................................................................................................................................................................................. feito.
.
.
.
bg/LC_MESSAGES/frontend.po      msgfmt: erro ao abrir o arquivo "/root/bg/LC_MESSAGES/frontend.po/frontend.mo" para gravação: Arquivo ou diretório não encontrado
2052 mensagens traduzidas, 56 traduções aproximadas (fuzzy), 1213 mensagens não traduzidas.
.
.
.
pt_BR/LC_MESSAGES/frontend.po   3316 mensagens traduzidas, 5 mensagens não traduzidas.
.
.
.


E agora vamos colocar o novo frontend.mo na interface gráfica do Zabbix:
# cp /root/pt_BR/LC_MESSAGES/frontend.po/frontend.mo /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/

Reiniciar o apache
# systemctl restart httpd

E Voilà:

Interface Gráfica com a mensagem alterada
Volte o arquivo que você salvou no /root e reinicie o apache. Pois agora vamos fazer o trabalho, de verdade, vamos ter o Zabbix em Português com a interface intacta, e mais 3 variações do Português aplicado à nichos específicos.

Primeiro vamos criar a estrutura de diretórios para os idiomas Italiano (it), Francês (fr) e Russo (ru):
# mkdir -p /root/{it,fr,ru}/LC_MESSAGES/frontend.po/

Abaixo uma pequena cola, das alterações que vamos fazer:
pt_br - Hosts / Itens - Administrador da Rede Ethernet
it - Sensores / Métricas - Administrador da Rede de Sensores
fr - Plantas / Características - Usuário da Rede de Sensores - Ramo Agrícola
ru - Pacientes / Sinais Vitais - Usuário da Rede de Sensores - Ramo Medicina

Vamos copiar o arquivo frontend.po de pt_BR para os idiomas que vamos alterar:
# cd /var/www/html/zabbix/locale

# cp pt_BR/LC_MESSAGES/frontend.po it/LC_MESSAGES/frontend.po
cp: sobrescrever “it/LC_MESSAGES/frontend.po”? y

# cp pt_BR/LC_MESSAGES/frontend.po fr/LC_MESSAGES/frontend.po
cp: sobrescrever “fr/LC_MESSAGES/frontend.po”? y

# cp pt_BR/LC_MESSAGES/frontend.po ru/LC_MESSAGES/frontend.po
cp: sobrescrever “ru/LC_MESSAGES/frontend.po”? y


Primeiro vamos trabalhar no idioma Italiano e trocar todas as ocorrências de hosts por sensores e depois de host por sensor:
# sed -i -e ':g;/^msgstr/s/hosts/sensores/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/host/sensor/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Hosts/Sensores/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Host/Sensor/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po


Agora vamos trocar todas as ocorrências de itens por métricas e depois de item por métrica:
# sed -i -e ':g;/^msgstr/s/itens/métricas/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/item/métrica/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Itens/Métricas/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Item/Métrica/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po


Agora vamos ao idioma Francês, vamos trocar todas as ocorrências de hosts por plantas e depois de host por planta:
# sed -i -e ':g;/^msgstr/s/hosts/plantas/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/host/planta/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Hosts/Plantas/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Host/Planta/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po


Agora vamos trocar todas as ocorrências de itens por características e depois de item por característica:
# sed -i -e ':g;/^msgstr/s/itens/características/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/item/característica/g'  /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Itens/Características/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Item/Característica/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po


E finalmente vamos ao idioma Russo, vamos trocar todas as ocorrências de hosts por pacientes e depois de host por paciente:
# sed -i -e ':g;/^msgstr/s/hosts/pacientes/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/host/paciente/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Hosts/Pacientes/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Host/Paciente/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po


Agora vamos trocar todas as ocorrências de itens por sinais vitais e depois de item por sinal vital:
# sed -i -e ':g;/^msgstr/s/itens/sinais vitais/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/item/sinal vital/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Itens/Sinais Vitais/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Item/Sinal Vital/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po


Eentão gerar os nossos arquivos frontend.mo atualizados:
# sh update_po.sh

E coloca-los na interface gráfica do Zabbix:
# cp /root/fr/LC_MESSAGES/frontend.po/frontend.mo /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.mo
cp: sobrescrever “/var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.mo”? y

# cp /root/it/LC_MESSAGES/frontend.po/frontend.mo /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.mo
cp: sobrescrever “/var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.mo”? y

# cp /root/ru/LC_MESSAGES/frontend.po/frontend.mo /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.mo
cp: sobrescrever “/var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.mo”? y


Reiniciar o Apache
# systemctl restart httpd

E pronto:
Interface Gráfica com o Hack Aplicado

Conclusão:

Esse é apenas um pequeno exemplo de que com um pouco de criatividade e algum esforço, podemos levar o Zabbix a outros nichos e ampliar a nossa área de atuação, seja ela pessoal, acadêmica ou profissional.

segunda-feira, 9 de janeiro de 2017

Configurando um IP fixo na interface eth0 do BeagleBone Black

Introdução

Ao conectar o BBB (BeagleBone Black) no computador e instalar os drivers necessários, ele automaticamente cria uma conexão usb0 com o IP 192.168.7.2. Mas ele possui uma interface de rede, a eth0, e nem sempre estamos em um ambiente com DHCP.

O Ambiente

Estou usando a imagem Debian 8.6 2016-11-06 4GB SD LXQT

O Problema

Configurar um IP para essa interface deveria ser uma tarefa simples, bastaria editar o arquivo /etc/network/interfaces e configurar de acordo com sua necessidade:
# vi /etc/network/interfaces
auto eth0
 iface eth0 inet static
    address 10.0.1.100
    netmask 255.255.255.0
    network 10.0.1.0
    gateway 10.0.1.1
    dns-nameservers 8.8.8.8



Só que isso simplesmente não funciona! Você reinicia ele e nada.

A Solução

Depois muito pesquisar achei a solução em uma lista de discussão:
Primeiro vamos descobrir o identificador da interface
# connmanctl services
*AO Wired                ethernet_d05fb8ed4f78_cable


Depois vamos usar o comando connmanctl config para configurar as opções da interface
# connmanctl config ethernet_d05fb8ed4f78_cable --ipv4 manual 10.0.1.100 255.255.255.0 10.0.1.1 --nameservers 8.8.8.8
E agora já podemos visualizar os novos parâmetros da interface através do comando ip
# ip addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether d0:5f:b8:ed:4f:78 brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.100/24 brd 10.0.1.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::d25f:b8ff:feed:4f78/64 scope link
       valid_lft forever preferred_lft forever


E pronto você já pode executar um ping www.google.com por exemplo, para validar sua conexão com a internet.

Se você quiser reverter, e usar novamente a interface eth0 como DHCP, basta executar o comando
# connmanctl config ethernet_d05fb8ed4f78_cable --ipv4 dhcp

Fonte:

Google Groups BeagleBoard

sexta-feira, 30 de dezembro de 2016

Modelo de Script com uso de getopts para passagem de parametros

Introdução

Para fazer scripts profissionais e voltados a usuários iniciantes, temos que tomar uma série de cuidados, como por exemplo, exibir um help sobre o funcionamento do script, permitir passagem de parâmetros, checar se os parâmetros informados são válidos, se solicitarmos o uso de arquivos, verificar se o usuário possui o privilégio mínimo requerido naquele arquivo, se o script tem alguma dependência checar se essa dependência foi suprida no ambiente do usuário, e caso negativo informar como ele pode supri-la.

Junto com meu grande amigo Aécio Pires, desenvolvemos esse script base que demonstra todos os conceitos listados acima, esperamos que seja útil a todos.

Observação: Se você não conhece o getopts conheça-o aqui e sua vida será outra ;-)

sexta-feira, 13 de maio de 2016

Gerando uma Página Personalizada com Gráficos (Estáticos) do Zabbix sem uso de API

No post anterior eu demonstrei como gerar imagens dos seus mapas de maneira automatizada e respondi praticamente todas as dúvidas que eu mesmo propus a respeito do post do Mike Santangelo. O que faltou foi fazer uma página personalizada com os gráficos.

Muitas pessoas perguntam sobre isso, "não tem como eu gerar uma página para o cliente ver os gráficos dele? Eu queria algo personalizado com o logo do cliente e o gráfico", com certeza a API resolve esse problema, mas a maioria das pessoas que fazem esse questionamento não são desenvolvedoras, eu também não sou, mas resolvi aproveitar o post do Mike para ensinar como gerar as imagens (estáticas) dos gráficos em uma página, apenas como prova de conceito, eu já mencionei que não sou desenvolvedor? A ideia é apenas dar um help para quem não entende nada de programação, ok?

Vamos então resolver o problema de gerar as imagens automaticamente de forma cíclica.

Primeiro vamos criar o diretório onde serão armazenadas as imagens:
# mkdir -p /var/www/html/cliente/imagens/

Acesse seu servidor Zabbix, abra o gráfico que te interessa, clique com o botão da direita do mouse sobre a imagem e, escolha visualizar a imagem, vamos precisar das informações "chartX.php", onde "X" é um número que identifica o tipo de gráfico e "graphid=" que nos traz o ID do gráfico.

Agora vamos gerar as imagens:
# vi gera_graficos.sh

#!/bin/bash

######################################################################
# Variaveis de producao - Deve-se alterar de acordo com seu ambiente #
######################################################################

DIR_IMAGENS=/var/www/html/cliente/imagens #Diretorio que vai armazenar as imagens
NOME_IMAGEM=grafico #Nome das imagens a serem geradas
DIR_COOKIE=/root #Diretorio que vai armazenar o cookie
NOME_COOKIE=zabbix.cookie
ENDERECO='http://<IP-Servidor>/zabbix' #Url do Zabbix
USUARIO=admin # Usuario do Zabbix que tenha privilegio de visualizar todos os mapas
SENHA='zabbix'  # Senha do usuario acima
CHART=2 # ID do tipo de grafico
ID=523 # ID do grafico que sera gerada a imagem
PERIODO=3600 # Periodo (em segundos) que serao exibidos no grafico

######################################################################
# Logica do Script - Nao altere a menos que saiba o que esta fazendo #
######################################################################

# Gera o cookie
wget -q --save-cookies=$DIR_COOKIE\/$NOME_COOKIE -4 --keep-session-cookies 2> /dev/null -O - -S --post-data="name=

$USUARIO&password=$SENHA&enter=Sign in&autologin=1&request=" $ENDERECO\/index.php?login=1 > /dev/null

# Gera as imagens
wget -q -4 --load-cookies=$DIR_COOKIE\/$NOME_COOKIE -O $DIR_IMAGENS\/$NOME_IMAGEM.png "$ENDERECO/chart$CHART.php?graphid=$ID&period=$PERIODO"

# Remove o cookie
rm -rf $DIR_COOKIE/$NOME_COOKIE

# Ajusta as permissoes da imagem
chown apache:apache $DIR_IMAGENS\/$NOME_IMAGEM.png


Alterar as permissões do script:
# chmod 700 gera_graficos.sh

Pronto agora é só agendar no crontab de quanto em quanto tempo você quer gerar a imagem dos seus gráficos e automaticamente o cliente vai ter a página atualizada ;-)

Agora vamos gerar a nossa página com o gráfico

# vi /var/www/html/cliente/cliente.html

<html>
<head>
<body>
<center>
<p><b>Nome do Cliente</b></p>
<p>Gráfico do Cliente</p>
<img src=./imagens/grafico.png>
</center>
</body>
</html>

Exemplo de página gerada:

Referencias:

Tales of a Tech

Coletando uma imagem do Zabbix sem uso de API

Alguns dias atrás compartilhei um post do Mike Santangelo que achei muito interessante, ele demonstrou como usar o wget para gerar uma imagem dos mapas do ambiente dele.

Apesar do post exibir os comandos, ele não dava detalhes de como chegou naqueles endereços, por exemplo, ao acessar um mapa, o padrão de endereço é http://<IP-Servidor>/zabbix/maps.php?sysmapid=7, mas ele usava o endereço no padrão http://<IP-Servidor>/zabbix/map.php?sysmapid=7&severity_min=0. Por que map.php e não maps.php??

Ele dizia que tinha feito um script e que em 30 segundos gerou as imagens de 21 mapas, mas nada desse script, apesar de ser simples.

A imagem era de um Zabbix 3.0, mas será que isso funcionária para um Zabbix 2.4? Será que isso funcionaria para outros itens como Gráficos?

Ele disse que num próximo post pretendia fazer uma página com gráficos, triggers e mapas, sendo alimentada de forma cíclica. Bom, com essas dúvidas na cabeça eu comecei a destrinchar os comandos, tentar entender a questão das url's e fazer meus próprios testes. Vamos ao que eu descobri ;-)

Primeiro a questão das url's, se você abrir um mapa vai ver uma url no formato http://<IP-Servidor>/zabbix/maps.php?sysmapid=7 (Zabbix 2.4) ou http://<IP-Servidor>/zabbix/zabbix.php?action=map.view (Zabbix 3.0), mas se clicar com o botão da direita na imagem e escolher visualizar a imagem, vai ver o padrão de url http://<IP-Servidor>/zabbix/map.php?sysmapid=7&severity_min=0 (Em ambas as versões). E sim, o esquema funciona para ambas as versões do Zabbix.

Tendo testado isso, rapidamente percebemos que pode ser usado para qualquer imagem do zabbix (mapas e gráficos). Isso já me deu ideias.

Vamos então resolver o problema de gerar as imagens automaticamente de forma cíclica.

Primeiro vamos criar o diretório onde serão armazenadas as imagens:
# mkdir /root/imagens

Agora vamos gerar as imagens:
# vi gera_mapas.sh

#!/bin/bash

######################################################################
# Variaveis de producao - Deve-se alterar de acordo com seu ambiente #
######################################################################

MAPAS=7 # Quantidade de Mapas no seu ambiente
DIR_IMAGENS=/root/imagens #Diretorio que vai armazenar as imagens
NOME_IMAGEM=mapa #Nome das imagens a serem geradas
DIR_COOKIE=/root #Diretorio que vai armazenar o cookie
NOME_COOKIE=zabbix.cookie
ENDERECO='http://
<IP-Servidor>/zabbix' #Url do Zabbix
USUARIO=admin # Usuario do Zabbix que tenha privilegio de visualizar todos os mapas
SENHA='zabbix' # Senha do usuario acima
SEVERIDADE=0 #Severidade minima da trigger a ser exibida no mapa

######################################################################
# Logica do Script - Nao altere a menos que saiba o que esta fazendo #
######################################################################

# Gera o cookie
wget -q --save-cookies=$DIR_COOKIE\/$NOME_COOKIE -4 --keep-session-cookies 2> /dev/null -O - -S --post-data="name=$USUARIO&password=$SENHA&enter=Sign in&autologin=1&request=" $ENDERECO\/index.php?login=1 > /dev/null

# Gera as imagens
for ((i=1; i<=$MAPAS; i++))
do
         wget -q -4 --load-cookies=$DIR_COOKIE\/$NOME_COOKIE -O $DIR_IMAGENS\/$NOME_IMAGEM$i.png "$ENDERECO/map.php?sysmapid=$i&severity_min=$SEVERIDADE"
done

# Remove o cookie
rm -rf $DIR_COOKIE/$NOME_COOKIE


Alterar a permissão do script:
# chmod 700 gera_mapas.sh

Pronto agora é só agendar no crontab de quanto em quanto tempo você quer gerar a imagem dos seus mapas ;-)

Observação

Apesar do título do meu post, e como pode ser observado no post original, a API não tem função para coletar imagens.

Referencias:

Tales of a Tech

quarta-feira, 22 de julho de 2015

Servidor CentOS 7 Básico

Introdução

Com o advento do Systemd e a mudança de MySQL para MariaDB, algumas pessoas se assustam ao migrar de CentOS 6.X para 7.X, o objetivo desse post é prover uma instalação básica, mostrar alguns comandos para que você se sinta mais confortável e sugerir algumas boas práticas.

Antes de continuarmos

Eu sou da época em que a ajuda e incentivo que a gente recebia era RTFM, fui criado no Slackware, então apesar de gostar de ensinar, algumas coisas permanecem, pois fazem parte da minha formação. Só para citar as principais:
Servidor não tem interface gráfica, a menos que seja uma necessidade da aplicação;
Instalações são feitas sempre partindo-se do Minimal;
Só instale o que for necessário;
Servidor é 64 bits;
Cada aplicação precisa pacotes e ajustes específicos, esse post trata do que você deve fazer em todos os seus servidores.

Ajustes Pós Instalação

Partindo do princípio que você fez uma instalação Minimal do CentOS 7, logou pela primeira vez como root, vamos fazer alguns ajustes.

Parar a execução do firewall:

# systemctl stop firewalld

Desabilitá-lo permanentemente:

# systemctl disable firewalld
rm '/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service'
rm '/etc/systemd/system/basic.target.wants/firewalld.service'

Conferir se o mesmo está desabilitado:

# systemctl is-enabled firewalld
disabled


DICA: Você pode ver o status de todos os serviços com o comando abaixo:
# systemctl list-unit-files

Checar o estado do SELinux:

# getenforce
Enforcing

Torna-lo permissivo:

# setenforce 0

Checar o estado do SELinux:

# getenforce
Permissive


DICA: Para desabilitar definitivamente o SELinux edite o arquivo /etc/selinux/config e altere a opção "SELINUX=enforcing" para "SELINUX=disabled". Isso pode ser feito por meio do comando:
# sed -i 's/enforcing/disabled/g' /etc/selinux/config

Observação: Estou desabilitando o Firewall e o SELinux porque cada servidor tem uma finalidade específica e, exige ajustes específicos para essa finalidade, então por padrão desabilito os dois, e se houver necessidade, reabilito e faço os ajustes específicos.

O EPEL - Extra Packages for Enterprise Linux é um repositório oficial com pacotes extras e as últimas versões dos pacotes. Podemos instalá-lo através do comando abaixo:
# rpm -Uvh http://download.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm

O REMI é um repositório com pacotes adicionais aos do EPEL e/ou versões mais atualizadas do mesmo, dependendo do caso. Ele não funciona se o EPEL não estiver instalado, é um pré-requisito. Para instalar o remi, use o comando abaixo:
# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

Além disso ele vem desabilitado, é preciso habilitá-lo:
# vi /etc/yum.repos.d/remi.repo
[remi]
name=Les RPM de remi pour Enterprise Linux 7 - $basearch
#baseurl=http://rpms.famillecollet.com/enterprise/7/remi/$basearch/
mirrorlist=http://rpms.famillecollet.com/enterprise/7/remi/mirror
#enabled=0
enabled=1

gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi


Feito isso atualize seu sistema:
# yum update -y

Este último comando vai atualizar todos os pacotes do seu sistema para as versões disponíveis no EPEL e REMI.

Dependencias Básicas

Esses são pacotes que precisamos para o dia-a-dia, independente da aplicação desse servidor. Lembre-se um Servidor Web tem necessidades diferentes de um Servidor de FTP.
# yum -y install rsync  bind-utils mlocate mailx wget net-tools make cmake automake man net-tools

Clamav

Todo servidor tem que ter antivírus? Mas não é Linux? Eu disse que ia lhe sugerir algumas boas práticas, mas são apenas sugestões, este é o meu setup de Servidor CentOS 7.
# yum -y install clamav-server clamav-data clamav-update clamav-filesystem clamav clamav-scanner-systemd clamav-devel clamav-lib clamav-server-systemd

Precisamos comentar as linhas de exemplo:
# sed -i -e "s/^Example/#Example/" /etc/freshclam.conf
# sed -i -e "s/^Example/#Example/" /etc/clamd.d/scan.conf


E atualizar o clamav:
# freshclam

Precisamos comentar a linha abaixo:
# sed -i -e "s/^FRESHCLAM_DELAY/#FRESHCLAM_DELAY/" /etc/sysconfig/freshclam

Editar o arquivo scan.conf:
# vi /etc/clamd.d/scan.conf

E descomentar a linha:
#LocalSocket /var/run/clamd.scan/clamd.sock

Habilitar o Clamav, Inicia-lo e Checar se o processo está ativo:
# systemctl  enable clamd@scan
# systemctl  start clamd@scan
# systemctl  status clamd@scan


Testar a verificação de um arquivo:
# clamdscan -c /etc/clamd.d/scan.conf /etc/hosts

Cron

Deixar um cron padrão para que qualquer um possa editá-lo:
# crontab -e

# Exemplo de uso
# 0     4       *       *       *       <usuario>       who

# Campo         Funcao
# 1o.           Minuto
# 2o.           Hora
# 3o.           Dia do mes
# 4o.           Mes
# 5o.           Dia da semana

# 6o.           Usuario com o qual o comando sera executado <opcional>
# 7o.           Programa para execucao

# Campo                 Valores
# Minuto                 0-59
# Hora                     0-23
# Dia do mes           1-31
# Mes                      1-12
# Dia da semana      0-6 (o "0" eh o domingo), 1 eh a segunda, etc.

# -----------------------------------------------------------------------------------------------
# Roda o update do antivirus todos os dias as 23:00
0 23 * * * /usr/bin/freshclam


Reiniciar o servidor:
#reboot

Referências

ISMAILYENIGUL

sexta-feira, 17 de julho de 2015

Como recuperei meus dados de um Volume LVM

Introdução

Resumindo em poucas palavras perdi meu volume LVM, fiz várias besteiras na tentativa de recuperá-lo e quando achei que estava tudo perdido, meu amigo Ariel me deu as ferramentas necessárias para resolver a questão.

As soluções apresentadas aqui não vão se aplicar a qualquer situação de perdas de dados de LVM, mas podem ser a solução se o seu cenário for próximo do meu.

Cenário

Dois discos instalados no notebook

/dev/sda:
/boot - Partição padrão ext4
swap - Partição padrão swap
/ - Partição LVM VG1
/home - Partição LVM VG1

/dev/sdb:
/Dados - Partição LVM VG1

O meu cenário era relativamente simples, um VG compreendendo ambos os discos, sendo que o LV que eu queria recuperar estava isolado no /dev/sdb, aliás, fica a dica: evite quebrar seus LVs em mais de um disco, caso seja possível. Eu acredito que as soluções apresentadas podem funcionar para outros cenários, mas não testei isso! O objetivo aqui é apenas relatar como recuperei o meu cenário.

Criar uma imagem do disco

Esse passo é fundamental, independente de qual solução você escolher, a primeira coisa que você deve fazer é gerar um clone do seu disco.
dd if=/dev/sdX of=/mnt/sdX.img bs=512 conv=noerror,sync

No meu caso:
# dd if=/dev/sdb of=/mnt/sdb.img bs=512 conv=noerror,sync

Onde /mnt é um HD externo, outro disco, uma unidade de rede, enfim, um lugar com espaço suficiente para armazenar uma cópia completa (mesmo tamanho) do seu disco.

Esse processo vai demorar, vai demorar muito... Meu HD de míseros 320 GB demorou mais de 10 horas. Não pule esse passo, se nada funcionar você ainda pode voltar essa cópia para o mesmo disco (ou outro) e envia-lo para uma empresa especializada em recuperação de dados.

Primeira Solução - Montar a imagem do disco de forma direta

Na ordem cronológica do meu caso, essa foi a segunda solução encontrada, mas ela é mais simples, então aconselho você a começar por ela.

Basicamente o que vamos fazer é montar a imagem que temos do disco no sistema e restaurar nossos dados para outro disco.

Essa solução também é um pouco mais limitada: só dá para usá-la caso seu LV esteja alocado em uma faixa contínua no disco, ou seja, se ele tiver apenas um segmento, e estiver situado em apenas um dos discos. Para saber se o seu LV tem apenas um segmento contínuo, veja mais abaixo o dump do metadado feito a partir do início da partição LVM.

# mkdir /Dados2
# mount -o loop,ro,offset=$((2*1024*1024)) /run/media/deo/IMG/Déo/sdb.img /Dados2


O comando mount acima abre um sistema de arquivos contido em uma imagem (arquivo sdb.img), fazendo sua associação a um ponto de montagem. O detalhe importante é a opção offset que ignora os primeiros n bytes do arquivo de imagem. Neste caso foi tentado o valor de 2MB, afim de ignorar o primeiro MB entre o início do disco e a primeira partição e também 1 MB referente ao metadado da partição LVM. Caso você tente usar esse comando, se o mount pedir para você informar o sistema de arquivos, é porque não funcionou, não perca tempo tentando especificá-lo. Dá para tentar também variações como 3*... 4*..., em fim, pode ser que o seu metadado seja maior.

É possivel também que você precise aumentar o offset, caso o LV em questão não esteja no início da partição. Nesse caso some ao valor acima o valor do start_extent multiplicado pelo extent_size, que podem ser encontrados no metadado, discutido mais abaixo.

# ls -las /Dados2
total 23927780
      4 drwxr-xr-x. 10 deo  deo        4096 Jun 14 17:44 .
      4 dr-xr-xr-x. 20 root root       4096 Jun 23 15:29 ..
      4 drwx------.  2 deo  deo        4096 Mar 24 08:47 centos-6.5-pe-3.7.0-ptb2.13-vbox
8388648 -rw-------.  1 deo  deo  8592031744 Jan  4 00:57 CentOS 7 - Zabbix Server.vdi
8388648 -rw-------.  1 deo  deo  8592031744 Jan 28 00:13 CentOS Scripts.vdi

# df -kh
Sist. Arq.                Tam. Usado Disp. Uso% Montado em
/dev/loop0                294G   93G  186G  34% /Dados2

Segunda Solução - Extrair as informações referentes ao LVM do disco

É isso mesmo que você leu, o LVM guarda uma cópia das configurações dele no início de cada partição integrante do VG, aquele 1MB de metadado do LVM da primeira solução ;-), foi essa solução que salvou a minha pele.

Vamos extrair as primeiras 500 linhas do disco, você pode fazer isso com um live cd por exemplo. Esse arquivo possui os dados que serão a base para recriarmos o nosso volume.
strings -t x /dev/sdX | head -500 > string_dev_sdX.txt

No meu caso:
# strings -t x /dev/sdb | head -500 > string_dev_sdb.txt

Agora você precisa criar um volume LVM na sua máquina, ou instalar o HD que você quer recuperar em uma máquina com LVM funcional. No meu caso eu reinstalei o sistema no /dev/sda criando a mesma estrutura: /boot, swap, / e /home. Como a partição /Dados estava em outro disco, e em somente em um disco, eu não precisei me preocupar muito.

Recapitulando o que temos até agora:
  • Sistema funcional com LVM;
  • Disco que desejo recuperar instalado na máquina;
  • Arquivo que vamos utilizar para recriar os apontamentos.

Carregar o módulo
# modprobe dm-mod

Exibir os volumes físicos:
# pvs -v
    Scanning for physical volume names
  PV         VG     Fmt  Attr PSize   PFree   DevSize PV UUID
  /dev/sda2  fedora lvm2 a--  111,59g      0  111,59g 1r10wL-sh0C-KcAF-K9XB-ji2L-hzbM-UBhEDL
  /dev/sdb1         lvm2 a--  298,09g 298,09g 298,09g uYRucm-f2aK-Ye0q-C2Db-QYpg-aw2z-9sBGV3


O que nos interessa é o PV UUID, nesse caso "uYRucm-f2aK-Ye0q-C2Db-QYpg-aw2z-9sBGV3". E o nome do VG funcional, no meu caso "fedora".

Agora é a etapa final, mas antes de mais nada BACKUP:
# cp /etc/lvm/backup/fedora /etc/lvm/backup/fedora_02
# cp /etc/lvm/archive/fedora_00000-427671572.vg /etc/lvm/archive/fedora_2_00000-427671572.vg


Esses arquivos, são os arquivos que o LVM utiliza para controlar quais são os volumes, partições, pontos de montagem e etc.

Ao abrir o arquivo string_dev_sdb.txt, encontramos as informações referentes ao pv1:
 102594 pv1 {
 10259a id = "uYRucm-f2aK-Ye0q-C2Db-QYpg-aw2z-9sBGV3"
 1025c8 device = "/dev/sdb1"
 1025de status = ["ALLOCATABLE"]
 1025f7 flags = []
 102602 dev_size = 625140400
 102617 pe_start = 2048
 102627 pe_count = 76310

Remova todo esse código hexadecimal, faça as devidas indentações, feche as chaves que estão faltando e, transforme os dados nisso:
                pv1 {
                        id = "uYRucm-f2aK-Ye0q-C2Db-QYpg-aw2z-9sBGV3"
                        device = "/dev/sdb1"

                        status = ["ALLOCATABLE"]
                        flags = []
                        dev_size = 625140400
                        pe_start = 2048
                        pe_count = 76310
                }

Agora procure no arquivo string_dev_sdb.txt, as informações referentes ao ponto de montagem dados:
 1029b1 dados {
 1029b9 id = "SdiIbs-5dcB-hZkU-ykcW-cXy0-EIdr-5DNBwZ"
 1029e7 status = ["READ", "WRITE", "VISIBLE"]
 102a0d flags = []
 102a18 creation_host = "deonote"
 102a32 creation_time = 1411552196
 102a4d segment_count = 1
 102a60 segment1 {
 102a6b start_extent = 0
 102a7c extent_count = 76310
 102a92 type = "striped"
 102aa3 stripe_count = 1
 102ab5 stripes = [
 102ac1 "pv1", 0

Remova todo esse código hexadecimal, faça as devidas indentações, feche as chaves que estão faltando e, transforme os dados nisso:
                dados {
                        id = "SdiIbs-5dcB-hZkU-ykcW-cXy0-EIdr-5DNBwZ"
                        status = ["READ", "WRITE", "VISIBLE"]
                        flags = []
                        creation_host = "localhost"
                        creation_time = 1411552196
                        segment_count = 1

                        segment1 {
                                start_extent = 0
                                extent_count = 76310

                                type = "striped"
                                stripe_count = 1

                                stripes = [
                                        "pv1", 0
                                ]
                        }
                }

Essas entradas devem ser inseridas nos dois arquivos:
/etc/lvm/backup/fedora
/etc/lvm/archive/fedora_00000-427671572.vg

MUITA, mas muita atenção na posição em que as informações devem ser inseridas.

Testando a recuperação do volume:
# vgcfgrestore fedora --test -f /etc/lvm/archive/fedora_00000-427671572.vg
  TEST MODE: Metadata will NOT be updated and volumes will not be (de)activated.
  Restored volume group fedora


Observação:
O meu VG se chama fedora, você deve alterar o comando de acordo com o nome do seu VG. Nenhuma mensagem de erro? Então você fez tudo certinho, caso contrário, reveja suas configurações.

Recuperando o volume:
# vgcfgrestore fedora -f /etc/lvm/archive/fedora_00000-427671572.vg
  Restored volume group fedora


Verificando o status do volume:
# lvscan
  ACTIVE            '/dev/fedora/root' [9,77 GiB] inherit
  ACTIVE            '/dev/fedora/swap' [512,00 MiB] inherit
  ACTIVE            '/dev/fedora/home' [101,32 GiB] inherit
  inactive          '/dev/fedora/dados' [298,09 GiB] inherit


Ativando o volume:
#  vgchange -ay
  4 logical volume(s) in volume group "fedora" now active


Verificando o status do volume:

# lvscan
  ACTIVE            '/dev/fedora/root' [9,77 GiB] inherit
  ACTIVE            '/dev/fedora/swap' [512,00 MiB] inherit
  ACTIVE            '/dev/fedora/home' [101,32 GiB] inherit
  ACTIVE            '/dev/fedora/dados' [298,09 GiB] inherit


Montando o volume:

# mkdir /Dados
# mount /dev/fedora/dados /Dados/


Verificando os dados:
# ls -l /Dados/
total 23927780
      4 drwxr-xr-x. 10 deo  deo        4096 Jun 14 17:44 .
      4 dr-xr-xr-x. 20 root root       4096 Jun 23 15:29 ..
      4 drwx------.  2 deo  deo        4096 Mar 24 08:47 centos-6.5-pe-3.7.0-ptb2.13-vbox
8388648 -rw-------.  1 deo  deo  8592031744 Jan  4 00:57 CentOS 7 - Zabbix Server.vdi
8388648 -rw-------.  1 deo  deo  8592031744 Jan 28 00:13 CentOS Scripts.vdi

# df -kh
Sist. Arq.                Tam. Usado Disp. Uso% Montado em
/dev/mapper/fedora-dados  294G   93G  186G  34% /Dados

Outros cenários

Caso seu problema seja mais complexo, talvez por ter dividido o LV entre os discos, ou então tenha um LV com vários segmentos, decorrente de expansões alternadas de diferentes volumes lógicos, creio que ainda assim seja possível fazer algum procedimento para sua recuperação. Se conseguir fazer o dump do metadado e tiver o conteúdo do disco razoavelmente preservado, o pior que pode acontecer é você ter que calcular o início e final de cada segmento, recortá-los, possívelmente com um dd, especificando valores para skip e count, e juntá-los na ordem correta.

Escrito a 4 mãos pelo mestre Ariel e por esse humilde ser, dono do blog ;-)

Referencias

PissedOffAdmins
ADAMS BROS BLOG
serverfault.com

terça-feira, 26 de maio de 2015

Manipulação de arquivos via SCP, Rsync e Scripts por Chave Pública

Introdução

Nos posts anteriores [1, 2] eu ensinei a criar um par de chaves publica/privada através de utilitários no Windows e no Linux, e como acessar os servidores utilizando essas chaves.

Nesse post eu vou demonstrar como criar chaves sem senha que serão utilizadas para realizar cópias de arquivos via scp e rsync, e em servidores onde existe a necessidade de realizar cópias automatizadas (via scripts), dispensando assim a necessidade de digitação e/ou armazenamento de senhas.

O servidor que recebe o arquivo será tratado neste documento como Servidor Destino e o servidor que envia o arquivo como Servidor Origem.
Lembrando que se existir a necessidade dos servidores trocarem arquivos entre si, será necessário realizar os dois procedimentos (origem e destino) em ambos os servidores.

Procedimentos Servidor Origem

Gerar o par de chaves Pública/Privada

# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/teste/.ssh/id_rsa): <ENTER>
Created directory '/home/teste/.ssh'.
Enter passphrase (empty for no passphrase): <ENTER>
Enter same passphrase again: <ENTER>
Your identification has been saved in /home/teste/.ssh/id_rsa.
Your public key has been saved in /home/teste/.ssh/id_rsa.pub.
The key fingerprint is:
79:2d:88:c4:35:1e:be:8f:f2:c1:df:dc:ae:27:b0:39 teste@private.localhost
The key's randomart image is:
+--[ RSA 2048]----+
|        +        |
|     . + o       |
|      o o        |
|     . . + .     |
|      . S o .    |
|       . +..     |
|      . + .+     |
|       o oEo...  |
|        . ..+=o  |
+-----------------+


Observações
Created directory '/home/teste/.ssh'. - Aparece apenas na primeira vez que a chave é criada;
Enter passphrase (empty for no passphrase): - É a senha para sua chave privada, nesse caso vamos criar uma chave sem senha, portanto basta pressionar Enter.

Copiar a Chave Pública

# cat /home/teste/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAxka6+ntfEcwUMCXYRpCS9im8yJrlyp/+LhFh3K/X0Ad5QPUlUTTklZ2bDps4CdKNbQf/6T4j1nu/ylJwUHBBJyK6y8uZDXCjCtjCcZfLsO8pSLjsmYJfKqXeD50y+zSYqC9GB+HeQf+It09unQt5gTvGtfgWdKzq2hchfpkEEgWQD0mKyQZAl5cU2SbmLMJV8YxfBpwAONyj7ARKtUrkW3XcVa+QKFdYFTfHshMdcBCAsGuO6tDFmWSRjcEkYHgyNaaeIufOwHPvLzs4TVk3/NmOC1Pd1bYUcmEQslL0U6UPun9X8A6aNs3eu6JgOWWifze6bxgshp9dKVJHlgAxbQ== teste@private.localhost


Copie esta chave para um txt temporário, pois ela será necessária no Procedimento Servidor Destino. Obs.: As informações da chave acima estão em uma única linha.

Procedimentos Servidor Destino

Criar o usuário e configurar o acesso via chave

Crie o usuário no Linux
# adduser teste

Entre no diretório do usuário
# cd /home/teste/

Crie o diretório.ssh
# mkdir .ssh

Acesse o diretório
# cd .ssh/

Crie o arquivo authorized_keys
# vi authorized_keys

Dentro desse arquivo você vai colocar o conteúdo da chave pública, aquela que você colou em um arquivo temporário. Tenha certeza de que não houve quebra de linha.

Uma boa prática é colocar uma linha com a identificação do servidor:
# Servidor 01
<CHAVE>

# Servidor 02
<CHAVE>

Dica do grande amigo Andreyev

Altere as permissões do diretório
# chmod 700 .

E do arquivo
# chmod 600 authorized_keys

E por último de todo o diretório .ssh
# chown -R teste:teste /home/teste/.ssh

Testar a conexão - Partindo do Servidor Origem

# ssh teste@servidor_destino

The authenticity of host '[servidor_destino]:1922 ([192.168.100.2]:22)' can't be established.
RSA key fingerprint is 3e:99:b4:aa:c6:8a:e2:e0:e0:55:d4:f8:01:76:2a:8b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[servidor_destino]:22,[192.168.100.2]:22' (RSA) to the list of known hosts.
[teste@servidor_destino ~]$
[teste@servidor_destino ~]$ logout
Connection to servidor_destino closed.


Observações:
Essas mensagens informando que a conexão não foi possível e que vai adicionar o host ao arquivo know hosts só aparece na primeira conexão.

Copiar um arquivo do Servidor Origem para o Servidor de Destino usando scp

# scp teste.txt teste@servidor_destino:/home/teste
teste.txt                                     100%    0     0.0KB/s   00:00


Copiar um arquivo do Servidor Origem para o Servidor de Destino usando rsync

# rsync -Cravzp teste teste@servidor_destino:/home/teste/
sending incremental file list
teste/
teste/teste.txt
teste/teste01.txt
teste/teste02.txt
teste/teste03.txt

sent 270 bytes  received 92 bytes  724.00 bytes/sec
total size is 0  speedup is 0.00


Observações:
Se você mudar a porta do SSH nos Servidores a sintaxe dos comandos passam a ser:
# scp -P 2891 teste.txt teste@servidor_destino:/home/teste

# rsync -Cravzp --rsh='ssh -p
2891' teste teste@servidor_destino:/home/teste/

Os mesmos procedimentos podem ser usados em scripts, sem a necessidade de senhas.

Observação:
Todas as recomendações de segurança dos posts anteriores devem ser implementadas.

terça-feira, 19 de maio de 2015

Acesso via SSH por Chave Pública entre Servidores Linux

Introdução

No post anterior ensinei a criar um par de chaves publica/privada através de utilitários no Windows, e acessar um servidor Linux.
Agora vou demonstrar como gerar o seu par de chaves em um servidor Linux, tratado neste post como Servidor Origem, como disponibiliza-la em outros servidores que você deseja acessar, tratados neste post como Servidor Destino. E por último, mas não menos importante, como importar essa chave para ser utilizada nos utilitários no Windows.

Gerar o par de chaves Pública/Privada no Servidor Origem

# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/teste/.ssh/id_rsa): <ENTER>
Enter passphrase (empty for no passphrase):
<SENHA DA CHAVE PRIVADA>
Enter same passphrase again:

<SENHA DA CHAVE PRIVADA> 
Your identification has been saved in /home/teste/.ssh/id_rsa.
Your public key has been saved in /home/teste/.ssh/id_rsa.pub.
The key fingerprint is:
fc:21:f9:9f:1e:45:9d:3f:fa:40:45:70:d6:bb:7f:b1 teste@private.localhost
The key's randomart image is:
+--[ RSA 2048]----+
|             ..+.|
|              +.o|
|              .oo|
|       . .   ....|
|        S .  ...o|
|         + ....o.|
|          o .o  +|
|           . ooEo|
|           .+  ..|
+-----------------+


Observações:
Created directory '/home/teste/.ssh'. - Aparece apenas na primeira vez que a chave é criada;
Enter passphrase (empty for no passphrase): - É a senha para sua chave privada, quanto maior a frase maior a segurança da chave. Quando fornecendo uma frase-chave, ela não é exibida na tela (nem mesmo *s aparecerão).

Copiar a Chave Pública

# cat /home/teste/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA1iQX//ED02Ranp2M4GD4uQCVtDjMg5nArtUDz0Voblvz02fcnmUePu36TU85q6eHf4RlR3z/w0wNmz4b4haQRoMmIMZSi4TxYZKtyUIHipiQkCt+TpLNZm9chekLCn5pMGB4DSpL2XJC5N2Yw12w5HNKvAXZOUqUnKK+lX5G/YYM+Td0p/t+PG3E3ZjSy9kMDDpc61uGz/BjnIvrSFj+rot5l5tn2mynmfb4lhTkLE+0Ot30+q+s9IkK7J33+Y4cpEX+jMb4MvfdEyUUnjjZPgGlaXggsaKrE5ZMUhGvmIX0t/b81DRxtpI+1iu01/GHOUZ5EoSTo/EsUAViXrPV6w== teste@private.localhost


Copie esta chave para um txt temporário, pois ela será necessária no Procedimento Servidor Destino. Obs.: As informações da chave acima estão em uma única linha.

Procedimentos Servidor Destino

Criar o usuário e configurar o acesso via chave

Crie o usuário no Linux
# adduser teste

Entre no diretório do usuário
# cd /home/teste/

Crie o diretório.ssh
# mkdir .ssh

Acesse o diretório
# cd .ssh/

Crie o arquivo authorized_keys
# vi authorized_keys

Dentro desse arquivo você vai colocar o conteúdo da chave pública, aquela que você colou em um arquivo temporário. Tenha certeza de que não houve quebra de linha.

Altere as permissões do diretório
# chmod 700 .

E do arquivo
# chmod 600 authorized_keys

E por último de todo o diretório .ssh
# chown -R teste:teste /home/teste/.ssh

Testar a conexão - Partindo do Servidor Origem

$ ssh teste@servidor_destino
The authenticity of host '[servidor_destino]:22 ([192.168.100.2]:22)' can't be established.
RSA key fingerprint is 3e:99:b4:aa:c6:8a:e2:e0:e0:55:d4:f8:01:76:2a:8b.
Are you sure you want to continue connecting (yes/no)? <yes>
Warning: Permanently added '[servidor_destino]:22,[192.168.100.2]:22' (RSA) to the list of known hosts.
Enter passphrase for key '/home/teste/.ssh/id_rsa': <SENHA DA CHAVE>
Last login: Wed May 13 17:43:38 2015 from servidor_origem
 

[teste@servicor_destino ~]$ logout
Connection to servidor_destino closed.


Observações:
Essas mensagens informando que a conexão não foi possível e que vai adicionar o host ao arquivo know hosts só aparece na primeira conexão.

Converter a chave gerada no Linux para ser usada no Putty

Pode ser necessário em algum momento utilizar essa chave gerada no Linux, para acessar o Servidor Destino a partir de uma máquina Windows, para isso será necessário converter a chave, mas o processo é bem simples.
Copie a chave para o Windows e abra o Puttygen

Na tela principal clique em Load

Mude o tipo de arquivo para All Files e selecione a chave privada gerada no Linux

Digite a senha da sua chave privada

Será exibida a mensagem que a chave foi importada com sucesso clique em OK


Agora você pode visualizar a sua chave pública e salvar a chave privada


De posse das chaves devidamente importadas pelo Puttygen, basta seguir o post anterior.Você pode realizar o acesso pelo Windows normalmente, a chave importada contém o mesmo hash da chave original.

Observação:
Todas as recomendações de segurança do post anterior devem ser implementadas. 

terça-feira, 12 de maio de 2015

Acesso via SSH por Chave Pública

 Introdução

A maioria dos administradores de rede toma alguma ação com relação ao serviço de ssh, como, por exemplo, não permitir login como root, alterar a porta default do serviço, tudo isso pode e deve ser feito, mas o objetivo dessa documentação é implementar uma camada a mais de segurança, o uso de chaves.

Isso deve ser implementado em todos os seus servidores, pois mesmo sendo um servidor interno da sua rede, ele ainda está exposto aos atacantes internos e aos ataques automatizados através de botnet. Algum usuário da sua rede pode estar atacando seu servidor sem nem suspeitar disso.

Gerar a chave no Windows

Para gerar a chave no Windows vamos utilizar um utilitário chamado Puttygen. Baixe o executável e inicie o mesmo

A tela inicial já nos vem configurada para chave SSH-2 RSA de 2048 bits, clique no botão Generate.


Movimente o mouse na área sem dados para gerar a senha.


Na parte superior temos a chave pública que será colocada no servidor, selecione o seu conteudo e copie para um txt temporário.

A segunda seleção é onde você deve cadastrar uma senha para sua chave privada, crie a maior senha que você consiga lembrar, se alguém quebrar essa senha você perdeu sua chave privada.

E na última seleção temos a opção de salvar a chave pública e privada. Salve apenas a chave privada.

Configurações no Servidor Linux

Criar o usuário e configurar o acesso via chave

Crie o usuário no Linux
# adduser teste

Entre no diretório do usuário
# cd /home/teste/

Crie o diretório.ssh
# mkdir .ssh

Acesse o diretório
# cd .ssh/

Crie o arquivo.
# vi authorized_keys

Dentro desse arquivo você vai colocar o conteúdo da chave pública, aquela que você colou em um arquivo temporário. Tenha certeza de que não houve quebra de linha (Se você colar no Word já era) - Dica do meu amigo Gesiel.

Altere as permissões do diretório
# chmod 700 .

E do arquivo
# chmod 600 authorized_keys

E por último de todo o diretório .ssh
# chown -R teste:teste /home/teste/.ssh

Testar a conexão

Para se conectar ao servidor Linux vamos utilizar outro utilitário o Putty. Baixe o executável e inicie o mesmo

Em Session informe o IP e Porta do Servidor


Em Connection // Data informe o nome do usuário


Em Connection // SSH // Auth informe o caminho da sua chave privada e clique em Open.

Observe que ele não pede a senha do meu usuário, mas sim a senha da minha chave privada. Aquela que nós definimos no momento da criação da chave.


E agora estamos logados.


Incrementar a segurança do SSH

Uma vez logados com sucesso, chegou a hora de incrementarmos a segurança do SSH no servidor Linux. Para isso execute o login como root e edite o arquivo sshd_config

# vi /etc/ssh/sshd_config
# Alterar a porta padrao
#Port 22
Port 2891

# Proibir login como root, os usuarios devem usar o su -
#PermitRootLogin yes
PermitRootLogin no

# Liberar acesso via chave
#RSAAuthentication yes
#PubkeyAuthentication yes
#AuthorizedKeysFile     .ssh/authorized_keys
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile      .ssh/authorized_keys

# Proibir o acesso via senha
#PasswordAuthentication yes
PasswordAuthentication no


Se o servidor em questão for um FreeBSD altere também a diretiva abaixo:
ChallengeResponseAuthentication no

# service sshd restart

Testar acesso com usuário e senha

Ao tentar se logar passando um nome de usuário a mensagem abaixo é exibida


Pronto! Basta acessar passando a sua chave privada e a porta correta ;-)

Referências

Locaweb
Man sshd_config
Fórum FreeBSD