Discuta este tópico no fórum

Se este conteúdo te ajudou, deixe um presente!

quarta-feira, 31 de maio de 2017

OpenWrt/LEDE: sane-backends 1.0.27 e hplip submetido ao repositório oficial

Mais um artigo da série sobre o OpenWrt/LEDE.

Faz longos 2 anos desde a última atualização do sane-backends. Enfim, lançaram uma nova versão: 1.0.27. Se notar a falta da 1.0.26, ela não existiu mesmo.

Mudou algo? Sim, bugs, falhas de segurança, melhorias diversas. Nada de grande nota. Alguns dos patches do pacote também foram aceitos no projeto, reduzindo o meu trabalho de mantê-lo.

As instruções para instalação continuam as mesmas. Com a diferença que o repositório para o LEDE está em http://luizluca.github.io/lede/. Quem já está com o pacote instalado e quer somente atualizar, basta adicionar o repositório (veja no atalho anterior) e trocar o install por upgrade.
router# opkg list-upgradable | grep sane
router# opkg upgrade <os pacotes do sane listados anteriormente)
Por sinal, sempre é bom observar os pacotes atualizáveis pelo "opkg list-upgradable". Normalmente são só correções de bugs (em especial, de falhas de segurança). Para pacotes instalados depois da gravação da firmware, não deve dar problema. Para os que já estavam na firmware, tem que ver se terá espaço livre para instalá-los.

Para quem não está com pressa, a próxima versão do OpenWrt/LEDE já terá a versão atualizada sem a necessidade de adicionar o meu repositório.

Outra novidade importante é que submeti o hplip ao repositório oficial. O entrave até agora era a falta do cups, que ficou sem mantenedor desde a versão OpenWrt CC. Eu criei um pequeno pacote libcups apenas para gerar as bibliotecas necessárias para o SANE compilar. Se for aceito, vai simplificar bastante a instalação do hplip.

Se pintar um problema, tem sempre o fórum deste blog. Até a próxima.

domingo, 21 de maio de 2017

OpenWRT/LEDE: Capturando pacotes de dentro do roteador

Mais um artigo da série sobre o OpenWRT/LEDE.

Algumas vezes já me perguntaram o que deveria aprender para ser um bom administrador de redes.  A resposta é sempre a mesma: "Várias coisas, mas principalmente o Wireshark".

O Wireshark é uma excelente ferramenta de diagnóstico e de estudo. Eu normalmente recomendo que qualquer bom administrador de redes deve entender todos os campos até a camada do TCP/UDP/ICMP e boa parte dos protocolos mais usados como DHCP (bootp), DNS, HTTP. Se entender para que cada campo serve, implicitamente vai conhecer quase tudo que precisa.

Além, claro, de capturar pacotes, o wireshark tem diversas ferramentas de análise excelentes para diagnósticos diversos (ver nota [1] no fim do artigo). Ele próprio também faz diversas validações de protocolos conhecidos. Perdi a conta da quantidade de problemas que o próprio wireshark informou. Bastou capturar pacotes, abrir no wireshark e ele já mostrava o pacote com uma cor diferente e uma bela mensagem informando o problema.

Qualquer coisa que eu falar além sobre os recursos do wireshark será superficial demais para ser útil. Então, vamos ao tema propriamente dito deste artigo. Os melhores (e alguns dos ruins também) permitem que você capture de alguma forma o tráfego que passa nas suas interfaces. E o OpenWRT/LEDE? Bem, ele não tem uma forma padrão de fazer isso pois não precisa.

Por ser simplesmente um Linux, existem diversas formas de fazer essa captura de forma simples. Se existir uma unidade de armazenamento no roteador, pode fazer a captura em arquivo e analisar depois. Mas se quiser fazer "ao vivo", pode usar o recurso de pipes. A que eu mais gosto é usando um SSH para rodar o tcpdump no roteador e, por pipe, fazer um wireshark local ler os pacotes enviados pela entrada padrão. Parece complexo mas é só uma linha:
$ ssh root@router tcpdump -U -w - -s0 -i eth0.2 | wireshark -i - -k
A eth0.2 é a interface que quero capturar. Poderia ser outra como a br-lan ou mesmo any para pegar pacotes de todas as redes. Só tome cuidado de excluir o próprio SSH da captura para não criar um processo retroalimentado: "um pacote qualquer capturado é enviado por SSH que é um pacote qualquer e novamente capturado...". Então, use os filtros pcap como argumento do tcpdump para excluir, no mínimo, o SSH da captura (se ele estiver utilizando uma interface capturada). Ex:
$ ssh root@router tcpdump -U -w - -s0 -i any not port 22 | wireshark -i - -k
Ou:
$ ssh root@router tcpdump -U -w - -s0 -i any not host oip.do.meu.pc | wireshark -i - -k
Ah, é preciso antes de tudo instalar o tcpdump no roteador. Recomendo o pacote tcpdump-mini, que deve atender as necessidades básicas para capturar pacotes para análise no wireshark.

Isso vale também para capturar pacotes de servidores remotos que não têm wireshark (e nem deveriam), mas normalmente têm o tcpdump. Só trocar no comando o "router" para o nome do servidor e pode reaproveitar a dica.

