Finalmente, chegamos na parte mais interessante: “O controle de acesso“.

As permissões de acesso ao cache são configuradas com a definição de ACLs (lista de controle de acesso). As ACLs são identificadores específicos para o tipo de “conteúdo” que desejamos filtrar, podendo ser: “endereços de origem/destino, métodos de conexão, tipo mime, domínios, URLs, usuários e etc“.

O formato de uma ACL é definido da seguinte maneira:

   acl  nome  tipo  argumentos

ou

   acl  nome  tipo  "/caminho_absoluto/arquivo"

Os tipos mais utilizados costumam ser: “src (IP de origem: 10.0.0.1),  proxy_auth (usuário: user1@dominio.local), dstdomain (domínio de destino: .dominio.com), dstdom_regex (domínio de destino: \.dominio[0-9]\.com\.br), url_regex (URL: facebook\.com\/[0-9]+\/photos\/), port (portas: 80, 8080 ou 8081) e method (método HTTP: GET ou POST), por exemplo“.

As ACLs all, manager, localhost e to_localhost são prédefinidas (nem sempre foram)“.

Alguns exemplos:

1. Identificando determinados domínios do Youtube:

acl dstyoutube dstdomain .youtube.com .googlevideo.com .video.google.com

2. Definindo uma blacklist por domínio:

acl blacklist dstdomain "/etc/squid/acl/domain_blacklist"

– Conteúdo de /etc/squid/acl/domain_blacklist:

#Games
.friv.com
.friv2online.com
.yoob.com
.spilgames.com
.wowwiki.com
.warnet.com.br
.innogames.com
.dkpsystem.com
.bosskiller.com
.animesxgames.com
.crafterstome.com
.mmo-champion.com
.tribalwars.com.br
.thesettlersonline.com.br
.goodgamestudios.com
.netfreedomgames.com
.guerrakhan.com
.supremacy1914.com
.jogatina.com
.callofwar.com
.frivjogosonline.com.br
.leagueoflegends.com
.rachacuca.com.br
.frivjogosonline.com.br
.coolrom.com

O nome da primeira ACL foi definido como dstyoutube e o segundo como blacklist. Em ambos os casos, identificando domínios de destino (tipo dstdomain). Conforme exposto inicialmente, são “apenas identificadores”.

Diferentes ações podem ser tomadas a partir dos filtros anteriores.

O veredito é feito com opções como: “http_access (requisições HTTP) ou http_reply_access (respostas HTTP), delay_access (recurso delay_pool para controle de banda), icp_access (controle de acesso entre caches vizinhos) ou no_cache (controle de objetos armazenados em cache)”.

Poderíamos, por exemplo, criar um controle de banda para dstyoutube e bloquear todos os domínios identificados pela ACL blacklist.

acl no_delay src 10.0.1.0/24
acl dstyoutube dstdomain .youtube.com .googlevideo.com .video.google.com
acl blacklist dstdomain "/etc/squid/acl/domain_blacklist"

# Limitando a banda total de domínios do Youtube em aproximadamente 5Mb/s (5000k * 1000 / 8)
# - Exceto para a rede 10.0.1.0/24 (ACL no_delay)
delay_pools 1
delay_class 1 1
delay_parameters 1 626000/626000
delay_access 1 allow dstyoutube !no_delay
delay_access 1 deny all

# Bloqueando os domínios listados no arquivo domain_blacklist
http_access deny blacklist

Caso existam dúvidas quanto a configuração da opção delay_pools, recomendo a leitura do blog do João Eriberto:
https://eriberto.pro.br/wiki/index.php?title=Implementa%C3%A7%C3%A3o_de_delay_pool_com_Squid

Conforme demonstrado, cada opção de controle (delay_access ou http_access) permite especificar mais de uma ACL na mesma regra, estabelecendo um operador lógico AND. Logo, no exemplo acima, o limite de 5Mb/s NÃO se aplicará a rede 10.0.1.0/24 – percebam que houve uma inversão com !no_delay (utilizando o sinal !).

