A necessidade de equipamentos embarcados conectados à internet continua crescendo a cada dia. Uma ótima opção quando não se tem internet cabeada ou Wi-Fi é buscar cobertura das redes de telefonia móvel. Sendo assim, este tutorial apresenta as configurações necessárias para conectar uma placa utilizando Linux Embarcado à internet por meio do link PPP (Point-to-Point Protocol).
Equipamento Utilizado
Para este tutorial foi utilizado o módulo Colibri iMX6S em conjunto com a placa Colibri Evaluation Board, ambos da Toradex. A Colibri Evaluation é uma placa recomendada para desenvolvimento de projetos, que disponibiliza uma variedade de interfaces de conectividade, incluindo USB 2.0, 100 Mbit Fast Ethernet, I2C, SPI, RS232, RS485 e CAN. As interfaces multimídia disponíveis incluem áudio analógico, HDMI, LVDS, VGA e LCD TFT.
Para realizar a conexão com a internet, é possivel executar todo o tutorial com qualquer modem USB ou Serial. Atente-se apenas a adaptar a interface usada do “/dev” e aos comandos “ATs” devido ao fato de que cada modem tem sua própria lista de comandos.
No nosso caso, nos baseamos em um modem 3G da Huawei modelo E173s, com um SIM card da Operadora Vivo.
Preparando o KERNEL
Para utilizar modens USB por meio do protocolo PPP, é necessário que o kernel Linux possua suporte a algumas funcionalidades. Sendo assim, caso não esteja pré-selecionado no kernel, será necessário adicionar alguns itens. Para compilar o Kernel, sugiro que usem o artigo abaixo como base:
Basicamente o processo para compilar o kernel se resume nos seguintes passos:
- Configuração da toolchain;
- Baixar o kernel do repositório;
- Configurar as características padrão do processador (defconfig);
- Alterá-las para sua aplicação;
- Compilar.
Quando você estiver no passo de alterar as configurações padrões, entre no menuconfig e certifique-se de habilitar as seguintes opções:
CONFIG_PPP:
PPP (Point to Point Protocol) is a newer and better SLIP. It serves the same purpose: sending Internet traffic over telephone (and other serial) lines. Ask your access provider if they support it, because otherwise you can't use it; most Internet access providers these days support PPP rather than SLIP.
Device Drivers --->
[*] Network device support --->
<*> PPP (point-to-point protocol) support
<*> PPP BSD-Compress compression
<*> PPP Deflate compression
[*] PPP filtering
<*> PPP MPPE compression (encryption)
[*] PPP multilink support
<*> PPP over Ethernet
<*> PPP support for async serial ports
<*> PPP support for sync tty ports
CONFIG_USB_ACM:
This driver supports USB modems and ISDN adapters which support the
Communication Device Class Abstract Control Model interface.
Please read <file:Documentation/usb/acm.txt> for details.
Device Drivers --->
[*] USB support --->
<*> USB Modem (CDC ACM) support
Programas necessários
Para configurar e conectar o modem à internet, o Linux utiliza além dos drivers do kernel, um software a nível de aplicação que gerência a conexão. Normalmente as imagens da Toradex já vem com o PPP instalado.
Caso você não tenha o programa “ppp” instalado, e você tenha uma imagem baseada em Yocto ou Openembedded, adicione ao arquivo “local.conf” o pacote PPP:
IMAGE_INSTALL_append = " ppp"
Testando comunicação com Modem
Após ter instalado todos os drivers e programas necessários, é possível identificar se sua placa reconheceu o modem através do /dev. Basicamente o driver simula a conexão USB em várias conexões seriais.
Execute o comando para buscar as interfaces /dev/ttyUSB.
$ ls -l /dev/ttyUSB*
Se os arquivos ttyUSB0, ttyUSB1 … e ttyUSB2 forem encontrados, o modem USB foi reconhecido.
Caso você queira ir mais a fundo nos testes, é possível usar um terminal serial como “minicom” para iniciar a comunicação com o modem e validar a comunicação com o mesmo.
No meu caso o meu modem estava configurado com velocidade 115200.
$ minicom -D /dev/ttyACM0 ___________________________ AT OK ___________________________
Configurando os Arquivos do PPP
Após ter validado a conexão serial com o modem é hora de criar os arquivos de configuração para conexão com a internet.
Você deverá ser capaz de encontrar a pasta “/etc/ppp”. Iremos criar alguns arquivos dentro dela para realizar a conexão.
Primeiro, iremos criar o arquivo de configuração do PPP:
$ vi /etc/ppp/options _____________________________________ auth crtscts lock hide-password modem mru 296 mtu 296 lcp-echo-interval 30 lcp-echo-failure 4 noipx persist asyncmap 0xa0000 mru 1500 refuse-chap ipcp-max-failure 30 logfile /home/root/ppp _____________________________________
No meu caso iremos usar o arquivo de autenticação PAP (variam em relação à operadora).
$ vi /etc/ppp/pap-secrets _____________________________________ # * password vivo vivo vivo _____________________________________
O próximo passo foi criar o arquivo dentro da pasta /etc/ppp/peer.
Nele estão as configurações para cara operadora e o caminho para o arquivo chat.
Para a Vivo foi criado o seguinte arquivo:
$ vi /etc/ppp/peers/vivo-3g.provider _____________________________________ hide-password noauth debug defaultroute noipdefault user vivo remotename vivo ipparam vivo persist usepeerdns /dev/ttyUSB0 115200 crtscts replacedefaultroute connect 'chat -v -f /etc/ppp/chat/vivo-3g.chat'
Agora iremos criar o arquivo responsável por enviar os comandos AT para o módulo 3G estabelecer a conexão com a internet. Esse arquivo varia conforme o módulo usado.
$ vi /etc/ppp/chat/vivo-3g.chat _____________________________________ ECHO ON ABORT 'BUSY' ABORT 'NO CARRIER' ABORT 'ERROR' "" ATZ OK \d\dAT+CGDCONT=1,"IP","zap.vivo.com.br" OK \d\d\dATDT*99# CONNECT _____________________________________
Conectando à Internet
Em seguida iremos executar o programa PPP e analisar os log’s para verificar a execução de cada comando AT.
$ pon vivo-3g.provider
Após executado, abra o arquivo de LOG.
$ tail -f "ARQUIVO" $ tail -f ppp
No meu caso obtive o seguinte resultado:
__________________________________________ tail -f ppp.log Sent 3940 bytes, received 2843 bytes. restoring old default route to eth0 [192.168.10.1] restore default route ioctl(SIOCADDRT): Network is unreachable(101) Script /etc/ppp/ip-down started (pid 778) sent [LCP TermReq id=0x2 "User request"] rcvd [LCP TermAck id=0x2] Connection terminated. Script /etc/ppp/ip-down finished (pid 778), status = 0x0 ATZ OK AT+CGDCONT=1,"IP","zap.vivo.com.br" OK ATDT*99# CONNECT Script chat -v -f /etc/ppp/chat/vivo-3g.chat finished (pid 795), status = 0x0 Serial connection established. using channel 2 Using interface ppp0 Connect: ppp0 <--> /dev/ttyACM0 rcvd [LCP ConfReq id=0x1 <asyncmap 0x0> <auth pap> <magic 0x96baf40f> <pcomp> <accomp>] sent [LCP ConfReq id=0x1 <asyncmap 0xa0000> <magic 0xa068db01> <pcomp> <accomp>] sent [LCP ConfAck id=0x1 <asyncmap 0x0> <auth pap> <magic 0x96baf40f> <pcomp> <accomp>] rcvd [LCP ConfAck id=0x1 <asyncmap 0xa0000> <magic 0xa068db01> <pcomp> <accomp>] sent [LCP EchoReq id=0x0 magic=0xa068db01] sent [PAP AuthReq id=0x1 user="vivo" password=<hidden>] rcvd [LCP EchoRep id=0x0 magic=0x96baf40f] rcvd [PAP AuthAck id=0x1 ""] PAP authentication succeeded sent [CCP ConfReq id=0x1 <deflate 15> <deflate(old#) 15> <bsd v1 15>] sent [IPCP ConfReq id=0x1 <compress VJ 0f 01> <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns2 0.0.0.0>] rcvd [LCP ProtRej id=0x2 80 fd 01 01 00 0f 1a 04 78 00 18 04 78 00 15] Protocol-Reject for 'Compression Control Protocol' (0x80fd) received rcvd [IPCP ConfNak id=0x1 <ms-dns1 10.11.12.13> <ms-dns2 10.11.12.14>] sent [IPCP ConfReq id=0x2 <compress VJ 0f 01> <addr 0.0.0.0> <ms-dns1 10.11.12.13> <ms-dns2 10.11.12.14>] rcvd [IPCP ConfNak id=0x2 <ms-dns1 10.11.12.13> <ms-dns2 10.11.12.14>] sent [IPCP ConfReq id=0x3 <compress VJ 0f 01> <addr 0.0.0.0> <ms-dns1 10.11.12.13> <ms-dns2 10.11.12.14>] rcvd [IPCP ConfNak id=0x3 <ms-dns1 10.11.12.13> <ms-dns2 10.11.12.14>] sent [IPCP ConfReq id=0x4 <compress VJ 0f 01> <addr 0.0.0.0> <ms-dns1 10.11.12.13> <ms-dns2 10.11.12.14>] rcvd [IPCP ConfNak id=0x4 <ms-dns1 10.11.12.13> <ms-dns2 10.11.12.14>] sent [IPCP ConfReq id=0x5 <compress VJ 0f 01> <addr 0.0.0.0> <ms-dns1 10.11.12.13> <ms-dns2 10.11.12.14>] rcvd [IPCP ConfNak id=0x5 <ms-dns1 10.11.12.13> <ms-dns2 10.11.12.14>] sent [IPCP ConfReq id=0x6 <compress VJ 0f 01> <addr 0.0.0.0> <ms-dns1 10.11.12.13> <ms-dns2 10.11.12.14>] rcvd [IPCP ConfReq id=0x1] sent [IPCP ConfNak id=0x1 <addr 0.0.0.0>] rcvd [IPCP ConfRej id=0x6 <compress VJ 0f 01>] sent [IPCP ConfReq id=0x7 <addr 0.0.0.0> <ms-dns1 10.11.12.13> <ms-dns2 10.11.12.14>] rcvd [IPCP ConfReq id=0x2 <addr 179.133.47.109>] sent [IPCP ConfAck id=0x2 <addr 179.133.47.109>] rcvd [IPCP ConfNak id=0x7 <addr 179.133.47.109> <ms-dns1 187.100.246.254> <ms-dns2 187.100.246.251>] sent [IPCP ConfReq id=0x8 <addr 179.133.47.109> <ms-dns1 187.100.246.254> <ms-dns2 187.100.246.251>] rcvd [IPCP ConfAck id=0x8 <addr 179.133.47.109> <ms-dns1 187.100.246.254> <ms-dns2 187.100.246.251>] local IP address 179.133.47.109 remote IP address 179.133.47.109 primary DNS address 187.100.246.254 secondary DNS address 187.100.246.251 Script /etc/ppp/ip-up started (pid 805) Script /etc/ppp/ip-up finished (pid 805), status = 0x0 ______________________________________________________
Conforme visto no log, o script chat é executado passo a passo até obter:
ATDT*99# CONNECT
Você pode validar a sequência de comando necessária para chegar até o connect por meio do terminal serial. Uma vez validado você pode gerar seu chat script personalizado.
Após verificar que foi possível obter um IP da operadora, veja se a interface de rede ppp0 está ativa:
root@apalis-imx6:/etc/ppp# ifconfig
eth0 Link encap:Ethernet HWaddr 00:14:2D:C0:00:4C
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:1181 errors:0 dropped:0 overruns:0 frame:0
TX packets:1223 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:107025 (104.5 KiB) TX bytes:149841 (146.3 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:22 errors:0 dropped:0 overruns:0 frame:0
TX packets:22 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1536 (1.5 KiB) TX bytes:1536 (1.5 KiB)
ppp0 Link encap:Point-to-Point Protocol
inet addr:179.133.47.109 P-t-P:179.133.47.109 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:296 Metric:1
RX packets:13 errors:0 dropped:0 overruns:0 frame:0
TX packets:35 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3
RX bytes:1330 (1.2 KiB) TX bytes:2131 (2.0 KiB)
Testando a conexão
Em seguida, teste a conexão com a internet pingando algum IP externo:
root@apalis-imx6:/etc/ppp# ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8): 56 data bytes 64 bytes from 8.8.8.8: seq=0 ttl=45 time=182.304 ms 64 bytes from 8.8.8.8: seq=1 ttl=45 time=34164.126 ms 64 bytes from 8.8.8.8: seq=2 ttl=45 time=33164.085 ms
Para configurar o DNS podemos usar o comando a seguir, e então “pingar” uma URL. Por exemplo:
$ echo nameserver 8.8.8.8 > /etc/resolv.conf $ ping google.com
Podemos evitar que o arquivo resolv.conf seja reescrito quando a placa é reiniciada com o comando:
$ chattr +i /etc/resolv.conf
Agora é possível acessar a placa via SSH de um computador externo conectado na internet usando o comando a seguir:
$ ssh root@179.133.47.109
Configurando um nome Host para nosso IP
Outra coisa que podemos fazer é dar ao nosso IP um nome host. Para isso utilizamos o serviço do site NoIP. Foi criada uma conta gratuita e adicionado um Host. No nosso caso foi escolhido toradex.noip.me.
Após criado um host no site podemos acessar a placa com o comando:
$ ssh root@toradex.noip.me
No nosso caso, sempre que reiniciamos a conexão ou o modem 3G, recebemos um novo endereço IP. Então se tentarmos conectar com a placa novamente, vamos notar que não temos mais acesso. Para contornar esse problema, existe o método chamado DNS Dinâmico (Dynamic Domain Name System). O site noip.me também oferece o serviço de DNS Dinâmico. Algumas informações para realizar esse processo de troca de IP podem ser encontradas aqui. Basicamente precisamos fazer um http request para o site deles contendo informações como IP, nome do host, nome de usuário e senha.
Para fazer esse request foi feito um programa em Python, que é executado quando iniciamos a conexão do modem, e basicamente segue a seguinte sequência:
#!/usr/bin/python
import sys
import requests
import netifaces as ni
user = 'xxxxxxx'
pswd = 'xxxxxxx'
ni.ifaddresses('ppp0')
ip = ni.ifaddresses('ppp0')[2][0]['addr']
myhostname = 'toradex.noip.me'
payload = {'hostname' : myhostname , 'myip' : ip}
r = requests.get("https://dynupdate.no-ip.com/nic/update", params=payload, auth=(user,pswd))
print " "
if "good" in r.text:
print "Hello", user, "!"
print "Your IP was successfully updated to:", ip
print myhostname, "is up and running!"
if "nochg" in r.text:
print "Hello", user, "!"
print "Your IP", ip, "is still active, no change needed"
if "nohost" in r.text:
print "The given Host name", myhostname, "does not exist under specified account"
print "Please review your Host name and try again"
if "badauth" in r.text:
print "Login and/or Username incorrect"
print "Please correct your credentials and try again"
if "911" in r.text:
print "Sorry for the incovenience but we are experiencing some problems right now"
print "Please try again later"
print "noip.com says:", r.text
print " "
Após criado o programa em python e tornado o mesmo executável com o comando chmod +x, podemos colocá-lo na pasta /etc/ppp/ip-up.d/ que é a pasta onde se encontram os scripts executados após o link da conexão ppp ser estabelecido ou criar dentro dessa pasta um pequeno script que chama nossa aplicação em Python.
No diretório /etc/ppp/ se encontram os arquivos como ip-down, ip-up, ppp_on_boot e também os arquivos que criamos no início do artigo. Sinta-se livre para abrir esses arquivos e verificar o que cada um faz.
O ip-up é o script que chama outro script ou programa em python localizado dentro da pasta ip-up.d.
No nosso caso criamos um pequeno script dentro da pasta ip-up.d:
#!/bin/bash python /home/root/noipReq.py > /home/root/noipLog.log
Obs: O script não tem a terminação .sh.
Note que todos os comandos print dentro do programa em python podem ser vistos depois no arquivo de log.
root@colibri-imx6:~# cat noipLog.log Hello giovannibauer ! Your IP was successfully updated to: 179.92.172.193 toradex.noip.me is up and running! noip.com says: good 179.92.172.193
Se tudo foi configurado corretamente, sempre que recebemos um novo IP da Vivo ao realizarmos uma nova conexão, o sistema automaticamente atualiza o nosso Host criado no noip.com, tornando possível o acesso à placa qualquer que seja o seu endereço IP.
A partir disso, é possivel realizar muitas outras atividades com relação a redes. Uma delas é compartilhar a internet da placa em que temos conectado o modem 3G USB com algum outro computador via ethernet. Para isso configuramos uma rede LAN básica entre dois computadores e usamos o seguinte comando na placa:
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
Além do compartilhamento de internet também é possível fazer port forwarding e muitas outras funções de rede.
Considerações Finais
Conforme visto no tutorial, o sistema operacional Linux te traz diversas funcionalidades já prontas. Sendo assim, basta apenas configurá-las corretamente para obter acesso à interface de rede ppp0. Outro ponto importante é que, independentemente da interface de rede usada, o modo de programar é o mesmo e o gerenciamento do meio (eth0, wlan0 ou ppp0) pelo qual a conexão vai ser estabelecida é feito automaticamente pelo Linux dependendo das rotas. Para aqueles que requerem o uso de redes em projetos e prezam pela flexibilidade do sistema, a utilização do Linux em sistemas embarcados traz uma grande facilidade.
Referências