Tunelar pelo SSH pode não ser a forma mais eficiente de fazer essa captura mas é a mais simples. Casos especiais onde o excesso de tráfego e os restritos recursos do roteador não aguentarem o trabalho, pode-se pensar em enviar os pacotes por netcat e sem criptografia. Mais inseguro, complicado mas bem mais leve para o roteador. Mas casos especiais são especiais e fica para outra oportunidade.

Alguma dúvida? Criei um fórum para o blog e vou criar um tópico para cada novo artigo.

Até a próxima!

[1] : na verdade, eu nem gosto de capturar pacotes diretamente com o wireshark pois a captura de pacotes exige privilégios especiais, que normalmente são supridos rodando a captura como root. Entretanto, como qualquer software, o wireshark é passível de vulnerabilidades. Um atacante que conheça uma delas pode injetar pacotes que a exploram em qualquer interface que ele tenha acesso, mesmo em uma insegura como a entrada da internet. Se um administrador capturar esse pacotes com o wireshark, ele processará o pacote malicioso e o atacante tomará conta do wireshark. Se o wireshark estiver rodando como root, o atacante rodará o código malicioso com os acessos de root na máquina atual. Então, procurem não rodar o wireshark como root e, na dúvida, use-o com captura remota e rode-o dentro de uma máquina virtual descartável sem acessos especiais.

quinta-feira, 16 de março de 2017

OpenWRT/LEDE: Debugando código dentro do roteador (e corrigindo bugs)

Mais um artigo da série OpenWRT/LEDE.

Fazer o debug de um programa muda a forma de desenvolvimento de um código. É imensamente melhor do que usar printf ao longo do código. Você pode ver os valores de qualquer variável, adicionar paradas condicionais, ver onde ele engasgou, etc. Para tudo isto, basta compilar seu código com os símbolos de debug, acesso ao código fonte (ajuda) e um debugger.

Uma das coisas que eu acho fantástico no mundo Linux é, diante de um problema, instalar os símbolos, código fonte e disparar um debugger. Isto com o processo rodado! Apesar dos programas instalados não conterem os símbolos, normalmente a distribuição fornece estes símbolos em um pacote a parte. Eu parto de um processo problemático em execução para um passo a passo dentro do código em poucos minutos. Fantástico!

Agora voltamos ao tema do artigo: como posso "debugar" dentro do OpenWRT/LEDE? Temos os símbolos nos executáveis? Não, são removidos antes de serem empacotados pelo sstrip. Mesmo que não fossem, normalmente você não teria espaço no roteador para instalar um executável com os símbolos de debug e mais o código fonte (ao menos que tenha expandido o disco com uma unidade externa). O gdb seria até pequeno, mas é sem símbolos e o fonte ele não tem muita utilidade. Mesmo se tivesse tudo isso, ainda debugar pelo gdb remotamente não é a forma mais amigável para este trabalho. Para coisas maiores, uma interface gráfica pode deixar o trabalho mais agradável.

Felizmente o OpenWRT/LEDE já está preparado para esta interação. Vamos tomar como exemplo o sane-backends, pacote que mantenho no OpenWRT/LEDE. Ele estava com um comportamento engraçado. O scanner aparecia na listagem mas sempre falhava ao escanear. Rodando localmente um escaneamento, eu obtinha:
root@router.lan3:~# scanimage >/dev/null
Trace/breakpoint trap
Parei o xinetd (que estava aguardando pelos pedidos do saned) e rodei o saned em modo debug. Novamente, o famigerado erro:
root@router.lan3:~# saned -d 128

[saned] main: starting debug mode (level 2)
[saned] saned (AF-indep+IPv6) from sane-backends 1.0.25 starting up
[saned] do_bindings: [0] bind failed: Address in use
[saned] check_host: access by remote host: ::ffff:192.168.3.20
[saned] init: access granted to luizluca@::ffff:192.168.3.20
Trace/breakpoint trap
Não fui apresentado, mas pelo nome, parece algo explicitamente introduzido. Alguma verificação falhou e abortou o programa. Sem mais informações por meio de mensagens, resta o debug do código.

O primeiro passo é ter os fontes e os códigos compilados. Provavelmente tudo isso se aplica caso opte por usar o SDK, mas vou, a princípio considerar que você está usando a árvore completa do projeto. Você precisa dos fontes e configurar o ambiente para compilar, ao menos, o sane-backend. Esta preparação já foi feita em outro artigo sobre compilação a partir dos fontes.

No roteador, eu irei debugar o programa saned, que não contém informações de debug. No pacote, ele é bem reduzido (menos que 33 kbytes):
$ tar --to-stdout -xzf bin/packages/mips_24kc/packages/sane-daemon_1.0.25-2_mips_24kc.ipk ./data.tar.gz | tar tzv ./usr/sbin/saned

-rwxr-xr-x root/root     32900 2017-03-12 22:40 ./usr/sbin/saned
Porém, antes de ser limpo pelo sstrip, ele tinha:
$ stat -c "%A %U %G %y %s %n" staging_dir/target-mips_24kc_musl-1.1.16/root-ar71xx/usr/sbin/saned
-rwxr-xr-x luizluca deluca 2017-03-12 22:40:49.510354194 -0300 44200 staging_dir/target-mips_24kc_musl-1.1.16/root-ar71xx/usr/sbin/saned
Agora vamos recompilar o pacote com os símbolos. Você pode fazer isso adicionando a opção no menuconfig para incluir os símbolo de debug em toda a árvore. Eu prefiro adicionar pontualmente os símbolos em alguns pacotes. Para isto, basta incluir a configuração extra na chamada do make:
$ make -j5 package/sane-backends/{clean,compile} CONFIG_DEBUG=y
Adicione ainda um V=s se quiser ver muitas letrinhas passando (ou precisar resolver problemas de compilação). Se fizer, observe um -g3 a mais nos argumentos do gcc.

