Usando o Pi-Hole, um filtro de DNS

Algo bem legal de usar o raspberry pi é usar ele como servidor de DNS, para bloquear algumas propagandas. E existe uma solução perfeita para isso chamada pi hole.

Primeiro temos que saber o que é DNS.

DNS é o Domain Name System, um sistema que responde qual o ip de um determinado nome. Basicamente ele traduz nomes em endereços de ip. Antes de existir o DNS, não existiam páginas como google.com, tudo era um endereço de ip, e você tinha que ter uma listinha de ips que te interessavam, até que alguém fez o dns para tirar essa listinha da sua mão e deixar num servidor, porque é mais prático, e mais simples lembrar de google.com do que um endereço de ip.

Pra entender melhor, no terminal no linux, a gente tem o programa chamado host que diz em qual ip um endereço responde, então por exemplo o google.com

augusto@augusto-xps:~$ host google.com google.com has address 216.58.202.174 google.com has IPv6 address 2800:3f0:4001:815::200e google.com mail is handled by 30 alt2.aspmx.l.google.com. google.com mail is handled by 40 alt3.aspmx.l.google.com. google.com mail is handled by 20 alt1.aspmx.l.google.com. google.com mail is handled by 50 alt4.aspmx.l.google.com. google.com mail is handled by 10 aspmx.l.google.com.

Ele na verdade está no ip 216.58.202.174, o programa host fez uma pergunta para o DNS, e esse respondeu. Agora, veja que o google.com.br está em outro endereço.

augusto@augusto-xps:~$ host google.com.br google.com.br has address 216.58.202.3 google.com.br has IPv6 address 2800:3f0:4001:807::2003 google.com.br mail is handled by 40 alt3.aspmx.l.google.com. google.com.br mail is handled by 10 aspmx.l.google.com. google.com.br mail is handled by 20 alt1.aspmx.l.google.com. google.com.br mail is handled by 50 alt4.aspmx.l.google.com. google.com.br mail is handled by 30 alt2.aspmx.l.google.com.

No caso 216.58.202.3, provavelmente porque deve estar mais perto da gente, para evitar ter que percorrer uma grande distância física, mas isso não vem ao caso agora.

Então o DNS é uma lista que fala qual ip está associado a qual nome. Normalmente a gente usa o dns do nosso provedor, ou o do google, mas ter controle sobre o dns pode ser interessante, para bloquear endereços indesejados de propagandas por exemplo, que é o que o pi hole faz.

Para instalar ele no raspberry é bem fácil, começamos fazendo um update e upgrade.

sudo apt-get update
sudo apt-get upgrade

E para instalar

sudo curl -sSL https://install.pi-hole.net | sudo bash

Veja que eu coloco o sudo, porque precisamos ser root, e eu achei mais fácil assim. E pronto, acabou, eu escolhi todas as opções default na instalação e já era. Meu Raspberry é um servidor de DNS bloqueando links indesejados.

Agora quando todo mundo conecta no meu roteador, eu tenho que avisar a todos dispositivo que é para usar o raspberry como DNS, então precisamos agora alterar no roteador isso, que no meu roteador dlink fica logo na tela inicial que se configura a conexão.

Bem simples, agora meu raspberry, que está no endereço de rede interno 192.168.0.3 fixo funciona como DNS server, todo mundo pergunta para ele qual o IP das páginas, claro que não está tudo nele, num grande arquivo, existe uma hierarquia de procura, mas depois vemos isso, o que interessa é que ele da a resposta final, você fala um nome e ele da o ip.

Como tudo não são flores, eu tive um problema que o pi hole começou a bloquear meus javascript, temos que consertar alguns problemas que tive. Lembra que deixo o raspberry em kiosk mode? Então, meu kiosk mode pifou sem javascript, na página, o javascript vinha assim:

x = "Pi-hole: A black hole for Internet advertisements."

Mas com algumas buscas eu vi que ele altera alguns arquivos, nesse caso esse arquivo /etc/lighttpd/lighttpd.conf, então precisamos fazer uma pequena modificação nele.