As permissões de acesso costumam ser feitas através da opção http_access, definindo allow para liberações e deny para bloqueios. Mas, tome cuidado com a sequência de http_access ou http_reply_access, pois, como o processamento é top-down (de cima para baixo), o veredito será final na primeira correspondência (sem analisar as regras seguintes).

Se fizéssemos uma liberação (http_access allow) para no_delay antes do controle de blacklist, nenhum bloqueio seguinte se aplicaria a rede 10.0.1.0/24. Ou seja, percebam que a estrutura de configuração depende do critério de acesso desejado.

# Bloqueando os domínios listados no arquivo domain_blacklist
http_access allow no_delay
http_access deny blacklist

Vale lembrar que o processamento de um operador lógico “AND” se faz através de duas ou mais ACLs na mesma opção de controle. Como o processamento é sequencial, o “OR” é o operador lógico padrão. Caso a primeira condição não seja satisfeita, a regra seguinte é verificada“.

A utilização de expressões regulares (ACLs terminadas com _regex) oferece uma flexibilidade ainda maior. E, para demonstrar o potencial existente, finalizarei o artigo demonstrando, por meio de expressões regulares, como bloquear o facebook globalmente, autorizando apenas as fanpages linuxfirewall e aprendizfinanceiro (risos).

Como a maior parte destas requisições é encriptada, a configuração do SSL_Bump será obrigatória“.

 

Colocando a mão na massa (TO GET THE HANDS DIRTY)… 😉

Para ativar o suporte ao SSL_Bump é necessário que o Squid tenha sido compilado com as opções “–enable-ssl“, “–enable-ssl-crtd” e “–with-openssl=’/usr/include/openssl/’“.

O Squid trabalha com processos separados, gerenciados pelo binário ssl_crtd, para recriar os certificados originais dos sites remotos. Sendo assim, para viabilizar esta demanda (criação e armazenamento dinâmico dos certificados), devemos satisfazer alguns pré-requisitos.

# Geração do certificado auto-assinado do servidor proxy
# - Informações serão solicitadas para incorporar ao certificado (comando openssl req)
sudo apt-get install ssl-cert
sudo mkdir -p /etc/squid/ssl_cert/
sudo chown -R proxy.proxy /etc/squid/ssl_cert
sudo chmod 700 /etc/squid/ssl_cert

cd /etc/squid/ssl_cert
openssl req -new -newkey rsa:2048 -sha256 -days 3650 -nodes -x509 -extensions v3_ca -keyout myCA.pem  -out myCA.pem
openssl x509 -in myCA.pem -outform DER -out myCA.der


# Estrutura para o gerenciamento dinâmico de certificados de sites remotos
sudo ln -sf /usr/lib/squid/ssl_crtd /bin/ssl_crtd
sudo /bin/ssl_crtd -c -s /var/spool/squid_ssldb
sudo chown -R proxy.proxy /var/spool/squid_ssldb

No primeiro comando openssl (openssl req -new …), criamos um certificado auto-assinado (válido por 10 anos) para que a criptografia aconteça entre o servidor proxy e os clientes, permitindo ao Squid identificar o conteúdo de conexões HTTPS (é um man-in-the-middle). O segundo, foi utilizado para gerar outro certifcado, em codificação DER, que será importado na seção “Autoridades” dos navegadores dos usuários – sem esta etapa, inúmeros sites (como facebook e google) retornarão erro de certificado.

Em caso de dúvidas, leiam o howto oficial do Squid:
http://wiki.squid-cache.org/ConfigExamples/Intercept/SslBumpExplicit

Para tornar o exemplo ainda mais claro, criaremos uma sequência de controles mandatórios (whitelists e blacklists), antes de submeter aos demais filtros. Demonstraremos um controle de acesso global e mandatório, antecedendo o controle de acesso para redes sociais.

Para isto, na ACL alnetworks, o administrador deverá cadastrar quais redes terão acesso ao cache. Do contrário, nenhuma requisição será aceita. Em serverlist é possível cadastrar uma lista de servidores confiáveis (destino) – ou seja, servidores livres de qualquer restrição. As demais ACLs foram utilizadas na definição dos controles mandatórios.