O resultado é um executável relativamente maior:
$ stat -c "%A %U %G %y %s %n" staging_dir/target-mips_24kc_musl-1.1.16/root-ar71xx/usr/sbin/saned -rwxr-xr-x luizluca deluca 2017-03-12 23:56:52.157169597 -0300 188296 staging_dir/target-mips_24kc_musl-1.1.16/root-ar71xx/usr/sbin/saned
Mas o ipkg continua exatamente igual, pois os símbolos ainda foram removidos antes do empacotamento.

No meu caso, uso o driver hplip. Então, incluí em todo o processo anterior este pacote. Além de adicionar no menuconfig, o make ficou assim:
$ make -j5 package/{sane-backends,hplip}/clean package/{sane-backends,hplip}/compile CONFIG_DEBUG=y
Tudo pronto, agora vamos ao roteador. Vou instalar o gdbserver. Como o nome já diz, é um servidor do gdb, permitindo que um gdb na minha máquina use um executável rodando em uma máquina remota.
root@router.lan3:~# opkg install gdbserver
E agora, repito o comando do saned mas pelo gdbserver:

root@router.lan3:~# gdbserver :9000 /usr/sbin/saned -d 128Process /usr/sbin/saned created; pid = 4391Listening on port 9000
A princípio, ele inicia o processo parado, aguardando a conexão do gdb e sua autorização para continuar. No lado do computador, o OpenWRT/LEDE já fornece um "facilitador" para configurar o gdb remoto:
$ ./scripts/remote-gdb router:9000 staging_dir/target-mips_24kc_musl-1.1.16/root-ar71xx/usr/sbin/saned
Pronto! Estou com o debugger na mão. Peço ao gdb para parar ao receber qualquer sinal ("catch signal all"). Depois, libero a execução ("cont") até chegar em algo interessante.
Thread 1 "saned" hit Catchpoint 1 (signal SIGTRAP), memcpy (__n=270, __os=0x77dc3a76 <ms+770086>, __od=0x77dc3a74 <ms+770084>)    at /home/luizluca/prog-local/lede/17.01/staging_dir/toolchain-mips_24kc_gcc-5.4.0_musl-1.1.16/include/fortify/string.h:4848 __builtin_trap();
(gdb) bt#0  memcpy (__n=270, __os=0x77dc3a76 <ms+770086>, __od=0x77dc3a74 <ms+770084>) at /home/luizluca/prog-local/lede/17.01/staging_dir/toolchain-mips_24kc_gcc-5.4.0_musl-1.1.16/include/fortify/string.h:48#1  device_id (fd=1,     buffer=0x77dc3a74 <ms+770084> "\001\020MFG:HP;MDL:Officejet J4660 series;CMD:MLC,PCL,PML,DW-PCL,DESKJET,DYN;1284.4DL:4d,4e,1;CLS:PRINTER;DES:CB786A;SN:BR145GF09J052W;S:038000C484001021002c1f0005cc2d8002b;J:", ' ' <repete 20 vezes>, ";Z:0102,050"..., size=1024) at io/hpmud/musb.c:773#2  0x77cbe5cd in musb_open (pd=<optimized out>) at io/hpmud/musb.c:1160#3  0x77cb8067 in hpmud_open_device (uri=<optimized out>, iomode=HPMUD_DOT4_MODE, dd=0x41b0a4) at io/hpmud/hpmud.c:539#4  0x77ebbc51 in sclpml_open (device=0x418a96 "/usb/Officejet_J4660_series?serial=BR145GF09J052W", pHandle=0x7ffffaf4) at scan/sane/sclpml.c:2016#5  0x77eb02f7 in sane_hpaio_open (devicename=0x418a96 "/usb/Officejet_J4660_series?serial=BR145GF09J052W", pHandle=0x7ffffaf4) at scan/sane/hpaio.c:267#6  0x77f3f673 in sane_dll_open (full_name=<optimized out>, meta_handle=0x0) at dll.c:1201#7  0x77f31e97 in sane_open (name=<optimized out>, h=<optimized out>) at dll-s.c:23#8  0x00403391 in process_request (w=0x418198 <wire>) at saned.c:1916#9  0x00403a99 in handle_connection (fd=<optimized out>) at saned.c:2283#10 0x00402031 in run_standalone (argv=<optimized out>, argc=3) at saned.c:3167#11 main (argc=<optimized out>, argv=<optimized out>) at saned.c:3345

Hum... fortify... O LEDE introduziu opções de compilação que restringem alguns comportamentos inseguros (_FORTITY_SOURCE), "fortificando" o programa contra ataques. Pela pilha, isso foi dentro do hplip. Acho que ele tem algum problema...

A chamada em questão foi em io/hpmud/musb.c, linha 773:

 771     if (len > 2)
 772         len -= 2;
 773     memcpy(buffer, buffer+2, len);    /* remove length */
 774     buffer[len]=0;
 775     DBG("read actual device_id successfully fd=%d len=%d\n", fd, len);