sudo emacs /etc/lighttpd/lighttpd.conf

O arquivo é grande, mas o problema são essas duas linhas, que basta comentar, e inserir um comentário acima para lembrar que fomos nos que comentamos.

# Impede o uso de javascript # Rewite js requests, must be out of $HTTP block due to bug #2526 # url.rewrite = ( "^(?!/admin/).*\.js$" => "pihole/index.js" )

Feito isso tudo volta a funcionar. Agora para entender o que está sendo feito, como o pi hole está funcionando, veja como uma página como o pirate bay fica sem bloquear o DNS de propaganda.

Agora bloquando, a gente ve o seguinte.

Não abre as propagandas, ou seja, quando o navegador pergunta, ei DNS, qual o ip dessa propaganda para que eu possa baixar as imagens, o DNS fala que não achou e pimba, a gente não baixa a imagem, e fica desse jeito a página. Ai você pode dizer, a, mas eu uso algum bloqueador já, mas de qualquer forma você baixou a imagem e depois bloqueou, dessa forma você nem baixa propaganda, o que pode diminuir até o seu tráfego. Além de que, você pode bloquear páginas maliciosas também de quebra.

O pi hole tem um menu para administração.

Ele traz uma série de informações, e ao fim da instalação, ele te da uma senha gerada automática para acessar esse menu de administração.

Nele podemos ligar e desligar, mexer em várias opções, podemos curiosar inclusive sobre o tráfego, o que está mais sendo bloqueado.

So de olhar os endereços bloqueados, a gente ve o tanto de informação que deve estar mandando para caras como o google, sobre nossa atividade na internet, além das propagandas.

Veja que quem está fazendo mais requisições de DNS, lembrando que 192.168.0.1 é o meu roteador, ou seja meu notebook pergunta o DNS pro roteador, que pergunta pro raspberry, que resolve, e devolve pro roteador que devolve pro notebook, por isso as requisições vem todas do 192.168.0.1.

E podemos resolver nossos próprios endereços também. No arquivo /etc/dnsmasq.d/01-pihole.conf temos algumas configurações interessantes.

pi@rasp_levins:~ $ cat /etc/dnsmasq.d/01-pihole.conf # Pi-hole: A black hole for Internet advertisements # (c) 2015, 2016 by Jacob Salmela # Network-wide ad blocking via your Raspberry Pi # http://pi-hole.net # dnsmasq config for Pi-hole # # Pi-hole is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. ############################################################################### # FILE AUTOMATICALLY POPULATED BY PI-HOLE INSTALL/UPDATE PROCEDURE. # # ANY CHANGES MADE TO THIS FILE AFTER INSTALL WILL BE LOST ON THE NEXT UPDATE # # # # IF YOU WISH TO CHANGE THE UPSTREAM SERVERS, CHANGE THEM IN: # # /etc/pihole/setupVars.conf # # # # ANY OTHER CHANGES SHOULD BE MADE IN A SEPERATE CONFIG FILE # # OR IN /etc/dnsmasq.conf # ############################################################################### addn-hosts=/etc/pihole/gravity.list addn-hosts=/etc/pihole/local.list addn-hosts=/etc/pihole/black.list domain-needed localise-queries bogus-priv no-resolv server=8.8.8.8 server=8.8.4.4 interface=eth0 cache-size=10000 log-queries log-facility=/var/log/pihole.log local-ttl=300 log-async

Veja que no começo, ele chama 3 arquivos, que são listas de nomes com ips para resolver, no caso a lista local.list, da nossa rede interna aqui em casa tem.

pi@rasp_levins:~ $ cat /etc/pihole/local.list 192.168.0.3 rasp_levins 192.168.0.3 pi.hole

Agora quando eu digito http://pi.hole eu sou mandando para o ip 192.168.0.3, ou seja para acessar o pi.hole, eu posso usar http://pi.hole ao invés de http://192.168.0.3. Lembra do comando host la que usamos la em cima, veja so

