208.3 Implementando um Servidor Proxy (Squid)
Introdução
Um servidor proxy é um servidor que atua como intermediário entre os clientes e os servidores de destino. Quando um cliente faz uma solicitação para acessar um site ou serviço, essa solicitação pode passar primeiro pelo proxy. O proxy recebe a requisição, aplica suas regras e, se o acesso for permitido, encaminha a solicitação para o servidor de destino. Depois, quando recebe a resposta, o proxy retorna o conteúdo para o cliente que originou a conexão.
De forma simplificada:
Cliente -> Proxy -> Servidor de destino
Servidor de destino -> Proxy -> Cliente
O proxy é usado para centralizar o acesso à rede e aplicar controles em um único ponto. Em vez de cada cliente acessar a Internet diretamente, o tráfego passa por um servidor responsável por aplicar políticas de acesso, autenticação, registro de logs e, em alguns casos, cache.
Algumas finalidades comuns de um servidor proxy são:
Controle de acesso
O proxy pode permitir ou negar acesso a sites, domínios, URLs ou tipos de conteúdo, dependendo das regras configuradas.
Registro de acesso
O proxy pode registrar quais clientes acessaram determinados sites, em quais horários e com qual resultado. Isso é útil para auditoria e troubleshooting.
Cache de conteúdo
O proxy pode armazenar localmente alguns conteúdos acessados com frequência. Assim, quando outro cliente solicitar o mesmo conteúdo, o proxy pode entregar a resposta usando o cache, reduzindo tráfego externo e melhorando o tempo de resposta.
Autenticação de usuários
O proxy pode exigir autenticação antes de liberar o acesso à Internet. Essa autenticação pode ser local ou integrada a serviços como LDAP, Active Directory e RADIUS.
Filtragem de conteúdo
O proxy pode bloquear categorias de sites, extensões de arquivos, palavras-chave, domínios ou URLs específicas, dependendo dos recursos disponíveis e da configuração aplicada.
Existem diferentes tipos de proxy, como proxy HTTP, proxy SOCKS, proxy reverso e proxy transparente. Cada tipo atende a uma finalidade diferente.
Neste tópico, será usado o Squid. O Squid é um servidor proxy de código aberto muito usado em ambientes Linux e Unix-like. Ele pode ser usado para controle de acesso, autenticação de usuários, cache de conteúdo web e registro de navegação.
O principal arquivo de configuração do Squid costuma ser:
/etc/squid/squid.conf
# Em algumas distribuições mais antigas, o caminho pode aparecer como:
/etc/squid3/squid.conf
O Squid trabalha principalmente com regras chamadas ACLs, que representam listas de controle de acesso. Essas ACLs podem identificar redes de origem, domínios, horários, portas, métodos HTTP e outros critérios. Depois de criar as ACLs, o administrador usa regras de acesso para permitir ou negar o tráfego.
Exemplo simples:
acl rede_local src 192.168.1.0/24
http_access allow rede_local
http_access deny all
Nesse exemplo, a ACL rede_local representa a rede 192.168.1.0/24. A regra http_access allow rede_local permite o acesso dessa rede, enquanto http_access deny all bloqueia o restante.
O Squid também pode ser usado como proxy transparente. Nesse modo, os clientes não precisam configurar manualmente o proxy no navegador, porque o tráfego é redirecionado para o Squid por regras de firewall ou roteamento.
Mesmo assim, proxy transparente não deve ser visto como uma solução que impede qualquer tentativa de bypass. Ele ajuda a centralizar o tráfego e aplicar políticas, mas ainda depende de regras de firewall, roteamento, DNS e controle de saída bem configurados.
Uma observação importante é que o tráfego HTTPS possui limitações. Como o conteúdo da conexão é criptografado pelo TLS, o proxy não consegue ver o conteúdo interno da requisição sem técnicas adicionais, como interceptação TLS. Por isso, em muitos cenários, o controle de HTTPS é feito com base em domínio, IP, porta ou SNI, e não no conteúdo completo da página.
Instalação e Configuração do Squid
Vamos começar instalando o Squid:
sudo apt update
sudo apt install squid -y
O principal arquivo de configuração do Squid fica em:
/etc/squid/squid.conf
Antes de alterar, é recomendado salvar uma cópia do arquivo original:
sudo mv /etc/squid/squid.conf /etc/squid/squid.conf.orig
Agora crie um novo arquivo de configuração:
sudo vim /etc/squid/squid.conf
Adicione o conteúdo abaixo:
# Define a porta onde o Squid vai escutar.
# A porta padrão do Squid é 3128.
http_port 3128
# Define o nome visível do servidor proxy.
visible_hostname proxyserver
# ACL que representa qualquer endereço IP.
# Ela será usada no final para bloquear tudo que não foi permitido antes.
acl todosrc src all
# ACL para o próprio servidor local.
acl localhost src 127.0.0.1/32
acl localhost src ::1
# ACL usada para requisições de gerenciamento do Squid.
# Esse tipo de acesso deve ficar restrito ao localhost.
acl manager proto cache_object
# Portas consideradas seguras para conexões SSL/TLS.
# A porta 443 é usada por HTTPS.
# A porta 563 é usada por NNTPS.
acl SSL_ports port 443 563
# Portas consideradas seguras para acesso via proxy.
# Requisições para portas fora dessa lista serão bloqueadas.
acl Safe_ports port 21 # FTP
acl Safe_ports port 80 # HTTP
acl Safe_ports port 443 # HTTPS
acl Safe_ports port 563 # NNTPS
acl Safe_ports port 70 # Gopher
acl Safe_ports port 210 # WAIS
acl Safe_ports port 280 # HTTP-MGMT
acl Safe_ports port 488 # GSS-HTTP
acl Safe_ports port 591 # FileMaker
acl Safe_ports port 777 # Multiling HTTP
acl Safe_ports port 901 # SWAT
acl Safe_ports port 1025-65535 # Portas altas não privilegiadas
# ACL para o método HTTP PURGE.
# Esse método é usado para remover objetos do cache.
acl purge method PURGE
# ACL para o método CONNECT.
# O método CONNECT é usado principalmente para túneis HTTPS.
acl CONNECT method CONNECT
# Permite acesso de gerenciamento somente a partir do localhost.
http_access allow manager localhost
http_access deny manager
# Permite PURGE somente a partir do localhost.
http_access allow purge localhost
http_access deny purge
# Bloqueia acessos para portas que não fazem parte da ACL Safe_ports.
# O "!" significa negação.
http_access deny !Safe_ports
# Bloqueia CONNECT para portas que não fazem parte da ACL SSL_ports.
# Isso evita o uso do proxy para criar túneis para portas indevidas.
http_access deny CONNECT !SSL_ports
# ACL que representa a rede local autorizada a usar o proxy.
acl redelocal src 192.168.121.0/24
# Permite acesso local.
http_access allow localhost
# Permite acesso da rede local.
http_access allow redelocal
# Bloqueia todo o restante.
# No Squid, a ordem das regras importa.
# Por isso, as permissões devem vir antes do bloqueio final.
http_access deny todosrc
Nessa configuração, somente o próprio servidor e a rede 192.168.121.0/24 poderão usar o proxy. Qualquer outra origem será bloqueada pela regra final:
http_access deny todosrc
A ordem das regras é importante no Squid. O acesso é avaliado de cima para baixo, e a primeira regra compatível define se a requisição será permitida ou bloqueada.
Antes de reiniciar o serviço, valide a configuração:
sudo squid -k parse
Se não houver erro de sintaxe, reinicie o Squid:
sudo systemctl restart squid
# Também é possível recarregar a configuração sem reiniciar completamente o serviço:
sudo squid -k reconfigure
Para verificar o status do serviço:
sudo systemctl status squid
E para confirmar se o Squid está escutando na porta 3128:
sudo ss -lntp | grep 3128
Um teste simples pode ser feito com curl, informando o proxy manualmente:
curl -x http://127.0.0.1:3128 http://example.com
A partir de outro host da rede 192.168.121.0/24, o teste ficaria assim:
curl -x http://IP_DO_PROXY:3128 http://example.com
Cache
O cache é um recurso usado pelo proxy para armazenar localmente alguns conteúdos acessados pelos clientes. Quando um cliente solicita um recurso da web, o Squid verifica se aquele conteúdo já existe no cache e se ainda pode ser reutilizado. Se o conteúdo estiver disponível e válido, o Squid pode entregar a resposta diretamente a partir do cache local, sem buscar novamente no servidor de origem.
Isso pode reduzir o uso de banda externa e melhorar o tempo de resposta para conteúdos acessados com frequência. É importante entender que nem todo conteúdo será armazenado em cache. O Squid respeita cabeçalhos HTTP enviados pelo servidor de origem, como Cache-Control, Expires e outros controles de cache.
Além disso, em conexões HTTPS comuns, o Squid normalmente não consegue enxergar o conteúdo interno da conexão, porque o tráfego está protegido pelo TLS. Nesse caso, sem interceptação TLS, o proxy trabalha principalmente com o túnel CONNECT, mas não com o conteúdo da página em si, ou seja, o cache é mais útil para conteúdos HTTP ou para cenários em que o conteúdo pode ser armazenado de forma explícita e permitida.
Habilitando cache em disco
Edite o arquivo de configuração do Squid:
sudo vim /etc/squid/squid.conf
Adicione a diretiva abaixo:
cache_dir ufs /var/spool/squid 100 16 256
Essa diretiva define um diretório de cache em disco para o Squid. Explicando cada campo:
cache_dir Diretiva usada para configurar cache em disco.
ufs Tipo de armazenamento usado pelo Squid para salvar objetos em disco.
/var/spool/squid Diretório onde os arquivos de cache serão armazenados.
100 Tamanho máximo do cache em disco, em MB.
16 Quantidade de diretórios de primeiro nível.
256 Quantidade de diretórios de segundo nível dentro de cada diretório de primeiro nível.
Nesse exemplo, o Squid poderá usar até 100 MB em disco para cache. Ele também criará uma estrutura com 16 diretórios principais e, dentro de cada um deles, 256 subdiretórios.
Isso ajuda a distribuir os arquivos do cache, evitando que muitos arquivos fiquem concentrados em um único diretório.
Inicializando a estrutura do cache
Antes de reiniciar o Squid, valide a configuração:
sudo squid -k parse
Depois, pare o serviço:
sudo systemctl stop squid
Crie a estrutura de diretórios do cache:
sudo squid -z
Agora reinicie o Squid novamente:
sudo systemctl restart squid
Se a estrutura do cache já existir e apenas alguma configuração tiver sido alterada, pode ser usado:
sudo squid -k reconfigure
O comando squid -k reconfigure relê a configuração, mas não substitui a necessidade de inicializar a estrutura de cache quando um novo cache_dir é criado.
Verificando a estrutura criada
Depois de executar squid -z, o diretório /var/spool/squid deve conter os diretórios de cache:
ls /var/spool/squid
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F swap.state
Nesse caso, foram criados 16 diretórios de primeiro nível, de 00 até 0F. Dentro de cada um deles, existem 256 diretórios de segundo nível:
ls /var/spool/squid/00
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
...
F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
A nomenclatura usa valores em hexadecimal. Por isso aparecem números de 0 a 9 e letras de A a F. Como existem dois dígitos, os valores vão de:
00 até FF
Isso representa 256 combinações possíveis:
16 x 16 = 256
Já o arquivo swap.state é usado pelo Squid para manter informações sobre os objetos armazenados no cache.
Verificando uso do cache
Para acompanhar os acessos, é possível visualizar o log:
sudo tail -f /var/log/squid/access.log
Algumas entradas podem aparecer com informações como:
TCP_MISS
TCP_HIT
O TCP_MISS indica que o Squid não encontrou o conteúdo no cache e precisou buscar no servidor de origem. Já o TCP_HIT indica que o conteúdo foi encontrado no cache e entregue diretamente pelo Squid.
Também é possível verificar o tamanho usado em disco:
sudo du -sh /var/spool/squid
Essa configuração é suficiente para laboratório. Em produção, o tamanho do cache, o tipo de armazenamento, as regras de expiração e o comportamento para conteúdos dinâmicos precisam ser ajustados conforme o perfil de uso da rede.
ACL - Access Control List
Uma ACL (Access Control List), é usada no Squid para definir critérios de controle de acesso. A ACL sozinha não permite nem bloqueia o tráfego. Ela apenas representa uma condição que pode ser testada pelo Squid. Depois, essa ACL precisa ser aplicada em uma regra, como http_access allow ou http_access deny. De forma simples:
- acl: define o critério
- http_access: aplica a ação de permitir ou negar
Um exemplo prático seria:
acl redelocal src 192.168.121.0/24
http_access allow redelocal
Nesse exemplo, a ACL redelocal representa a rede 192.168.121.0/24. A regra http_access allow redelocal permite o uso do proxy para clientes dessa rede. As ACLs podem ser baseadas em vários critérios, como endereço IP de origem, endereço IP de destino, domínio, porta, protocolo, método HTTP, horário de acesso, navegador e expressões regulares.
Alguns tipos comuns de ACL no Squid são:
# ACL para origem da conexão,
# usado para identificar o IP ou rede do cliente:
acl rede_local src 192.168.121.0/24
# ACL para o destino da conexão,
# usado para identificar o IP ou rede de destino:
acl destino dst 192.168.200.0/24
# ACL para domínio de origem,
# usa resolução reversa a partir do IP do cliente:
acl origem_dominio srcdomain .exemplo.com
# ACL para domínio de destino,
# o ponto no começo indica subdomínios:
acl dominios_liberados dstdomain .debian.org .google.com
# Porta de destino:
acl portas_web port 80 443
# Protocolo da requisição:
acl protocolos_web proto HTTP HTTPS FTP
# Navegador usado pelo cliente,
# essa ACL analisa o cabeçalho User-Agent:
acl navegador browser Firefox
# Dias e horários.
# S = Sunday | Domingo
# M = Monday | Segunda
# T = Tuesday | Terça
# W = Wednesday | Quarta
# H = Thursday | Quinta
# F = Friday | Sexta
# A = Saturday | Sábado
#
# De segunda até sexta, das 09h às 18h:
acl horario_comercial time MTWHF 09:00-18:00
# Expressão regular na URL completa, procura o padrão em toda a URL:
acl bloqueia_uol url_regex -i uol
# Expressão regular no caminho da URL,
# em http://site.com.br/esporte, analisa principalmente a parte "/esporte".
acl bloqueia_path urlpath_regex -i esporte
O -i é usado para ignorar diferença entre letras maiúsculas e minúsculas, no exemplo abaixo (mesmo usado acima):
acl bloqueia_uol url_regex -i uol
Com o -i, o Squid pode casar com uol, UOL, Uol e outras variações.
Aplicando ACLs com http_access
Depois de criar uma ACL, é preciso aplicar uma ação usando http_access. Exemplo permitindo o próprio servidor local:
# ACL para localhost.
acl localhost src 127.0.0.1/32
acl localhost src ::1
# Permite o localhost.
http_access allow localhost
Exemplo permitindo a rede local:
# ACL que representa a rede local.
acl redelocal src 192.168.121.0/24
# Permite a rede local.
http_access allow redelocal
Exemplo bloqueando todo o restante:
# ACL que representa qualquer origem.
acl todosrc src all
# Bloqueia tudo que não foi permitido antes.
http_access deny todosrc
A ordem das regras é muito importante. O Squid avalia as regras de cima para baixo. Por isso, as regras mais específicas normalmente ficam antes, e o bloqueio geral fica no final.
acl redelocal src 192.168.121.0/24
acl todosrc src all
http_access allow redelocal
http_access deny todosrc
Nesse caso, a rede 192.168.121.0/24 é permitida primeiro. Depois, qualquer outra origem é bloqueada. Se a ordem fosse invertida, o bloqueio geral seria aplicado antes e a rede local nunca chegaria a ser permitida.
Safe_ports e SSL_ports
É comum usar ACLs para controlar quais portas podem ser acessadas pelo proxy.
# Portas permitidas para uso geral:
acl Safe_ports port 80 443 21 1025-65535
# Portas permitidas para túneis CONNECT:
acl SSL_ports port 443
# Método HTTP CONNECT:
acl CONNECT method CONNECT
# Bloqueia acesso para portas fora da lista Safe_ports:
http_access deny !Safe_ports
# Bloqueia CONNECT para portas fora da lista SSL_ports:
http_access deny CONNECT !SSL_ports
O
!representa negação.
O CONNECT é um método HTTP usado para criar um túnel TCP através do proxy. Ele é muito usado em acessos HTTPS. Quando um cliente acessa um site HTTPS usando proxy, o navegador normalmente envia uma requisição CONNECT para pedir que o proxy abra uma conexão até o servidor de destino na porta 443.
Depois que o túnel é criado, a negociação TLS acontece entre o cliente e o servidor de destino. Nesse cenário, sem interceptação TLS, o Squid não enxerga o conteúdo interno da conexão HTTPS. Ele apenas encaminha o tráfego criptografado pelo túnel.
Veja mais detalhes do CONNECT
A regra abaixo bloqueia o uso do método CONNECT para portas que não fazem parte da ACL SSL_ports:
http_access deny CONNECT !SSL_ports
Isso é importante porque o CONNECT cria um túnel TCP. Se ele fosse liberado para qualquer porta, o proxy poderia ser usado para acessar serviços que não deveriam passar por ele, como SMTP, SSH ou outros serviços TCP. Por isso, em uma configuração básica, é comum permitir CONNECT apenas para portas usadas por HTTPS, como 443.
Essa regra não significa que o Squid está verificando o conteúdo criptografado. Ela apenas controla para quais portas o método CONNECT pode abrir túneis.
Controle de Acesso
Agora vamos ver alguns exemplos de controle de acesso no Squid usando ACLs. Comece editando o arquivo de configuração:
$ sudo vim /etc/squid/squid.conf
Crie as ACLs no começo do arquivo, antes das regras http_access:
# Rede autorizada a usar o proxy:
acl allow_hosts src 192.168.1.0/24
# Domínios permitidos:
acl allow_domain dstdomain .debian.org .ubuntu.com
# Domínios bloqueados:
acl deny_domain dstdomain .centos.org .kernel.org
# Palavras bloqueadas na URL.
# O "-i" faz a busca ignorar maiúsculas e minúsculas:
acl deny_words url_regex -i futebol esporte novela
# Também é possível carregar as palavras de um arquivo:
#acl deny_words url_regex -i "/etc/squid/blacklist_words"
Depois, aplique as ACLs usando http_access:
# Bloqueia palavras proibidas para qualquer cliente:
http_access deny deny_words
# Bloqueia a rede allow_hosts ao acessar os domínios negados:
http_access deny allow_hosts deny_domain
# Permite a rede allow_hosts acessar os domínios permitidos:
http_access allow allow_hosts allow_domain
# Bloqueia o restante:
http_access deny all
Reinicie o serviço do Squid:
$ sudo systemctl restart squid
Os bloqueios usando url_regex funcionam melhor em requisições HTTP, porque a URL fica visível para o proxy.
Em conexões HTTPS comuns, o navegador usa o método CONNECT para criar um túnel criptografado até o servidor de destino. Sem a interceptação do TLS, o Squid não consegue enxergar o caminho completo da URL, como /noticias/esporte.
Por isso, em HTTPS, o controle normalmente é feito por domínio, IP, porta ou SNI, e não pelo conteúdo completo da URL.
Autenticação
Vamos configurar o Squid para exigir autenticação dos usuários, com isso, somente clientes autenticados poderão usar o proxy. A autenticação pode ser usada de duas formas principais:
- liberar o acesso para qualquer usuário autenticado;
- criar regras específicas por usuário, grupo ou origem.
O Squid suporta diferentes esquemas de autenticação, como:
basic
Autenticação básica. O navegador solicita usuário e senha e envia essas credenciais ao proxy. É simples de configurar, mas não deve ser considerada forte sozinha, porque as credenciais podem ser facilmente decodificadas se o tráfego até o proxy for capturado.
digest
Usa um mecanismo de desafio e resposta. A senha não é enviada diretamente como no Basic, mas esse método é menos comum em ambientes atuais.
negotiate
Usado principalmente com Kerberos. É comum em ambientes integrados a domínio, como Active Directory, onde o usuário pode autenticar usando credenciais do próprio domínio.
ntlm
Usado em integrações com ambientes Microsoft mais antigos. Ainda pode aparecer em redes legadas, mas normalmente Kerberos é preferível quando disponível.
Além desses esquemas, o Squid também pode usar helpers externos para validar usuários em outros serviços, como LDAP, Active Directory, RADIUS ou bancos de dados próprios. Neste exemplo, será usada autenticação Basic com arquivo local no formato htpasswd.
O comando htpasswd faz parte do pacote apache2-utils em Debian/Ubuntu, vamos instalar esse pacote:
sudo apt install apache2-utils -y
Configurando autenticação Basic no Squid
Edite o arquivo de configuração:
sudo vim /etc/squid/squid.conf
Adicione a configuração abaixo no começo do arquivo, antes das regras http_access:
# Define o texto exibido na janela de autenticação do navegador:
auth_param basic realm Proxy Squid
# Define o helper usado para validar usuário e senha.
# Neste exemplo, será usado um arquivo local no formato htpasswd:
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/password
# Define uma ACL que representa qualquer usuário autenticado:
acl autenticado proxy_auth REQUIRED
A linha abaixo define o programa responsável por validar as credenciais:
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/password
Nesse caso, o Squid usa o helper basic_ncsa_auth, que valida o usuário e a senha usando o arquivo:
/etc/squid/password
Já esta linha cria uma ACL para autenticação:
acl autenticado proxy_auth REQUIRED
O REQUIRED significa que qualquer usuário válido no mecanismo de autenticação será aceito.
Aplicando a autenticação
Depois de criar a ACL, é preciso aplicar a regra com http_access. Exemplo para permitir apenas usuários autenticados:
http_access allow autenticado
http_access deny all
Se o objetivo for permitir somente usuários autenticados da rede local, pode ser usado assim:
acl redelocal src 192.168.1.0/24
acl autenticado proxy_auth REQUIRED
http_access allow redelocal autenticado
http_access deny all
Criando o arquivo de senhas
Agora crie o arquivo de senhas:
sudo htpasswd -c /etc/squid/password fulano
New password:
Re-type new password:
Adding password for user fulano
O -c é usado para criar o arquivo. Para adicionar novos usuários depois, não use -c, porque ele recria o arquivo e pode apagar os usuários existentes. Exemplo adicionando outro usuário:
sudo htpasswd /etc/squid/password ciclano
Ajuste a permissão do arquivo para que o Squid consiga ler:
sudo chown proxy:proxy /etc/squid/password
sudo chmod 640 /etc/squid/password
Em Debian/Ubuntu, o usuário do serviço costuma ser proxy. Em outras distribuições, pode ser squid.
Antes de aplicar, valide a configuração:
sudo squid -k parse
Se não houver erro, recarregue a configuração:
sudo squid -k reconfigure
# Ou reinicie o serviço:
sudo systemctl restart squid
Testando a autenticação
Um teste simples pode ser feito com curl:
curl -x http://IP_DO_PROXY:3128 http://example.com
Sem usuário e senha, o acesso deve ser negado ou deve retornar solicitação de autenticação.
Com usuário e senha:
curl -x http://fulano:SENHA@IP_DO_PROXY:3128 http://example.com
Também é possível testar pelo navegador, configurando o proxy manualmente nas opções de rede.
Autenticação por proxy normalmente exige que o navegador saiba que está usando um proxy. Por isso, autenticação com proxy_auth não funciona corretamente em modo transparente/interceptação. Nesse modo, o navegador acredita que está falando diretamente com o site de destino e não envia as credenciais de autenticação esperadas pelo proxy.
Se a ideia for usar autenticação por usuário, o mais comum é configurar o proxy manualmente no navegador, usar WPAD/PAC ou aplicar configuração centralizada, como GPO em ambientes Windows.
Fontes importantes
No Ubuntu a localização do arquivo é
/usr/lib/squid/basic_ldap_auth.