Opa! Copiando o buffer sobre ele mesmo para tirar os dois primeiros bytes? OK, mas não usando memcpy! Muito feio! Isto nunca era para dar certo... O memcpy simplesmente copia de um lado para outro, desconsiderando sobreposição. Isto quer dizer, pode copiar do começo ao fim (ou o inverso), em blocos de vários bytes, etc. Foi sorte ter funcionado até agora (e funcionou?). A alternativa correta é o memmove, que verifica possíveis sobreposições e decide se copia de trás para frente, ou do início ao fim. Caso não tenha sobreposições, simplesmente chama o memcpy. E  claro que temos sobreposições aqui!

Vamos tentar a última versão 3.16.11 do hplip? Não, ainda está lá o memcpy. Vamos precisar fazer um patch.

A melhor forma de trabalhar com patches dos programas empacotados no OpenWRT/LEDE é pelo quilt. Ele gerencia os patches de forma menos dolorida, em especial para atualizar os endereços depois de uma mudança de versão, onde os "hunks" funcionaram. Como acabei de atualizar a versão do hplip, devem ocorrer mudanças nos fontes e os patches existentes precisam ser atualizados:
$ make package/hplip/{clean,prepare} QUILT=y
$ cd build_dir/target-mips_24kc_musl-1.1.16/hplip-3.16.11
$ quilt push
Aplicando caminho 010-libusb_fix.patch
patching file configure.in
Hunk #1 succeeded at 561 (offset 38 lines).
Agora no caminho 010-libusb_fix.patch
 
$ quilt refresh # atualizar o endereço do patch
Patch atualizado 010-libusb_fix.patch
Tudo certo até aqui. Patch atualizado sem esforço.
$ quilt push
Aplicando caminho 020-remove_cups_dep_on_scan.patch
patching file scan/sane/hpaio.c
Hunk #2 FAILED at 172.
Hunk #3 FAILED at 232.
Hunk #4 FAILED at 259.
3 out of 4 hunks FAILED -- rejects in file scan/sane/hpaio.c
patching file Makefile.am
Hunk #1 succeeded at 60 with fuzz 1 (offset 1 line).
Caminho 020-remove_cups_dep_on_scan.patch não aplica (force com -f)
Hum... conflito. Preciso intervir manualmente.
$ quilt push -fAplicando caminho 020-remove_cups_dep_on_scan.patchpatching file scan/sane/hpaio.cHunk #2 FAILED at 172.Hunk #3 FAILED at 232.Hunk #4 FAILED at 259.3 out of 4 hunks FAILED -- saving rejects to file scan/sane/hpaio.c.rejpatching file Makefile.amHunk #1 succeeded at 60 with fuzz 1 (offset 1 line).Caminho 020-remove_cups_dep_on_scan.patch aplicado (forçado; necessita ser atualizado)
$ quilt edit scan/sane/hpaio.c<faz a mágica para resolver o conflito...>$ quilt refresh
Agora vamos, enfim, fazer o novo patch:
$ quilt new 030-replace_unsafe_memcpy_with_memmove.patch$ quilt edit io/hpmud/musb.c<troca o memcpy por memmove>$ quilt refresh
De volta a raiz do projeto, pedimos que ele atualize os patches: 
make package/hplip/update QUILT=y
E, por fim, limpar e recompilar:
make package/hplip/{clean,compile} CONFIG_DEBUG=y
Tudo compilado, só copiar, instalar e testar

$ scp bin/packages/mips_24kc/packages/hplip-* root@router:/tmp
root@router.lan3:~# opkg install /tmp/*hplip*
Upgrading hplip-common on root from 3.15.7-1 to 3.16.11-1...
Upgrading hplip-sane on root from 3.15.7-1 to 3.16.11-1...
Configuring hplip-common.
Configuring hplip-sane.
root@router.lan3:~# 
E...

Funcinou!


Infelizmente, o "funcionar" é não mostram uma mensagem de erro e não abortar o processo. Não faz muito sentido colar a saída.

Agora, para a cereja do bolo, bug submetido ao hplip.

Até a próxima. Happy Hacking!

domingo, 12 de março de 2017

OpenWRT/LEDE: Compilando a partir dos fontes

Mais um artigo da série OpenWRT/LEDE.

Dificilmente alguém vai precisar compilar o seu sistema operacional. Isto se aplica também aos ambientes embarcados. O OpenWRT/LEDE fornece o acréscimo de programas por pacotes, a personalização dos pacotes de uma firmware, ou mesmo um ambiente de desenvolvimento para compilar pacotes individuais. Tudo isso evita em muito a necessidade de recompilar todo o ambiente. Todavia, às vezes é inevitável.

Sempre que a mudança não é em "um pacote", vai precisar recompilar a árvore. Mudança de um parâmetro do kernel? Parâmetro do gerenciador de boot? Alguma outra coisa? Pode se preparar para recompilar tudo. E tudo é bastante coisa. O ambiente não só recompila o que vai no roteador mas compiladores, ligadores, ferramentas de geração de firmware, sistema de arquivos, etc. Tudo para ser o mais independente possível do sistema operacional onde está sendo compilado.