Agora por exemplo podemos fazer um atalho, ou simplificar para usar o ssh, que também usa o DNS, podemos adicionar rasp_levins.local naquele aquivo com o ip 192.168.0.3, assim:

192.168.0.3 rasp_levins 192.168.0.3 pi.hole 192.168.0.3 rasp_levins.local

E agora basta usar ssh pi@rasp_levins.local ao inves de ssh pi@192.168.0.3.

Bem é isso ai, algo que não mexemos aqui é na interface que o pi hole tem, mas eu vou colocar alguns gráficos no kiosk mode ainda, e se eu escrevi alguma bobeira, algo errado, deixe um comentário corrigindo ou mande um e-mail.

Usando o raspberry para administrar os arquivos de torrents.

Um uso que eu acho muito bom no raspberry é para baixar torrents, primeiro porque você deixa de ter que se preocupar com torrents no seu computador, e como ele fica ligado direto e gasta bem menos energia que um notebook por exemplo, é bem interessante.

O meu raspberry usa o Raspbian como sistema operacional, e para administrar os torrents eu uso o Transmission.

Primeiro temos que instalar o Transmission, que é fácil com o apt.

1
2
3
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install transmission-daemon

Aqui, no meu rasp_levins (que é o nome do meu raspberry aqui) tem um hd externo ligado nele, para ele sempre ser montado já na inicialização, eu alterei o arquivo fstab, que monta os drives na inicialização do linux.

proc /proc proc defaults 0 0 PARTUUID=0ce2607c-01 /boot vfat defaults 0 2 PARTUUID=0ce2607c-02 / ext4 defaults,noatime 0 1 # a swapfile is not a swap partition, no line here # use dphys-swapfile swap[on|off] for that # Montagen do hd_externo UUID=38F25F26F25EE7A0 /media/hd_externo ntfs-3g uid=1000,gid=1000,umask=007 0 0

Então como ele é sempre montado no /media/hd_externo, eu criei duas pastas la. Detalhe que ele é formatado como ntfs, para compatibilidade com windows, se precisar, mas eu uso o pacote ntfs-3g para funcionar o sistema de permissões do linux.

1
2
mkdir -p /media/hd_externo/Torrent_completo
mkdir -p /media/hd_externo/Torrent_emprogresso

Outra coisa a se fazer é permitir que o transmission escreva nesses locais, ele roda como o usuario “debian-transmission”, como o hd_externo é do usuario pi e do grupo pi, com permissão 770

drwxrwx--- 1 pi pi 8192 Aug 20 18:21 hd_externo

A gente adiciona o “debian-transmission para conseguir usar o hd_externo

1
sudo usermod -a -G pi debian-transmission

Feito isso, a gente so precisa configurar o Transmission, alterado o arquivo json que fica todas as configurações dele

1
sudo emacs /etc/transmission-daemon/settings.json

O meu ficou assim:

{ "alt-speed-down": 50, "alt-speed-enabled": false, "alt-speed-time-begin": 540, "alt-speed-time-day": 127, "alt-speed-time-enabled": false, "alt-speed-time-end": 1020, "alt-speed-up": 50, "bind-address-ipv4": "0.0.0.0", "bind-address-ipv6": "::", "blocklist-enabled": true, "blocklist-url": "http://list.iblocklist.com/?list=ydxerpxkpcfqjaybcssw&fileformat=p2p&archiveformat=gz", "cache-size-mb": 4, "dht-enabled": true, "download-dir": "/media/hd_externo/Torrent_completo", "download-limit": 100, "download-limit-enabled": 0, "download-queue-enabled": true, "download-queue-size": 5, "encryption": 1, "idle-seeding-limit": 30, "idle-seeding-limit-enabled": false, "incomplete-dir": "/media/hd_externo/Torrent_completo", "incomplete-dir-enabled": true, "lpd-enabled": false, "max-peers-global": 200, "message-level": 1, "peer-congestion-algorithm": "", "peer-id-ttl-hours": 6, "peer-limit-global": 200, "peer-limit-per-torrent": 50, "peer-port": 51413, "peer-port-random-high": 65535, "peer-port-random-low": 49152, "peer-port-random-on-start": false, "peer-socket-tos": "default", "pex-enabled": true, "port-forwarding-enabled": false, "preallocation": 1, "prefetch-enabled": 1, "queue-stalled-enabled": true, "queue-stalled-minutes": 30, "ratio-limit": 2, "ratio-limit-enabled": false, "rename-partial-files": true, "rpc-authentication-required": true, "rpc-bind-address": "0.0.0.0", "rpc-enabled": true, "rpc-password": "{2d15be92741a1b2cd87ef7af39931c1b088499b0A8PoYK7r", "rpc-port": 9091, "rpc-url": "/transmission/", "rpc-username": "rasp_levins", "rpc-whitelist": "127.0.0.1", "rpc-whitelist-enabled": false, "scrape-paused-torrents-enabled": true, "script-torrent-done-enabled": false, "script-torrent-done-filename": "", "seed-queue-enabled": false, "seed-queue-size": 10, "speed-limit-down": 100, "speed-limit-down-enabled": false, "speed-limit-up": 100, "speed-limit-up-enabled": false, "start-added-torrents": true, "trash-original-torrent-files": false, "umask": 18, "upload-limit": 100, "upload-limit-enabled": 0, "upload-slots-per-torrent": 14, "utp-enabled": true }

Eu alterei o “download-dir”, alterei o “incomplete-dir” e habilitei seu uso com “incomplete-dir-enabled”: true, por padrão ele joga todos os arquivos na mesma pasta, habilitei autenticação em “rpc-enabled”, troquei o “rpc-username” e “rpc-password”, e ao salvar o arquivo e reiniciar o transmission, ele usa um hash na senha, para ninguém ler sua senha nesse arquivo.

Para reiniciar o transmission no terminal eu uso

1
sudo service transmission-daemon reload

E depois disso é so acessar ele pelo ip do seu raspberry na porta 9091, se você não alterou a porta no arquivo acima, aqui em casa eu acesso com o link http://192.168.0.3:9091, ja que eu fixei o ip do rasp_levins.

Espero que ninguém me julgue pelo que estou baixando até o momento desse post heheh, agora outra coisa que eu fiz, é que como já tenho o raspberry rodando um kiosk mode, como visto no tópico passado, eu quis deixar rodando la um pequeno quadradinho para indicar se o torrent está ligado, se tem algo sendo baixado, para saber que estou consumindo banda e algumas estatísticas simples de uso. Isso foi relativamente fácil porque o Transmission tem uma interface php, disponível na página deles, nesse repositório do github, dai podemos usar essa classe para tirar algumas informações e deixar elas aparecendo, no meu caso ficou assim:

Todo o código dessa página do kiosk-mode está no repositório que eu fiz no github, e depois vou explicar melhor o código no README.md do repositório.

Bem é isso ai, estou tomando coragem para voltar a estudar mais seriamente, ainda tenho projeto para terminar de escrever mas o desanimo anda forte, mas vamos levando a vida. Até a Próxima.

Raspberry em modo Kiosk

Opa, não é que fazem 2 meses que eu não posto nada aqui, que vergonha de mim mesmo heheh.

Bem, eu tenho um computador chamado Raspberry pi, basicamente é um computador que é apenas um placa única, ele é bem fraquinho, não vai ser seu notebook, mas da para fazer muitas coisas legais com ele, além de ser muito barato. Eu tenho tentando usar esse tipo de computador, assim como placas de microcontrolador desde a época que escrevi sobre isso aqui e aqui. Bem, você ter essas coisas, arduinos e raspberrys, na maior parte das vezes, é mais fácil que tornar eles em algo útil. Mas vou tentar mostrar como tenho usado o meu, até para eu ter um lembrete de como consertar ele quando eu fizer alguma cagada, porque vira e mexe, eu consigo fazer ele parar de funcionar, mas a experimentação é muito legal.

