Stoa :: Leonardo K. T. Toshimitsu :: Blog

Abril 12, 2011

default user icon
Tipo: Script
Função: Automatizar o envio de mensagens do sistema
Linguagens: BASH Script, C, AWK, SED
Ferramentas: msmtp, gmail, daemon, cron, mail2sms

 

Resumo

Hoje vou lhes mostrar uma técnica para enviar mensagens de seu Linux e recebê-las via e-mail e/ou SMS, vulgo torpedo.

A função básica é receber mensagens relevantes do sistema, por exemplo, data e hora do boot, sucessivas tentativas de acesso remoto, execução de comandos não-autorizados... Como exemplo, o sistema deverá nos informar toda vez que obtivermos um novo IP externo para que possamos acessar remotamente o servidor de casa, transferir uns arquivos, etc; tivessem os IPs estáticos preços decentes aqui no Brasil isso seria irrelevante, mas o fato é que a grande maioria dos usuários domiciliares utilizam IPs dinâmicos e estes podem facilmente mudar por perda de sinal do modem, falta de energia, problemas no provedor de acesso... precisamos de algum modo simples e transparente de obtê-lo.

É, eu sei, existe o NoIP e o DynDNS, mas esta mesma solução pode resolver outros problemas para outros usuários, que simplesmente não consigo prever.
Então, mãos à obra pessoal.
Nossa tarefa será dividida em 3 partes:

  1. Instalar o software de envio de e-mails;
  2. Criar os scripts para ler automaticamente os e-mails;
  3. Criar um script para ser executado pelo boot e pelo cron.

Índice

1. Instalando o msmtp;
1.1 Gerando os certificados PEM;
1.2 Configurando o .msmtprc;
2. Lendo os e-mails com o wget;
2.1 Acessando o servidor remoto;
3. Criando um script de checagem e envio;
3.1 O script rc.mailMyIp;
4. Direcionando seus e-mails para o celular.

 


1 - Enviando os e-mails: msmtp + gmail

O msmtp é um cliente capaz de enviar e-mails para qualquer servidor SMTP, é um bom substituto simplificado para o sendmail. Sua documentação pode ser lida aqui: < http://msmtp.sourceforge.net/doc/msmtp.html > O código-fonte pode ser baixado aqui: < http://sourceforge.net/projects/msmtp/>

Instalação

$ wget sourceforge.net/projects/msmtp/files/msmtp/1.4.23/msmtp-1.4.23.tar.bz2
$ tar xjvf msmtp-1.4.23.tar.bz2
$ cd msmtp-1.4.23
$ ./configure
$ make
# make install

Se você estiver no Debian ou algum variante rode:

$ sudo apt-get install `apt-cache search msmtp | awk '{print $1}'`

Para configurar o msmtp eu me baseei neste ótimo artigo do Andrew's Corner. Como agora o gmail só permite POP e SMTP via conexão SSL, precisaremos gerar dois certificados PEM (Privacy-enhanced Electronic Mail). Vamos lá.


1.1 - Gerando os certificados PEM

O Andrew criou um script em Perl para gerarmos localmente os certificados e só me levou meia hora para configurar todas os módulos que o Perl necessitava no Slack. Então, por caridade, pus o código abaixo, basta copiar e colar:

$ mkdir -pv $HOME/.certs && cat > $HOME/.certs/Equifax_Secure_CA.pem << FIM
-----BEGIN CERTIFICATE-----
MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT
DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE
AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl
ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT
AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU
VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2
aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ
cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2
aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh
Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/
qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm
SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf
8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t
UCemDaYj+bvLpgcUQg==
-----END CERTIFICATE-----
FIM
$ cat > $HOME/.certs/Thawte_Premium_Server_CA.pem << FIM
-----BEGIN CERTIFICATE-----
MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE
ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT
B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR
fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW
8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG
A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE
CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG
A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS
spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB
Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961
zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB
BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95
70+sB3c4
-----END CERTIFICATE-----
FIM