Como eu começo? Primeiro precisa de algumas ferramentas básicas, como o git, o gcc (para compilar o gcc do OpenWRT/LEDE, o make e algumas bibliotecas de desenvolvimento para compilar o menuconfig. Já existem algumas linhas de comando prontas para instalar estes requisitos no site do LEDE. Vale a olhada. Depois, só baixar os fontes. Vou pegar o atual ramo estável do LEDE:
git clone --branch lede-17.01 https://github.com/lede-project/source.git
E depois configurar o ambiente:
make menuconfig
No menuconfig, você pode configurar todo seu ambiente. Normalmente você terá que configurar, ao menos, o alvo (target) e, preferencialmente, o modelo do roteador (por padrão, ele gera firmware para todos!). Este é o local para adicionar os pacotes. A simbologia é:
  • [*] significa que o pacote estará na firmware gerada ou uma opção foi selecionada;
  • [M] significa que o pacote será gerado (ipk) mas não estará na firmware;
  • [ ] significa que o pacote não será compilado ou opção não selecionada.
Saindo e salvando, basta compilar:
make
Ou, se tiver processadores sobrando, deixar o make usar diversos processadores:
make -j9
Não achei no menu um pacote! Busque apertando "/" no menuconfig. Ainda não o Luci! A maioria dos pacotes estão nos feeds adicionais, por padrão sem pacotes incluídos. Para incluir o "meu-pacote-querido":
./scripts/feeds update
./scripts/feeds install meu-pacote-querido
E ele aparecerá no menu (previamente ainda não selecionado).

Ao terminar o processo do make, sua firmware estará em:
  • bin/targets/<alvo configurado>/generic/
Os pacotes estarão em:
  • bin/targets/<alvo configurado>/generic/packages/ (para os específicos deste alvo)
  • bin/packages/<arquitetura>/luci (para pacotes da arquitetura que o <alvo configurado> pertence)
Você está pronto para se divertir. Só gravar a nova firmware ou copiar e instalar os novos pacotes.

Quer mudar algo depois? Mexer em um pacote? As receitas estarão em packages ou em feeds. Se mudar um pacote, como o sane-backends, pode recompilá-lo individualmente:
make package/meu-pacote-querido/compile
Ou rodar simplesmente o make geral e deixar ele encontrar o que falta fazer (vai demorar mais). Se tiver problemas, pode mostrar as informações da compilação:
make package/meu-pacote-querido/compile V=s
É isso pessoal. Espero que esta informação ajude nos primeiros passos de desenvolvimento do OpenWRT/LEDE. Quem sabe não ajude a revelar um novo desenvolvedor para o projeto?

Happy hacking!

quinta-feira, 2 de março de 2017

OpenWRT/LEDE: atualizando para LEDE 17.01.0

Mais um artigo da série sobre o OpenWRT/LEDE.

Como citei no post anterior, o sucessor do OpenWRT é o LEDE. E este acaba de lançar a sua primeira versão: 17.01.0.

Sim, este artigo repete diversos pontos do artigo de atualização anterior. Afinal, apesar da mudança no nome, ainda é a mesma base.

96,72% dos problemas com instalação/atualização com LEDE que ajudo é em relação a escolha incorreta da imagem da firmware. Como sempre, recomendo a versão squashfs, que possui modo de recuperação. Pegue o arquivo no download da última versão estável e nunca em um endereço qualquer, mesmo que seja na wiki do OpenWRT/LEDE. Normalmente a wiki referencia a versão em desenvolvimento, que não é a que você quer. As versões dentro de "releases", exceto as com o rc (release candidate) são estáveis. Pegue preferencialmente a mais nova (com número maior). Evite qualquer firmware que tenha no caminho palavras como "trunk", "snapshot" ou "rc1", "rc2"... exceto se estiver testando algo. As versõe estáveis também referenciam a versão do LEDE no nome como em "lede-17.01.0-r3205-59508e3-ar71xx-generic-tl-wr2543-v1-squashfs-sysupgrade.bin", ao contrário da versão instável/em desenvolvimento "lede-ar71xx-generic-tl-wr2543-v1-squashfs-sysupgrade.bin".

A nomeclatura da versão é parecida com a adotada pelo OpenWRT: ano.mês.correção. O ano/mês se referem ao momento que foi criado um ramo nos fontes para o lançamento da nova versão. Já o último número é apenas um sequencial de correção. Então, para quem usa uma versão 17.01.x, a próxima 17.01.x+1 conterá apenas bugs resolvidos (em especial, os de segurança) e deve ser considerada como recomendada. Prometeram lançar versões de correções periodicamente. Vamos acompanhar

Em downloads, navegue para releases, a versão desejada (17.01.0 até agora), "targets"  e seguindo o caminho da "arquitetura alvo" em uso no seu roteador. Se você já é um usuário do OpenWRT, você pode vê-la olhando o arquivo /etc/openwrt_release:
root@router:~~# cat /etc/openwrt_release
DISTRIB_ID='OpenWrt'
DISTRIB_RELEASE='15.05'
DISTRIB_REVISION='r46767'
DISTRIB_CODENAME='chaos_calmer'
DISTRIB_TARGET='ar71xx/generic'
DISTRIB_DESCRIPTION='OpenWrt Chaos Calmer 15.05'
DISTRIB_TAINTS=''
A diferença no LEDE para o OpenWRT é a presença do "targets" e, no mesmo nível, "packages". Comentei esta diferença no post anterior, mas normalmente o "packages" não é para você e será usado quase que exclusivamente pelo opkg de forma transparente.

OK, chegamos a uma lista enorme de firmwares! Vamos entender o que significa cada parte do nome do arquivo. O formato mudou um pouco no LEDE. Tomemos por exemplo "lede-17.01.0-r3205-59508e3-ar71xx-generic-tl-wr2543-v1-squashfs-sysupgrade.bin":
  • lede é o sistema operacional que você está instalando ;-)
  • 17.01.0 é a versão do lede. Em firmwares instáveis, este campo não existe!
  • r3205 é um sequencial do número de mudanças no fonte. Serve para saber se um arquivo é mais velho do que outro.
    • Caso apareça algo a mais como r3205+2, significa que alguém deve ter feito 2 mudanças não oficiais sobre a versão r3205.
  • 59508e3 é a versão resumida do hash da última mudança no git. Você pode usar comandos git sobre ela nos fontes do LEDE como "git log 59508e3".
  • ar71xx é a família do SoC (chip) do seu dispositivo. Você descobre isso na wiki do projeto ou abrindo o seu roteador e lendo os CI.
  • generic é o formato do layout da flash. Normalmente será o "generic", exceto para casos especiais.
  • tl-wr2543-v1 este é o modelo do seu roteador! Observe em especial a versão do HW (v1) pois ela pode mudar completamente o dispositivo, inclusive de família do SoC.
  • squashfs é o tipo do armazenamento da imagem. Nesta, existe uma cópia imutável dos arquivos (ROM) e o resto da flash é usada para, de forma transparente, guardar as modificações (overlay). Tudo parece editável para o usuário. A diferença é que você pode, a qualquer momento, apagar as diferenças e restaurar o sistema pós-instalação. Pode existir também o formato jffs2. Neste, não existe uma ROM e tudo pode ser realmente apagado. Alterou o arquivo errado? Vai ter que recuperar pela serial, JTAG ou arrancando a flash. Não recomendo!\
  • sysupgrade é a função da firmware. Esta é para atualizar de um OpenWRT/LEDE para outro (e, em alguns casos, de outros firmwares alternativos como DD-WRT). Porém, não deve ser reconhecido pela firmware original do roteador. Para primeira instalação, ainda com a firmware original, use a variante "factory".
