É, 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.
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 http://downloads.sourceforge.net/project/msmtp/msmtp/1.4.21/msmtp-1.4.21.tar.bz2
$ tar xjvf msmtp-1.4.21.tar.bz2
$ cd msmtp-1.4.21
$ ./configure
$ make
# make install
$ tar xjvf msmtp-1.4.21.tar.bz2
$ cd msmtp-1.4.21
$ ./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. Então, por caridade, pus o código abaixo, é só 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
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 menos de 5 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:
https://zeh:53nH*@mail.google.com/mail/feed/atom
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 was booted at 2010-09-12 23:51:15
NAVI IP=207.135.111.25
NAVI was 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 was 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 último e-mail) e saia (quit) |
#include <stdio.h>
#include <stdlib.h>
int main() {
system( "/usr/bin/wget --secure-protocol=TLSv1 --timeout=3 -t1 -q -O - https://zeh:53nH*@mail.google.com/mail/feed/atom --no-check-certificate | sed '/NAVI\ IP/!d;s/.*=//g;s/<.*//g;q'" );
return 0;
}
#include <stdlib.h>
int main() {
system( "/usr/bin/wget --secure-protocol=TLSv1 --timeout=3 -t1 -q -O - https://zeh:53nH*@mail.google.com/mail/feed/atom --no-check-certificate | sed '/NAVI\ IP/!d;s/.*=//g;s/<.*//g;q'" );
return 0;
}
Compile assim:
$ gcc naviip.c -Wall -ansi -o naviip
Teste o programa:
$ ./naviip
De preferência jogue-o em algum lugar do seu PATH.
$ 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.$ echo -e 'PATH=$PATH:$HOME/bin\nexport PATH' >> $HOME/.bashrc
$ source $HOME/.bashrc
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:
$ curl http://pastebin.com/download.php?i=upi4gMG4 | sed 's/.$//' > $HOME/bin/sshome && chmod 700 $HOME/bin/sshome
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! (TODO ;^)
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.
3 - Criando o script de checagem e envio
No Slackware para que um script seja executado por último lugar no boot, duas coisas são necessárias:
- Que ele seja chamado pelo /etc/rc.d/rc.local
- 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
. /etc/rc.d/rc.mailMyIp start
fi
E vamos criar o rc.mailMyIp.
Há 3 técnicas que gostaria de mencionar:
- 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... - Eu obtenho o IP externo na linha 45:
IP=`curl -s http://myip.com.br/index2.php | sed '/Seu\ IP/!d;s/.*\IP://g;s/<.*//g;s/\ //g'`Basicamente uso o curl para acessar um site que informa meu IP e parseio o endereço da mesma forma que fizemos com o e-mail. - A estratégia para enviar o e-mail é a seguinte:
- A placa de rede deve ter um endereço válido (em casa é 192.x.y.z, por isso a linha 52);
- Então na linha 57 damos 3 tiros de ping (-l3 -w1) para o google e contamos quantos chegam.
- 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).
- Se nenhum ping chegar, não tem internet. Desencane do resto.
- Se o ping chegou, busque o IP externo.
- Pegue o IP lá do e-mail e compare os dois.
- Se forem iguais não há nada a fazer.
- Se forem diferentes envie o e-mail.
- A versão start é para ser usada no boot, a versão check pelo cron.
3.1 - O script rc.mailMyIp
Preciso deixar colorido o que é para mudar?
Comece pelo ADDRS.
Cheque a linha 24.
Onde você pôs seu naviip (linhas 80, 106)?
O que você acha posso fazer para melhorar isso?
Uma cópia deste script está aqui: http://pastebin.com/B4YHkiHA