Hora de dizer ao openssl que temos os certificados:

$ c_rehash $HOME/.certs/

OK, tudo pronto para configurar o .msmtprc.


1.2 - Configurando o .msmtprc

Bom, criados os certificados, é hora de fazer nosso arquivo de configuração. Para evitar confusão entre o que é variável, função, comando e dados a serem preenchidos, o arquivo será configurado para o Zé abaixo. Mude para seus próprios dados. Eis, aí o Zé:

Endereço no gmail: zeh@gmail.com
Senha do gmail: 53nH*
USER: zeh
HOSTNAME: NAVI

E seu arquivo de configuração:

$ cat > $HOME/.msmtprc << FIM    
  account default
  host smtp.gmail.com
  port 587
  from zeh@gmail.com
  tls on
  tls_starttls on
  #tls_trust_file /home/zeh/.certs/Thawte_Premium_Server_CA.pem
  tls_trust_file /home/zeh/.certs/Equifax_Secure_CA.pem
  auth on
  user zeh@gmail.com
  password 53nH*
  logfile ~/.msmtp.log
  FIM
$ chmod 600 $HOME/.msmtprc 

Note que o chmod é muito importante já que não queremos que outros usuários possam ler nossa senha. Vamos testar para ver se deu tudo certo:

$ echo -e "Subject: Teste 1\n\nCan you read me?" | msmtp zeh@gmail.com

Veja em sua caixa de entrada se o e-mail chegou. Em casa ele leva pouco mais de 4 segundos para enviar o e-mail. Agora que já podemos enviar os e-mails, vamos ver como lê-los.


2 - Lendo e-mails com o wget

Há muitas formas diferentes de ler e-mails pelo bash, eu vou usar uma função pouco explorada do gmail, são os Atom Feeds. Eles podem ser naturalmente acessados via https através de seu login e senha. No caso do Zé é só jogar a URL abaixo no navegador:

O mesmo efeito pode ser obtido sem um navegador através do auxílio do wget:

$ /usr/bin/wget --secure-protocol=TLSv1 --timeout=3 -t1 -q -O - https://zeh:53nH*@mail.google.com/mail/feed/atom --no-check-certificate

Reparou que a saída está em XML? Se o e-mail enviado for bem padronizado será fácil analisá-lo. Nosso objetivo é fazer algo como:

Subject: NAVI has booted, check your IP
NAVI has booted at 2010-09-12 23:51:15
NAVI IP=207.135.111.25

Um grep 'IP=' no comando acima bastaria para retornar

<summary>NAVI has booted at 2010-09-12 23:51:15 NAVI IP=207.135.111.25</summary>

Mas este sed consumirá muito menos processos:

sed '/NAVI\ IP/!d;s/.*=//g;s/<.*//g;q'

Ele se divide em quatro partes:

/NAVI\ IP/!d Não apague a linha que contiver o padrão NAVI(espaço)IP
s/.*=//g Apague tudo do 'igual' para trás
s/<.*//g Apague tudo do início da tag '<' para frente
q Pegue apenas a primeira linha (o e-mail recente) e saia (quit)

Por fim, para não ficar com a senha em um script, simplemente compilei a chamada em C em um arquivo naviip.c:

Compile assim:

$ gcc naviip.c -Wall -ansi -o naviip

Teste o programa:

$ ./naviip

De preferência jogue-o em algum lugar do seu PATH.
Um dos diretórios abaixo:

$ echo $PATH

No Slackware o diretório $HOME está incluído. Pessoalmente gosto de:

$ mkdir -pv $HOME/bin
$ echo -e 'PATH=$PATH:$HOME/bin\nexport PATH' >> $HOME/.bashrc
$ source $HOME/.bashrc

e vou supô-lo de agora em diante.


2.1 - Acessando o servidor remoto

É claro que não queremos manipular o endereço nós mesmos, um código deve fazer isso. É mais rápido, é mais fácil. Este script deve lhe ajudar:

Repare que por muita ou pouca paranóia eu configurei meu SSH para escutar atrás de uma porta não-padrão. Normalmente usamos a porta 22, escolhi outra aleatória, a 2247. Seria interessante fazer um script no servidor para alterar aleatoriamente esta porta e informá-la no e-mail, melhor ainda seria usar o iptables para fazer um Port-Knocking, ou apenas permitir acesso remoto vindo de 143.107.45.30 ;^)!
Repare também que o cliente só tentará se conectar no servidor se realmente houver um SSH escutando atrás daquela porta, o que evita a tentativa infrutífera de acesso a outra máquina que, pelos motivos mais diversos, está agora com nosso antigo IP.
ATENÇÃO: se você tiver um roteador na frente do servidor precisará abrir a porta correspondente e/ou fazer um port fowarding.


3 - Criando o script de checagem e envio

Vamos agora criar um script chamado rc.mailMyIp que deverá rodar no boot e em certo intervalo de tempo (cron). No Slackware para que um script seja executado ao final do boot, duas coisas são necessárias:

  1. Que ele seja chamado pelo /etc/rc.d/rc.local
  2. Que ele seja executável

Adicione as linhas abaixo em seu /etc/rc.d/rc.local como root

if [ -x /etc/rc.d/rc.mailMyIp ]; then
   . /etc/rc.d/rc.mailMyIp start
fi

E vamos criar o rc.mailMyIp. Há 3 técnicas que gostaria de mencionar:

  1. Na função MSG() envio os dados para um arquivo. Talvez você prefira comparar o IP atual com o que está no arquivo. No dia-a-dia achei mais fácil comparar sempre com o que está legível no e-mail, vai que você deleta a mensagem...
  2. Eu obtenho o IP externo na linha 65: Basicamente uso o curl para acessar um site que informa meu IP, esta chamada ASP li em algum lugar das "Funções ZZ" do Aurélio, o IP já vem limpinho e como não precisamos parsear foi o campeão no teste do time{}: real < 0m0.200s, no nosso zillertal.
  3. A estratégia para enviar o e-mail é a seguinte:
    1. A placa de rede deve ter um endereço válido (em casa é 192.x.y.z, por isso nas linhas 70-72);
    2. Então na linha 79 damos 3 tiros de ping (-l3 -w1) para o CGI.br e contamos quantos chegam.
      1. Dê preferência a usar o IP, porque em caso de DNS inacessível, o tempo de espera cai bastante. Caso o DNS esteja DISPONÍVEL há um ganho de 17% (OK, 0.192s em média quando este post foi escrito).
      2. Se nenhum ping chegar, não tem internet. Desencane do resto.
    3. Se o ping chegou, busque o IP externo.
    4. Pegue o IP lá do e-mail e compare os dois.
    5. Se forem iguais não há nada a fazer.
    6. Se forem diferentes envie o e-mail.
    7. A versão start é para ser usada no boot, a versão check pelo cron, a única diferença é que o check é silencioso.
  4. Não esqueça de torná-lo executável!

3.1 - O script rc.mailMyIp

Uma cópia deste script está aqui: http://pastebin.com/3zqc7xeY


4. Direcionando seus e-mails para o celular

Pessoalmente acho muito confortável receber meus e-mails no celular, há um serviço já disponível no site http://mail2sms.fr.nf/help.php, basta seguir as intruções.

Eu não comentei nada sobre o cron, mas será realmente necessário?

Enfim, dúvidas, sugestões, correções envie um e-mail para movebo@linux.ime.usp.br.

[]s
;^)

Palavras-chave: automatization, bash, daemon, e-mail, external ip, gmail, ip externo, linux, msmtp, script, sms

Esta mensagem está sob a licença CreativeCommons Atribuição, Não-Comercial.

Postado por Leonardo K. T. Toshimitsu | 1 usuário votou. 1 voto | 0 comentário