A princípio, apenas os IPs listados no arquivo clientaddr_socialnetwork serão autorizados para acessar as principais redes sociais. Porém, no caso do facebook, todas as estações da rede terão acesso garantido a fanpage linuxfirewall – aliás, será a página de erro padrão (vide deny_info) para chamadas não autorizadas também.

Antes de prosseguir, é importante compreender como as expressões são construídas. Sendo assim, demonstrarei algumas referências básicas:

Expressão Identificação da cadeia de caracteres
^(expr) Início de cadeia – que inicie com “expr”
(expr)$ Fim de cadeia – que termine com “expr”
(expr)* Múltiplas ocorrências (ou nenhuma repetição)
(expr)+ Ao menos uma ou mais ocorrências (repetições)
(expr1|expr2) expr1 OU expr2
[0-9] Variações entre 0 e 9
. Qualquer caractere
\. Exatamente “.” (quando desejamos identificar o “ponto”)

Estou validando a eficiência dos filtros com SSL_Bump, mas o resultado já está dentro do previsto. Para aplicar a configuração, edite o arquivo squid.conf e inclua as seguintes linhas:

...

## Networks
acl serverlist dst "/etc/squid/acl/serverlist"
acl alnetworks src "/etc/squid/acl/networks_allowed"

http_access deny !alnetworks

## SSL site monitor
http_port 8080 ssl-bump generate-host-certificates=on dynamic_cert_mem_cache_size=4MB cert=/etc/squid/ssl_cert/myCA.pem
sslcrtd_program /usr/lib/squid/ssl_crtd -s /var/spool/squid_ssldb -M 4MB
acl step1 at_step SslBump1

acl monitoredSites ssl::server_name .google.com .google.com.br .ssllabs.com .facebook.com .fbcdn.net .cloudfront.net
sslproxy_cert_error allow monitoredSites
ssl_bump peek step1 all
ssl_bump bump monitoredSites
ssl_bump splice all
http_access allow CONNECT step1 monitoredSites


## Global Whitelist
acl domain_whitelist dstdom_regex -i "/etc/squid/acl/domain_whitelist"
acl clientaddr_whitelist src "/etc/squid/acl/clientaddr_whitelist"
acl url_whitelist url_regex "/etc/squid/acl/url_whitelist"

## Global Blacklist
acl domain_blacklist dstdomain -i "/etc/squid/acl/domain_blacklist"
acl clientaddr_blacklist src "/etc/squid/acl/clientaddr_blacklist"
acl url_blacklist url_regex "/etc/squid/acl/url_blacklist"


## Whitelist control (url_blacklist will deny domain_whitelist)
http_access allow clientaddr_whitelist
http_access allow serverlist
http_reply_access allow serverlist
http_access allow localhost !to_localhost
http_access deny  url_blacklist
http_access allow domain_whitelist
http_access allow url_whitelist
http_reply_access allow clientaddr_whitelist
http_reply_access allow domain_whitelist
http_reply_access allow url_whitelist

## Blacklist control
http_access deny to_localhost
http_access deny domain_blacklist


## Socialnetwork access
acl domain_socialnetwork dstdom_regex \.(facebook|fbcdn|twitter|badoo|linkedin|myspace|hi5|tagged|pinterest|twoo|tumblr)\.(net|com)
acl domain_socialnetwork dstdom_regex (plus|plusone)\.google\.(com|com\.br) (messenger|twitter|instagram|facebridge|fbstatic-[a-z].akamaihd|snapchat)\.(net|com)
acl clientaddr_socialnetwork src "/etc/squid/acl/clientaddr_socialnetwork"

deny_info https://www.facebook.com/linuxfirewallbrasil/ clientaddr_socialnetwork
http_access deny domain_socialnetwork !clientaddr_socialnetwork

O “pulo do gato” vem logo a seguir…

Através do controle estabelecido pela ACL url_whitelist, podemos criar expressões regulares que garantam o acesso para parte da API do facebook, sem precisar liberar o domínio por completo. Assegure, apenas, que nenhum bloqueio em url_blacklist possa invalidar a liberação que exemplificaremos abaixo.