Finalmente, é muito importante ler a wiki do seu roteador independente se ele já funcionava na versão anterior! São poucos minutos de leitura que podem salvar horas de trabalho ou mesmo seu roteador. Durante esta fase de OpenWRT e LEDE, sugiro que procurem na wiki de ambos os projetos.

Bem, se eu simplesmente ir na interface, fornecer a nova imagem, ele vai funcionar? Provavelmente, mas talvez não é a maneira que dê menos trabalho. A atualização pode preservar as configurações mas não os programas instalados. Se você tem raiz expandida em unidade externa, a encrenca é ainda maior.

Mas eu nunca instalei um programa! OK, use a interface web e provavelmente todas as configurações serão migradas sem problemas. Já testei isto em mais de um roteador e funcionou sem problemas. Mas faça o backup antes! Caso tenha instalado algum pacote, continue lendo.

Em primeiro lugar, precisamos do plano de retorno caso a nova versão não se comporte como o esperado. Faça sempre um backup geral do seu sistema. No processo de upgrade, eu sugiro que sejam feitas as três formas diferentes de backup que eu comento no artigo sobre o temabackup gerado pelo sistema, lista de pacotes instalados e todos os arquivos do overlay. Este último serve apenas para o plano de retorno caso algo importante não funcione para você na nova versão (e para recuperar algo que não entrou no backup do sistema).

Agora, finalmente, você está pronto para enviar a nova firmware. Se você usa um armazenamento externo para expandir a raiz, leia até o final deste post antes de iniciar o processo! Faça o upgrade pela interface web ou pelo terminal. Inclusive, você pode baixar o arquivo diretamente no roteador. Ex:

# cd /tmp
# wget http://downloads.lede-project.org/releases/17.01.0/targets/.../generic/lede-17.01.0-r3205-59508e3-....-squashfs-sysupgrade.bin
# sysupgrade lede-17.01.0-r3205-59508e3-....-squashfs-sysupgrade.bin

Só cuidado ao colar a URL. O downloads.lede-project.org usa HTTPS por padrão mas o wget do OpenWRT não tem suporte para HTTPS (por padrão). Contudo, o downloads.lede-project.org aceita http sem problemas, só tirar o "s" se tiver problemas.

E pode fazer pela Wifi? Os fabricantes não recomendam usar sempre um computador "conectado por cabo"? Sim, e já tive problemas com atualização a partir da firmware do fabricante por não escutar isto. Mas não com OpenWRT/LEDE. Se estiver atualizando (e não instalando a primeira vez!), pode fazer pela Wifi sem problemas. Quando a gravação for iniciada, todo o processo já está independente do computador cliente. Só não pode faltar energia ;-)

E depois do "Enter"/"Gravar", é a hora que você reza. Sempre dá um frio na barriga.

Se optar por preservar as configurações, tudo que seria guardado em um backup do sistema (listado pelo "sysupgrade -l") será restaurado. Se você instalou algum pacote e guardou a lista do que foi instalado (lembra que eu sugeri há alguns parágrafos atrás?), esta é a hora que você reinstala os pacotes desejados. Se for instalar manualmente, procure instalar os pacotes de mais alto nível (ex: "luci-app-minidlna" antes de "minidlna"), pois eles irão, por dependência, baixar os pacotes requeridos. No final do processo, é bom refazer a listagem do que está instalado e comparar com o que você tinha na versão anterior.