Bem, uma coisa que eu acho legal, é o que eles chamam de Kiosk Mode, que é deixar uma tela mostrando alguma informação, em muitos lugares a gente vê monitores mostrando propagandas, números de fila, essas coisas, basicamente, o Kiosk Mode é ter um monitor mostrando alguma informação. Como o meu Raspberry fica ligado na tv, eu achei que ao invés de uma tela preta, eu poderia mostrar algo mais legal, deixando ele ligado.

A primeira coisa, é instalar o SO nele, eu uso o Raspbian, mas não instale a versão Lite, pois vamos precisar usar um Brownser, no caso o chromium, que vem com o SO.
As instalação do SO é so seguir o tutorial da página do raspberry, que é um mega projeto legal, mas instalando ele, criando um arquivo ssh sem nada no boot para poder acessar ele remotamente, e colocando ele na rede interna do roteador de casa com um ip fixo, que não cabe aqui explicar, eu faço o seguinte:

Primeiro, após um update, eu instalo o emacs, pois é o melhor editor para o terminal.

1
2
3
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install emacs

Dai o que vamos fazer é ligar o raspberry e depois automaticamente ligar o navegador e modo tela cheia em uma página de interesse nosso.

Bem, um pacote que vamos precisar é o unclutter, que basicamente faz o ponteiro do mouse sumir.

1
sudo apt-get install unclutter

Agora, toda vez que o raspberry é iniciado, ele roda um arquivo chamado autostart, então nesse arquivo, a gente pode colocar comandos para que quando o raspberry seja iniciado, a gente rode esses comandos, iniciar um programa qualquer, mais especificamente, a gente quer iniciar o navegador em modo de tela cheia. Então eu uso o emacs para alterar esse arquivo.

1
emacs ~/.config/lxsession/LXDE-pi/autostart

Detalhe, que o modo gráfico inicia automaticamente, e inicia como o usuário pi, que é padrão da instalação, por isso usamos o autostart do usuário pi, mas cada usuário pode ter um autostart diferente, ou seja, esse autostart não é independente de do usuário ativo. Mas vamos comentar duas linhas dele(o autostart do usuário pi), que é a que liga o protetor de tela, porque ter alguma informação por 5 minutos e depois tela preta não é o intuito aqui, e tirar o comando que move o ponteiro para o iniciar do menu gráfico.

Agora as linhas do xset são para desligar o controle de economia de energia para com o desligamento da tela após um período de inatividade.
A próxima linhas do @sed é para o caso do raspberry reiniciar sem usar o shutdown corretamente, por exemplo em pique de energia, e a próxima linha é para iniciar o navegador, em kiosk mode, que é tela cheia.

Para experimentar, primeiro colocamos a página do google, e iniciamos no modo incognito e desabilitamos aquelas mensagens chatas de traduzir a página.

1
2
3
4
5
6
7
8
9
10
11
12
13
@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
 
##Kiosk	Mode
 
#@xscreensaver -no-splash
#@point-rpi
 
@xset s off
@xset -dpms
@xset s noblank
@sed -i 's/"exited_cleanly": false/"exited_cleanly": true/' ~/.config/chromium-browser Default/Preferences
@chromium-browser --noerrdialogs --kiosk http://google.com --incognito --disable-translate

Bem, agora já estamos começando o raspberry rodando o chromium em tela cheia na página do google, mas não é isso que queremos ainda.

Vamos instalar o lamp, para podermos construir uma página que mostre alguma informação útil.

A primeira coisa que fiz foi extrair algumas informações básicas do raspberry e exibir usando um script de php da seguinte forma.

O meu raspberry principal eu chamo de rasp_levins em homenagem ao Richard Levins, que uma pena ter falecido, o sonho da minha vida foi ter ido fazer algum tipo de trabalho com ele, ainda mais que ele era super gente boa respondendo email de perguntas estupidas minhas, mas tudo bem.