Edite o arquivo /etc/squid/acl/url_whitelist e inclua as seguintes linhas:

# Para autorizar a renderização da página (requer SSL_Bump)
facebook\.com\/ajax\/(bz|(mercury|event)\/|photos\/.*\/init\.php|pagelet\/.*\/(PhotoViewerInitPagelet|WebEgoPane)|log_ticker_render\.php)
facebook\.com\/v[0-9]\.[0-9]\/plugins\/like\.php
(external|scontent)-gru[0-9]-[0-9]\.xx\.fbcdn\.net
staticxx\.facebook\.com\/(connect\/.*\.js|common\/.*\.php)
\.fbcdn\.net\/rsrc\.php\/
\.facebook\.com\/(api\/graphqlbatch|ping\?)
(^|\.)facebook.com\/pages_reaction_units\/more\/
(^|\.)facebook\.com\/(logout|login.php\?|bluebar\/modern_settings_menu\/)
(^|\.)facebook\.(com|com\.br)(\/pg\/|\/)linuxfirewallbrasil($|\/)
(^|\.)facebook\.(com|com\.br)(\/pg\/|\/)aprendizfinanceiro($|\/)
(^|\.)cloudfront\.net\/assets\/(js|css|fonts)\/.*\.(js|css|ttf)($|\?)
pro\.iconosquare\.com

# Para autorizar alteração nas fanpages (requer SSL_Bump)
(^|\.)facebook\.com\/react_composer\/(logging|status|scraper)\/
(^|\.)facebook\.com\/job_opening\/composer
(^|\.)facebook\.com\/ufi\/(add|edit|delete|typing|reaction)\/
(^|\.)facebook\.com\/ajax\/(create|edit|sharer|notifications|edits\/(save|browser\/post))\/
(^|\.)facebook\.com\/ajax\/(photos\/.*(\.php|(edit|save)\/|\/move)|updatestatus\.php|timeline\/take_action_on_story.php)(\?|\/)
(^|\.)facebook\.com\/ajax\/(feed\/edit_post\.php|typeahead\/search|ticker_entstory\.php)(\?|\/)
(^|\.)facebook\.com\/ajax\/pages\/(recommendations|notifications|review|insights|edit_page)\/
(^|\.)facebook\.com\/events\/(dialog\/(create|edit|share)|ajax|create|edit)\/
(^|\.)facebook\.com\/page_edit\/dialog\/
(^|\.)facebook\.com\/pages\/(call_to_action|callout|feed|presence|insights|profile\/.*_(save|upload))\/
(^|\.)facebook\.com\/phot(o|os)\/(tagging\/|publish|.*\/save)
(^|\.)facebook\.com\/profile\/(picture\/(composer_data|crop_(viewer|profile_pic))\/|timeline)
(^|\.)facebook\.com\/album\/uploader
(^|\.)facebook\.com\/[0-9]+\/photos\/\?tab=album\&
(^|\.)facebook\.com\/(media|share)\/

Qualquer estação da rede poderá interagir com as duas fanpages autorizadas, sem liberar o domínio por completo e nem a timeline pessoal. Para liberar o acesso completo a uma estação específica, basta editar o arquivo clientaddr_socialnetwork e cadastrar o respectivo endereço.

Acredito que o básico (um pouco mais) e fundamental foi apresentado. Criar esta estrutura pela primeira vez pode ser um pouco trabalhoso. Mas, feito isto, o processo passa a ser praticamente operacional.

Futuramente, para trabalhar com filtragem heurística e sistema de classificação por categorias, pretendo compartilhar outro artigo com dicas para integração com serviços de filtragem avançada de conteúdo, como QLProxy ou C-ICAP.

Infelizmente, é inviável cobrir todas as possibilidades em um único artigo. O objetivo foi demonstrar o básico de configuração do servidor Squid, separando em quatro partes.

Espero que tenham gostado, e que as dicas sejam úteis ou possam ajudar de alguma forma.