Podem ser criados arquivos sufixados com "-opkg" em /etc/. Este são arquivos de configuração originais do pacote e são criados pois você modificou algo na configuração. Sugiro que verifique se não existe alguma coisa introduzida neste pacote que deveria ser adicionada no seu arquivo de configuração. Eu gosto do diff ou do "vim -d" para este trabalho comparando o arquivoconf com arquivoconf-opkg. Ao final do processo, eu gosto de apagar qualquer -opkg para deixar claro que apliquei tudo que queria.

As atualizações de segurança serão disponibilizadas por meio de atualização de pacotes (exceto as que exijam mudar o kernel). Para listar os pacotes atualizáveis:

# opkg update
# opkg list-upgradable

O maior problema é que estas atualizações de segurança, quando de pacotes embutidos oriundas na firmware instalada, ocuparão o espaço duas vezes no roteador pois ao substituir arquivos existentes na firmware inicial, ainda será preservado a versão em somente leitura para recuperação. Se for um problema para seu caso, a alternativa é esperar a próxima versão com a correção ou gerar uma nova firmware com o pacote atualizado.

Por fim, faça um novo backup geral. É sempre bom preservar o seu trabalho.

Se precisar retornar a versão anterior do OpenWRT, realize a gravação da firmware antiga, entre no modo de recuperação e restaure a overlay.

Se você não usa uma unidade externa para expandir o espaço interno, seu trabalho acabou. Para os demais, o processo é um pouco mais complicado... Ao atualizar o sistema, você terá um kernel novo que é incompatível com os módulos de kernel ou mesmo com as bibliotecas existentes na unidade externa, que ainda pertencentes à versão anterior. Você precisaria reinstalá-los. Esta é a sugestão de como proceder:

Em primeiro lugar, gere todos os backups sugeridos anteriormente. É importante preservar seu trabalho anterior. Ainda sem instalar a nova firmware, reinicie o sistema sem a unidade externa. Se você seguiu minha sugestão de manter uma configuração básica na flash interna, você ainda terá um ambiente funcional. Com isto, ele vai usar somente a flash interna (com a configuração que você tinha antes de usar a unidade externa).

Ainda com a unidade externa desconectada, faça o procedimento de atualização descrito neste artigo para quem não usa raiz expandida, inclusive com a etapa de backups. Você terá que preservar os dois conjuntos de backups: com e sem a unidade externa em uso. Ao final do processo, você deverá ter a sua configuração básica restabelecida. Caso tenha optado por não preservar as configurações na gravação, você pode aproveitar o backup gerado quando a unidade externa estava desconectada (o segundo) para restaurar as configurações.

Neste momento, a unidade externa ainda está com os programas da versão anterior, que são geralmente incompatíveis com a nova versão (os módulos de kernel sempre o são). Por isto, precisamos nos livrar de todos os arquivos da versão anterior do OpenWRT presentes na unidade externa. Na unidade externa, na partição usada como overlay, remova todo o conteúdo ou mova tudo para um subdiretório (ou para outra unidade se não estiver com espaço livre) afim de que este não seja usado. Como sugestão, crie um "openwrt-versao-xxx" e mova tudo para lá. Refaça a configuração de uso de uma unidade externa (que no mínimo será reinstalar os pacotes necessários). Reinicie o sistema. Você deve estar agora com mais espaço na raiz.

Neste ponto, você ainda terá as mesmas configurações que tinha quando usou o sistema sem a unidade externa. Envie o primeiro backup da versão anterior feito com a unidade externa conectada (primeiro backup). Na sequência, reinstale os pacotes extras, assim como é feito para ambientes sem a raiz expandida. Complete o trabalho com aquele backup final.

Espero que apreciem a nova versão. De agora em diante, vou apenas focar em configurações específicas para LEDE 17.01.0, que ainda podem funcionar nas versões OpenWRT 15.05, 14.07, 12.09 e 10.03.1.

Se pintar um problema, tem sempre o fórum deste blog. Até a próxima.

segunda-feira, 27 de fevereiro de 2017

LEDE é o novo OpenWRT: lançado primeira versão estável!

O "grande tema" deste blog tem sido o OpenWRT. Entretanto, talvez isto tenha que mudar. Agora, o LEDE (Linux Embedded Development Environment) deve ocupar o seu lugar (rimou?). Evitei comentar o assunto LEDE até este momento pois ainda não estava sacramentado o destino dos projetos. Para quem não acompanhou todos os capítulos da novela, vou tentar resumir.

O OpenWRT já não era mais uma mocinha. Depois de vários anos de projeto, a estrutura continuava a mesma: um pequeno grupo superpoderoso "dono do nome, servidores, acesso de administração, poder de conceder escrita ao repositório, etc" e um grupo de desenvolvedores posteriores que formavam o grupo de desenvolvimento (core developers). Já há algum tempo, quem realmente fazia o OpenWRT eram os desenvolvedores que chegaram depois. Apesar desses novos desenvolvedores estarem no grupo core (terem acesso de escrita concedido pelos principais desenvolvedores), seu poder era limitado. Os desenvolvedores "originais" tinham o poder de veto sobre mudanças, direção do projeto, ferramenta de controle de versão, tudo sem regras claras, apenas baseado na sua convicção. Este autoritarismo pode funcionar bem em alguns projetos, como o Wine ou mesmo o Linux (o kernel), mas se mostrou desastroso para o OpenWRT.