Então três informações úteis são a quanto tempo o rasp_levins ta ligado, quanto foi o último boot, a temperatura do processador e o uso do CPU, essas informações a gente consegue usando comandos do terminal, que basta dar um shell_exec no php e dar um parse na saída.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<h2>rasp_levins Status</h2>
 
 
<p><b>Tempo Ligado:</b><br>
    <?php echo shell_exec('uptime -p');?></p>
 
<p><b>Último boot:</b><br>
    <?php echo shell_exec('uptime -s');?></p>
 
<p><b>Temperatura:</b><br>
    <?php
    $temperatura = intval(shell_exec('cat /sys/class/thermal/thermal_zone0/temp'))/1000.00;
    echo round($temperatura,2);
    ?> graus celsius.
</p>
 
<p><b>CPU:</b><br>
    <?php
    $uso_cpu = sys_getloadavg();
    echo number_format($uso_cpu[0],2);
    ?>%.
</p>

Então esses script exibe o seguinte:

Como e tenho mais de um raspberry na rede, o outro eu tenho o mesmo script dentro dele, mas ai no rasp_levins eu fiz o seguinte script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
 
try {
    $homepage = file_get_contents('http://192.168.0.4/info_padrao.php');
 
 
if ($homepage===false) {
    echo "<h2>rasp_hanski Status</h2>";
    echo "<p><b>Offline</b></p>";
}
 
}catch (Exception $e) {
    /*Lembrete
      Keep in mind that if you use a URL as the filename attribute, and the external
      resource is not reachable, the function will not return FALSE but instead an
      exception will be thrown.
    */
    echo '<p>Exceção capturada: ',  $e->getMessage(), "</p>";
}
echo $homepage;
?>

Ilkka Hanski é meu outro idolo das teoria de metapopulações. Bem aqui eu tento acessar ele para pegar as informações, se não conseguir, eu deixo apenas exibo a informação que ele está offline.

Agora é so colocar essas informações numa página, no caso eu uso o index.php de uma pasta dentro do apache.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!DOCTYPE html>
<html>
 
  <head>
 
    <title>Quarto</title>
    <meta http-equiv="refresh" content="7200">
    <link rel="stylesheet" type="text/css" href="estilo.css">
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script type="text/javascript" src="scripts.js"></script>
 
  </head>
 
  <body>
 
 
    <div class="info_status">
      <div id="levins_info_padrao" class="levins_info_padrao">
	<p>Iniciando!!!</p>    
      </div>
 
      <div id="hanski_info_padrao" class="hanski_info_padrao">
	<p>Iniciando!!!</p>    
      </div>
    </div>
 
 
  </body>
</html>

E veja que nessa página chamamos um script chamado script.js no cabecalho, que basicamente vai escrever em um div a saída daqueles scripts de php com um intervalo de tempo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function update_levins_info_padrao () {
    $('#levins_info_padrao').load('info_padrao.php');
}
 
function update_hanski_info_padrao () {
    $('#hanski_info_padrao').load('hanski_info_padrao.php');
}
 
function update_info_padrao () {
    update_levins_info_padrao();
    update_hanski_info_padrao();
}
 
var tempo_info_padrao  = setInterval(update_info_padrao, 5000);

E agora temos algumas informações legais ao ligar a TV, temos uma página padrão sendo exibida, com algumas informações sobre o raspberry.

E o rasp_levins está do lado da TV, eu deixo um hd externo ligado nele, pois uso ele para guardar arquivos, principalmente para arquivos via P2P usando Torrent e backups o meu roteador.

Bem é isso ai, eu fiz um repositório especifico para esse projetinho do kiosk mode no https://github.com/Squiercg/kiosk_mode, mais porque ainda quero expandir ele, primeiramente medindo a temperatura ambiente do meu quarto usando um arduino e um esp8266, e se eu escrevi alguma bobeira, algo errado, deixe um comentário corrigindo ou mande um e-mail.