Uma das brigas foi a adoção do git. Sim, existem outros sistemas de controle de versões e o XYZ é melhor... mas o git é uma mãe para desenvolvimento distribuído. Todos queriam, menos os "donos da bola", que mantinham o SVN. O acesso aos servidores também foi um problema sério. Diversos casos de indisponibilidade (inclusive até hoje em dia eles ocorrem) levavam um significativo tempo para serem sanados. Isto é péssimo para um projeto que também não aceitava espelhos parceiros. Boa parte das brigas não eram divulgadas pois ocorriam em uma lista fechada a apenas os desenvolvedores core. Não foi um evento específico mas o clima estava ficando péssimo. Apesar dos desenvolvedores "donos da bola" não fazerem mais uma contribuição quantitativamente significativa para o OpenWRT, eles ainda se apresentavam como a "cara" do projeto. E quem fazia o trabalho duro não gostava muito disso.

Agora entra a beleza do Software Livre! Nome (marca), servidores, domínios DNS tem dono. Código não. Os principais desenvolvedores (fora os "donos da bola") se juntaram e fizeram um "fork" em um outro projeto: LEDE Project. Em suma, é o código do OpenWRT com os desenvolvedores responsáveis, na época, por mais de 90% das contribuições do OpenWRT. A estrutura é muito mais aberta, comunicação bem mais transparente (primam por mídias abertas), o poder é distribuído e infraestrutura simplificada. O código sofreu rapidamente melhorias significativas, que antes eram vetadas. O git foi adotado, as formas de contribuição flexibilizadas (aceitam PR no Github ;-), que aumentou o envolvimento de novos desenvolvedores. Teve diversas mudanças mas o resultado é que deu uma revigorada no projeto.

E o OpenWRT? Se uma das críticas dos "rebeldes" era justamente a dificuldade de conceder acesso para novos desenvolvedores, como um projeto que perde mais de 90% do seu desenvolvimento atual poderia sobreviver? A lista openwrt-devel, antes vivida, parecia a lista da turma da faculdade de 15 anos atrás: rola uma mensagem por semana mas nada de útil. O desenvolvimento mingou ao insignificante, em ritmo de manutenção mínima. Os "donos da bola" ficaram com a bola mas sem time para jogar. Simplesmente não teriam como manter o projeto sozinhos (mas demoraram para entender).

Alguns meses depois da separação difícil, os dois grupos sentaram para conversar. Concordaram que seria benéfico unificar os projetos. O primeiro passo foi conceder acesso aos antigos desenvolvedores do OpenWRT ao código do LEDE (por votação, como ocorre com qualquer outro novo desenvolvedor). Como o LEDE estava muito mais avançado, seria usado como o fonte. Resta ainda hoje decidir alguns pontos como: qual seria o nome? Usar a wiki e fórum de quem? Redirecionar? Sincronizar? Essas coisas. O LEDE não está muito preocupado com isso pois o que o OpenWRT tem a oferecer a mais é o nome. Esse até mesmo perdeu seu sentido quando o OpenWRT passou a rodar em diversos dispositivos não rotadores wireless (Wireless RouTer), ao mesmo tempo que perdeu suporte no Linksys WRT56G. E qualquer mesclagem/alteração de nome é um esforço que poderia ser utilizado melhorando o produto.

De qualquer forma, o LEDE acaba de lançar a sua primeira versão estável: 2017.01.0! Acho que isto sacramenta o fim do projeto OpenWRT. Posso estar errado mas acho que logo a página do OpenWRT será apenas conteúdo histórico com um redirecionamento para o LEDE. Vamos ver...

Agora a parte importante: o que temos de bom? Em primeiro lugar, separaram os pacotes das imagens. Ainda existem pacotes específicos para um tipo de equipamento, em especial o kernel, mas não fazia sentido recompilar o mesmo pacotes quando as instruções de processador eram as mesmas. Então, ao baixar uma firmware nova em Downloads, vá em "targets" e não em "packages" (o resto é igual). Esta mudança não afeta o uso do opkg do ponto de vista do usuário.

Várias versões foram atualizadas, melhorado desempenho, latência, e outras mudanças evolutivas. Ah, e o Telnet que é muito usado no modo de emergência? Morreu: use SSH sempre, mesmo antes de definir a senha de root. Isto significa que teremos também o scp funcionando ;-)

O repositório de pacotes extra (https://github.com/openwrt/packages) continua ativado por padrão e, apesar do nome OpenWRT, o foco agora é LEDE.

Vou atualizar e relançar o post sobre atualização de versão do OpenWRTLEDE. Até este momento, todos os upgrades funcionaram sem problemas de tal forma que um observador desatento nem notaria a mudança. Sim, pode fazer o upgrade a partir do OpenWRT como se fosse uma atualização de versão do próprio OpenWRT.

Ah, um dos problemas com a versão nova são os roteadores mais humildes. O opkg pode ter problemas com roteadores com 32 MBytes de RAM ao instalar pacotes e aqueles com 4MB de armazenamento já vão chegar quase cheios. Então, talvez você não consiga instalar mais coisas no seu TL-WR740N. Eu tive que baixar os pacotes manualmente e desligar o Luci. Estão trabalhando para melhorar isso...

Até a próxima!