Saudações.
Vou apresentar a vocês algumas experiências com o Squid Proxy em ambiente de containers.
Pré-requisitos:
- VM/VPS/Host com Docker (standalone ou Swarm);
- Internet no servidor (sua VPS ou host);
1 – Conceito de Proxy e o software Squid
O Squid (https://www.squid-cache.org/) é um software escrito em C++ cujo objetivo é ser um framework supremo de Proxy.
Foi criado em 1996 e possui décadas de maturidade.
Ele consegue atuar de todas as formas possíveis dentro do escopo dos protocolos HTTP, HTTPs, FTP, ICP e alguns outros.
Principais recursos:
- Proxy direto: Atende clientes HTTP fornecendo Internet indiretamente;
- Proxy reverso: Recebe conexões em direção a um site e entrega ao servidor interno correto;
- Conexão de entrada HTTPs, conexão interna HTTP;
- Cache ajuda a aliviar a carga no fornecimento de arquivos e assets;
- Proxy transparente: Captura tráfego de rede e se passa pelo site acessado;
- Cache: Armazena arquivos e recursos em RAM e/ou disco para acelerar a Internet e economizar banda;
- Esse era sua principal função antes da migração em massa para HTTPs;
- Num mundo HTTPs o cache perdeu seu lugar e descontinou o Squid nos provedores;
- Autenticação: Permite discriminar usuários por login e senha e controlar quais recursos o usuário pode acessar e com quais caractarísticas técnicas (IP de origem, QoS, horário, etc);
- ACL: Permite discriminar IPs, domínios, usuários, cabeçalhos para decidir permitir, negar, redirecionar ou modificar os detalhes do acesso;
No Docker standalone (servidor solitário) ou no cluster Docker Swarm o Squid encontra a oportunidade de nos ajudar no ingress (conexões que vem da Internet em direção aos nossos serviços) atuando como Proxy Reverso ou no egress, fornecendo acesso controlado e auditado do que nossos containers estão indo buscar na Internet.
2 – Estudo do caso
Observe meu caso:
- Cluster de servidores Docker Swarm com workers distribuídos em vários datacenters;
- Containers que precisam acessar a Internet (bots, pesquisas, scrapping, tools de agentes);
- Cada container navegava com um IP diferente pelo NAT do Linux de cada servidor;
- Containers workers rodam:
- Web Scrapping: Transformam os sites acessados em documentos JSON e MarkDown;
- Web Search: Meus agentes de IA precisam navegar (Agent Tools) em vários sites para realizar pesquisas;
- API: Acesso a API de provedores de IA, APIs corporativas, scrapping remoto (firecrawl), etc;

Problemas que enfrentei:
- Problema 1 – leve: Sites modernos implementam limite de requisições por IP (RPM – Request per Minute) e limite de banda por IP (Traffic Shapping);
- Problema 2 – moderado: Sites protegidos por WAF (Web Application Firewall), o WAF aprende o padrão de repetição “like a bot” e bloqueiam o IP de origem;
- Problema 3 – grave: Alguns containers rodam em países diferentes, o bloqueio por GEOIP impede o funcionamento nesses servidores;
- Problema 4 – gravíssimo: Para cada IP bloqueado os containers que ainda conseguem navegar passam a fazer muitas requisições e os problemas anteriores se amplificam.
A solução parece óbvia: Precisamos contratar um proxy externo PAGO para balancear essa carga de saída entre milhares de IPs diferentes para que os bloqueios e limites sejam contornados.

Como muitas das minhas ferramentas precisam apenas de controle de uso mais do que volume, optei por usar o Squid como gateway dos meus containers, e no Squid eu implemento toda a lógica do negócio, usando IPs próprios balanceados ou entregando para provedores de Proxy quando necessário.
Fase 1 – No diagrama abaixo o problema parece se agravar, os containers que antes navegavam com os IPs de seus servidores agora navegam com o IP do Squid.

Fase 2 – O servidor Squid agora pode ser configurado com a lógica do nosso negócio, indo diretamente na Internet para os serviços menos burocráticos e delegando para provedores Proxy o acesso sensível a IPs de origem, observe:

Fase 3 – Quando a rede escala e você precisa balancear seus softwares para navegarem na Internet fazendo centenas a milhares de requisições por segundo:

3 – Clientes HTTP e Variáveis de Ambiente
Para que você não tenha que configurar cada software e cada navegador para usar o proxy, a industria facilitou com o uso de alguns variáveis de ambiente que se presentes, desviam o tráfego para o proxy.
3.1 – Variáveis de Ambiente
As principais variáveis são:
http_proxy: Endereço do servidor proxy para requisições do schema “http://“;https_proxy: Endereço do servidor proxy para requisições do schema “https://“;ftp_proxy: Endereço do servidor proxy para requisições do schema “ftp://“;socks_proxy: Endereço do servidor proxy para conexões SOCKS4/SOCKS5;no_proxy: Registro de excessões separadas por virgula, as excessões não usam proxy e vão direto para o site de destino;all_proxy: Funciona como fallback genérico. Se não houver uma variável específica para o schema do protocolo (HTTP, HTTPS, FTP, etc.), o cliente usa esse endereço;
Você quer cobrir a maioria dos cenários, configurar http_proxy, https_proxy, no_proxy e all_proxy.
3.2 – Declarações com case-sensitive
Infelizmente diferentes softwares e bibliotecas HTTP fazem a leitura nas versões upper-case (maiúsculas) dessas variáveis, assim, recomendo declarar nas duas formas, mesmo a lower-case (minúscula) seja a oficial.
| Variável padrão | Variável uper-case | Finalidade |
|---|---|---|
http_proxy | HTTP_PROXY | Proxy para http:// |
https_proxy | HTTPS_PROXY | Proxy para https:// |
ftp_proxy | FTP_PROXY | Proxy para ftp:// |
socks_proxy | SOCKS_PROXY | Proxy para socks |
no_proxy | NO_PROXY | Declaração de destinos sem proxy |
all_proxy | ALL_PROXY | Proxy fallback para todos os protocolos |
3.3 – Bibliotecas de cliente HTTP
Você precisará estudar o manual da biblioteca HTTP que seus programas utilizam para afinar a configuração de proxy. As principais bibliotecas são:
- Python: requests (a mais popular), urllib3 (baixo nível, avançada), httpx (moderna, HTTP/2), aiohttp (async nativa), pycurl (performance máxima, multi-protocolo), httplib2 (mais antiga, cache, HTTP/2), urllib (stdlib, nativa da linguagem);
- JavaScript: fetch API (nativa), axios (mais popular), node-fetch (versões antigas do Node), got (rica em funcionalidades), ky (wrapper leve), undici (alta performance), superagent (encadeável, tem plugins), needle (leve, suporta streaming);
- Go: net/http (stdlib, geral), resty (wrapper da net/http), heimdall (avançada), gentleman (baseado em plugins), grequests (inspirada na requests do Python), go-retryablehttp (HashiCorp, net/http com retries automáticos e backoff).
3.4 – Declarando e usando variáveis de proxy
Exemplos de como declarar variáveis de ambiente e seus efeitos.
Usando endereço de proxy universal para todos os protocolos:
# Usando all_proxy:
export all_proxy="http://proxy.empresa.com:3128"
unset ftp_proxy;
unset http_proxy;
unset https_proxy;
# Todas as requisicoes abaixo vao via HTTP até o proxy (sem criptografia)
curl http://api.ipify.org; echo; # Usa o proxy (http => proxy => http)
curl https://api.ipify.org; echo; # Usa o proxy (http => proxy => https)
curl ftp://api.ipify.org; echo; # Usa o proxy (http => proxy => ftp)
Proxy apenas para HTTP ou apenas para HTTPs:
# Apenas HTTP
# - Declarar proxy HTTP
export http_proxy="http://proxy0.empresa.com:3128";
# - Sem proxy HTTPs
export https_proxy=""; # declarar vazio, ou
unset https_proxy; # remover variavel de ambiente
# Requisicao HTTP => Proxy HTTP
curl http://api.ipify.org; echo; # Usar proxy na porta 3128 do proxy0
# Requisicao HTTPs => direto na Internet
curl https://api.ipify.org; echo; # Nao passa pelo proxy
# Apenas HTTPs
# - Sem proxy HTTP
export http_proxy=""; # declarar vazio, ou
unset http_proxy; # remover variavel de ambiente
# - Declarar proxy HTTPs
export https_proxy="https://proxy0.empresa.com:8443";
# Requisicao HTTP => direto na Internet
curl http://api.ipify.org; echo; # Nao passa pelo proxy
# Requisicao HTTPs => Proxy HTTPs
curl https://api.ipify.org; echo; # Usar proxy na porta 8443 do proxy0
CURL com proxy HTTP e HTTPs em endereços diferentes:
# Declarar enderecos dos servidores proxy:
# - Proxy HTTP
export http_proxy="http://proxy1.empresa.com:3128"
# - Proxy HTTPs
export https_proxy="http://proxy2.empresa.com:3129"
# Acessar sites:
curl http://api.ipify.org; echo; # Usa proxy na porta 3128 do proxy1
curl https://api.ipify.org; echo; # Usa proxy na porta 3129 do proxy2
# Ignora o uso de proxy:
curl --no-proxy http://api.ipify.org; echo; # Acesso direto na Internet
curl --no-proxy https://api.ipify.org; echo; # Acesso direto na Internet
CURL com proxy geral de fallback:
# Declarar enderecos dos servidores proxy:
# - Proxy HTTP, HTTPs, Sockets, FTP, ...
export all_proxy="http://proxy3.empresa.com:3128"
# Acessar sites:
curl http://api.ipify.org; echo; # Usa proxy na porta 3128 do proxy3
curl https://api.ipify.org; echo; # Usa proxy na porta 3128 do proxy3
CURL com proxy geral de fallback e HTTPs (mais específico vence):
# Declarar proxy de HTTPs:
export https_proxy="http://proxy4.empresa.com:8443";
# Declarar proxy geral:
export all_proxy="http://proxy5.empresa.com:3128";
# Acessar sites:
curl http://api.ipify.org; echo; # Usa proxy na porta 3128 do proxy5
curl https://api.ipify.org; echo; # Usa proxy na porta 8443 do proxy4
CURL especificando proxy na linha de comando (sem variável de ambiente):
# Proxy explicito, canal HTTP acessando site HTTP:
curl -m 5 -x http://proxy6.empresa.com:1080 http://api.ipify.org; echo;
# Proxy explicito, canal HTTP (insecuro) acessando site HTTPs:
curl -m 5 -x http://proxy7.empresa.com:3128 https://api.ipify.org; echo;
4 – Canais entre cliente e proxy
Existem 3 canais (protocolos) para comunicação com um proxy:
- HTTP (RFC 2616): Transporta o protocolo em puro texto sobre TCP (padrão) ou UDP;
- HTTPs (RFC 2818): Transporta o protocolo HTTP dentro de uma conexão TCP protegida por TLS (padrão) ou SSL;
- Envolve o uso de certificados x509;
- Certificados auto-assinados não possuem reconhecimento dos clientes;
- Certificados assinados tem preço, os gratuitos possuem validade curta (3 meses);
- ICP (RFC 2186): Utiliza o Internet Cache Protocol como canal de comunicação, normalmente somente entre servidores proxy (essa adjacência se chama cache peer).
O cliente pode se comunicar com o Proxy usando as seguintes combinações de protocolos cliente=>proxy=>site:
4.1 – Proxy com HTTPs fim-a-fim
Essa é a configuração perfeita.
O cliente se conecta via HTTPs no Proxy. Nessa etapa há a validação do certificado do Proxy.
Se a conexão TLS com o Proxy for bem sucedida o cliente solicita método CONNECT e é conduzido de forma transparente (TCP opaco) até IP e porta do site.
- 1 – Cliente faz conexão TLS (TCP#1 + TLS) até o proxy;
- Cliente analisa certificado x509 do proxy;
- 2 – Cliente envia ao proxy: CONNECT exemplo.com:443 HTTP/1.1;
- 3 – Proxy irá se conectar ao site solicitado:
- Resolver o DNS, pode obter IPv4 e/ou IPv6;
- Conexão TCP simples até o IP e porta do site;
- 4 – Proxy retorna o status da operação CONNECT ao cliente:
- Proxy => Cliente: HTTP/1.1 200 Connection established;
- Qualquer erro nesse ponto impede a continuação, erros comuns:
- Erro de proxy sem rede;
- Site bloqueou o IP do proxy;
- Site fora do ar;
- Quando o proxy respondeu OK (status 200 na operação CONNECT) a conexão passou para o modo transparente (tunnel/relay), tudo que o cliente enviar a partir desse ponto vai direto para o site final;
- 5 – Cliente inicia uma conexão TLS dentro da conexão TCP+TLS já estabelecida com o proxy;
- Cliente analisa o certificado x509 do site;
- Cliente envia requisição (GET, POST, HEAD, …) para o site;
Apenas o IP é alterado (o site enxerga o IP do Proxy apenas).

Não é possível fazer CACHE de objetos (arquivos) no proxy devido a criptografia ficar intacta fim-a-fim.
4.2 – Proxy HTTP para acessos HTTPs
Cliente se conecta via HTTP com o Proxy, não há criptografia nesse canal inicial.
- 1 – Cliente faz conexão TCP sem criptografia até o proxy;
- 2 – Cliente envia ao proxy: CONNECT exemplo.com:443 HTTP/1.1;
- 3 – Proxy irá se conectar ao site solicitado:
- Resolver o DNS, pode obter IPv4 e/ou IPv6;
- Conexão TCP simples até o IP e porta do site;
- 4 – Proxy retorna o status da operação CONNECT ao cliente (status 200);
- 5 – Cliente inicia uma conexão TLS dentro da conexão TCP já estabelecida com o proxy;
- Cliente analisa o certificado x509 do site;
- Cliente envia requisição (GET, POST, HEAD, …) para o site;

Observe que a segurança é garantida pela negociação fim-a-fim do cliente até o site, mas comprometida na origem:
- O cliente não pode validar se o Proxy é real ou um ataque de homem no meio;
- Captura de tráfego torna visivel quais sites o cliente está acessando.
A vantagem desse método é:
- Não precisa fazer setup de certificado no Proxy;
- O proxy pode ser um container ou servidor implementado rapidamente.
Ambiente de containers usando Squid como gateway HTTP de saída:

4.3 – Proxy HTTP para acessos HTTP
Esse caso é o mais antigo de todos, não existe criptografia em nenhum dos canais. Atualmente esse modo é restrito a ambientes intranet e de soluções muito específicas.
A morte desse modo na Internet aconteceu pela implementação do HTTPs como padrão de navegação.
É o único que permite o CACHE de objetos (arquivos) no proxy para economizar banda e acelerar a entrega.
O cliente trata o proxy como o próprio site com algumas pequenas diferenças. Exemplos de cabeçalhos envolvidos na transação com o proxy HTTP-HTTP:
- O método inclui a URL inteira:
- Com proxy (Proxy-* não é repassado ao site):
- GET http://example.com/pagina.html HTTP/1.1
- Host: example.com
- Proxy-Authorization: Basic cHJ…w== (login no proxy)
- Proxy-Authorization: keep-alive
- Sem proxy:
- GET /pagina.html HTTP/1.1
- Host: example.com
- Com proxy (Proxy-* não é repassado ao site):
- Cabeçalhos inseridos pelo cliente que instruem o proxy:
- Proxy-Connection: keep-alive
- Cabeçalhos inseridos pelo proxy na requisição para o site:
- Via: 1.1 squid-host (squid/7.5)
- X-Forwarded-For: 192.168.1.10
- Cabeçalhos inseridos pelo proxy na resposta ao cliente:
- X-Cache: MISS (ou HIT)
- X-Cache-Lookup: HIT from squid-host:3128
Casos de uso:
- Controle de acesso em intranet de APIs protegidas;
- Roteamento de URLs em ambientes de micro-serviços.
4.4 – Proxy HTTPs para acessos HTTP
Essa combinação é comum em ambientes de proxy reverso, onde o cliente pode ser qualquer cliente na Internet ou Intranet e o destino é um serviço interno (container) que possui apenas HTTP como meio de comunicação.
O Traefik, Caddy e Squid são exemplos de implementações comuns.
O certificado x509 deve ser obtido via compra (1 ano de validade, renovavel) ou via provedor ACME como o LetsEncrypt.
O Squid não possui uma integração nativa com LetsEncrypt, esse recurso pode ser obtido por scripts externos (certbot) que obtem e renovam o certificado e mandam um “reconfigure” para o Squid ler novamente os arquivos.
Para obter o mesmo efeito do Traefik seria necessário criar um software agente que monitore via events os labels dos containers e construa a configuração do Squid para o caso. Requer acesso ao socket Unix do Docker.

5 – Certificados auto-assinados
Agora que ficou claro o uso de HTTPs e os canais onde ele aparece, preciso esclarecer o que acontece em ambientes seguros.
O ideal é que todos os seus serviços se comuniquem por HTTPs, deixando tudo muito seguro por criptografia.
O problema é que isso adiciona a camada TLS, que envolve:
- Gestão da Unidade Certificadora (CA);
- Geração de chaves privadas nos micro-serviços;
- Geração de certificados;
- Overhead de criptografia:
- Latência levemente maior no inicio de toda conexão;
- Consumo de CPU no processo de criptografia dos dados;
Você tem dois caminhos:
- 1 – Gerar certificados assinados corretamente e reconhecidos globalmente, cada micro-serviço possuindo o seu certificado – dispendioso e caro;
- 2 – Gerar uma CA local para assinar seus próprios certificados, problemas:
- Os clientes HTTP (CURL, navegadores) não vão reconhecer sua CA como globalmente confiável e se negarão a abrir as URLs;
- Você precisará instalar seu certificado de CA em todos os micro-serviços gerados em sua infra;
Bom… e tem o atalho! Ordenar que os clientes HTTP ignorem o certificado auto-assinado e confiem neles.
Novamente você terá que ler o manual das bibliotecas envolvidas.
No CURL:
# Usar proxy com certificado auto-assinado e site reconhecido globalmente:
# - Ignora a validacao do certificado auto-assinado (proxy10.empresa.com:8443)
# - Não ignora a validacao do site final (https://api.ipify.org)
curl \
--proxy-insecure \
-x http://proxy10.empresa.com:8443 \
\
https://api.ipify.org; echo;
# Usar proxy com certificado reconhecido globalmente com site auto-assinado:
# - Não ignora validacao do certificado do proxy (proxy11.empresa.com:8443)
# - Ignora a validacao do site final (https://api.ipify.org)
curl \
-x http://proxy11.empresa.com:8443 \
\
--insecure \
\
https://api.ipify.org; echo;
# Usar proxy com certificado auto-assinado e site com certificado auto-assinado:
# - Ignora a validacao do certificado auto-assinado (proxy12.empresa.com:8443)
# - Ignora a validacao do site final (https://api.ipify.org)
curl \
--proxy-insecure \
-x http://proxy12.empresa.com:8443 \
\
--insecure \
\
https://api.ipify.org; echo;
6 – Cache Peer
O recurso mais incrível do Squid é a flexibilidade de conectar proxies entre si. Esse recurso se chama “cache-peer” e pode ser implementado usando protocolo HTTP/HTTPs ou ICP.
O resultado é uma rede hierárquica ou mesh entre muitos servidores de proxy que, combinados com a flexibilidade de replicação e distribuição das plataformas de containers criam uma solução pronta pra todo tipo de engenharia.
O balanceamento por DNS, IPVS e round-robin entrega uma nuvem ultra-resiliente de acesso a serviços HTTP.

7 – Logs e observabilidade
O Squid conta com vários canais para logs, por padrão utiliza-se log em arquivos mas você pode alterar para TCP, UDP, Syslog e STDOUT (saída padrão).
Canais de logs:
- Arquivo: Grava diretamente em arquivos (volume);
- Daemon: Envia os logs para um processo vizinho, esse processo pode gravar em arquivos (padrão) ou transmitir no formato desejado;
- Syslog local: Enviar para syslog local (/dev/log);
- Syslog remoto: Enviar via TCP ou UDP para um servidor de logs remoto;
Usando Syslog via TCP (mais seguro):

Recursos da geração de logs:
- Formato: Permite formatar e personalizar a linha de log;
- Filtro: Permite filtrar por ACL quais logs são enviados para determinados canais;
Para observabilidade e métricas, precisamos de um exportador paraleo.
O serviço “squid-exporter” (https://github.com/boynux/squid-exporter) pode ser integrado para fazer a transmissão da telemetria em tempo real ou cronometrada.

8 – Squid no Docker
Para usar o Squid o processo é muito simples, você pode construir um container do zero. Você poderá incluir sua configuração personalizada e embutir sua regra de negócios nele.
Nesse capítulo vou demonstrar uma POC (prof of concept) de como rodar. Esse projetinho não é exatamente completo e perfeito mas serve para a didática da técnica.
Crie uma pasta para esse projeto, vou chamar de “squid-basic“. Na pasta coloque o arquivo Dockerfile:
# Container do Squid com base Alpine
FROM alpine:3.23.3
# Variaveis globais
ENV TZ=America/Sao_Paulo
ENV PS1='\u@\h:\w\$ '
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US.UTF-8
# Atualizar base
RUN apk update && apk upgrade
# Instalar pacotes
RUN apk add squid curl openssl
# Envs de proxy, ontainer usando o proprio squid como proxy
ENV http_proxy=http://localhost:1080/
# https requer projetar uso de certificados
#ENV https_proxy=https://localhost:443/
# Portas internas do Squid
EXPOSE 443/tcp
EXPOSE 1080/tcp
EXPOSE 8080/udp
EXPOSE 8443/tcp
# Processo do container
CMD [ "/usr/sbin/squid", \
"-n", \
"proxy", \
"-f", \
"/etc/squid/squid.conf", \
"--foreground" \
]
Dentro da pasta do projeto, construa a imagem “squid-basic” com tag padrão “latest“:
# Criar imagem squid-basic
docker build . \
--pull \
--no-cache \
-f Dockerfile \
-t squid-basic:latest;
A imagem está pronta para uso, mas infelizmente, usando a configuração padrão do squid em /etc/squid/squid.conf (caminho dentro do container).
Vamos criar um arquivo squid.conf na pasta do projeto para mapear como volume de arquivo dentro do container:
# Portas HTTP
http_port 1080
http_port 3128
http_port 8080
# Portas HTTPs, precisa projetar a forma de gerar e usar certificados
#https_port 8443 cert=/certs/fullchain.pem key=/certs/privkey.pem
#https_port 443 cert=/certs/fullchain.pem key=/certs/privkey.pem
# Lista de prefixos para controle de acesso
# - Localhost
acl LOCALHOSTv4 src 127.0.0.1/32
acl LOCALHOSTv6 src ::1/128
acl LOCALHOST src 127.0.0.1/32
acl LOCALHOST src ::1/128
# - Redes locais conhecidas
acl LOCALNETSv4 src 10.117.0.0/16
acl LOCALNETSv6 src 2001:db8:10:117::/64
acl LOCALNETSv6 src fe80::/64
# - Redes privadas (todas)
# - IPv4:
acl PRIVATESv4 src 10.0.0.0/8
acl PRIVATESv4 src 169.254.0.0/16
acl PRIVATESv4 src 172.16.0.0/12
acl PRIVATESv4 src 192.0.0.0/24
acl PRIVATESv4 src 192.0.2.0/24
acl PRIVATESv4 src 192.88.99.0/24
acl PRIVATESv4 src 192.168.0.0/16
acl PRIVATESv4 src 198.18.0.0/15
acl PRIVATESv4 src 198.51.100.0/24
acl PRIVATESv4 src 203.0.113.0/24
acl PRIVATESv4 src 224.0.0.0/4
acl PRIVATESv4 src 240.0.0.0/4
# - IPv6:
acl PRIVATESv6 src ::/3
acl PRIVATESv6 src 2001:db8::/32
acl PRIVATESv6 src 4000::/2
acl PRIVATESv6 src 8000::/1
# - Redes publicas confiaveis (seus servidores, VPs, VM)
# - IPv4
acl ALLOWED_NETWORKSv4 src 172.233.34.15
acl ALLOWED_NETWORKSv4 src 45.255.128.0/22
# - IPv4
acl ALLOWED_NETWORKSv6 src 2600:3c0d::f04d:a4ef:fc13:7cb8/128
acl ALLOWED_NETWORKSv6 src 2804:cafe::/32
# Controle de acesso
# - Sempre permitir localhost
http_access allow LOCALHOSTv4
http_access allow LOCALHOSTv6
# - Sempre permitir redes locais (docker networks)
http_access allow LOCALNETSv4
http_access allow LOCALNETSv6
# - Sempre permitir redes privadas
http_access allow PRIVATESv4
http_access allow PRIVATESv6
# - Sempre permitir IPs publicos conhecidos
http_access allow ALLOWED_NETWORKSv4
http_access allow ALLOWED_NETWORKSv6
# - NEGAR TODO O RESTO
http_access deny all
# Opcoes gerais
pid_filename /run/squid.pid
icon_directory /run
err_page_stylesheet none
# Ajustes de parametros
forward_max_tries 25
connect_timeout 2 minutes
read_timeout 15 minutes
request_timeout 5 minutes
shutdown_lifetime 30 seconds
# Arquivos de logs
access_log daemon:/data/logs/squid-access.log squid !LOCALHOST
cache_log /dev/null
cache_store_log none
logfile_rotate 10
# Cache
cache_replacement_policy heap GDSF
cache_mem 0 MB
maximum_object_size_in_memory 8 MB
minimum_object_size 0 KB
maximum_object_size 4 MB
# Modo oculto, nao encaminhar cabecalhos que revelam a existencia do proxy
# - Desativar cabecalhos nativos
via off
forwarded_for delete
follow_x_forwarded_for deny all
httpd_suppress_version_string on
visible_hostname localhost
strip_query_terms off
uri_whitespace strip
# - Retirar cabecalhos do Squid
reply_header_access X-Cache deny all
reply_header_access X-Cache-Lookup deny all
reply_header_access X-Squid-Error deny all
request_header_access X-xproxy-role deny all
request_header_access X-Forwarded-For deny all
request_header_access Forwarded deny all
request_header_access Proxy-Connection deny all
request_header_access Proxy-Authorization deny all
Agora vamos rodar o container. Na pasta do projeto onde está o squid.conf, execute:
# Rede de containers squid (ipv4 only)
docker network create proxynet \
-d bridge \
-o com.docker.network.bridge.name=br-proxynet \
-o com.docker.network.driver.mtu=1500 \
-o com.docker.network.bridge.gateway_mode_ipv4=nat-unprotected;
# Pasta do volume
# - Pasta principal
mkdir -p /storage/squid-basic;
# - Pasta para logs
mkdir -p /storage/squid-basic/logs;
chmod 777 /storage/squid-basic/logs;
# Renovar/rodar container squid-basic:
# Remover atual
docker rm -f squid-basic 2>/dev/null;
# Criar e rodar
docker run -d \
--restart=always \
--name=squid-basic \
--hostname squid-basic.intranet.br \
\
--user=root --cap-add=ALL --privileged \
\
--cpus=1 \
--memory 512m --memory-swap 512m --shm-size 512m \
\
--tmpfs /run:rw,size=8m \
-v /storage/squid-basic:/data \
-v ./squid.conf:/etc/squid/squid.conf \
\
--network proxynet \
\
-p 1080:1080 \
-p 3128:3128 \
\
squid-basic;
Container rodando, vamos entrar no shell do container:
# Entrar no shell ash do container:
docker exec -it squid-basic ash;
Testando proxy:
# Testar com proxy HTTP via variavel http_proxy
curl -v http://api.ipify.org; echo;
# * Uses proxy env variable http_proxy == 'http://localhost:1080/'
# * Host localhost:1080 was resolved.
# * IPv6: ::1
# * IPv4: 127.0.0.1
# * Trying [::1]:1080...
# * Established connection to localhost (::1 port 1080) from ::1 port 36930
# * using HTTP/1.x
# > GET http://api.ipify.org/ HTTP/1.1
# > Host: api.ipify.org
# > User-Agent: curl/8.17.0
# > Accept: */*
# > Proxy-Connection: Keep-Alive
# >
# * Request completely sent off
# < HTTP/1.1 200 OK
# < Date: Sun, 12 Apr 2026 15:15:07 GMT
# < Content-Type: text/plain
# < Content-Length: 14
# < Server: cloudflare
# < Vary: Origin
# < cf-cache-status: DYNAMIC
# < CF-RAY: 9eb32f424ab1c6ce-GRU
# < Cache-Status: localhost;detail=mismatch
# < Connection: keep-alive
# <
# * Connection #0 to host localhost:1080 left intact
# 45.255.128.158
Observe a primeira linha “http_proxy == ‘http://localhost:1080/’“.
Temos um proxy muito básico e funcional que infelizmente não atende HTTPs.
9 – Projeto Squid Gateway
Criei um projeto chamado “squid-gateway” capaz de prover um Squid pronto para produção e replicação e com suporte HTTPs com certificados do Traefik.
Recursos do container:
- Controle de portas internas:
HTTP_PORT: Padrão 8080;HTTPS_PORT: Padrão 8443;- As portas 1080 e 443 sempre serão abertas localmente no container;
- ACL automática para permitir redes locais (rede do container), redes privadas gerais e alguns IPs públicos da sua escolha;
ACL_ENABLE: Padrão “yes”, sem ACL libera tudo (“no”), se ativo:ACL_PERMIT_PRIVATES: Padrão “yes”,ACL_PERMIT_LOCAL: Padrão “yes”, permite redes locais do container;ACL_PERMIT_NETWORKS: Especifique os prefixos confiáveis;
- Controle de logs para ativar ou desativar;
LOG_ENABLE: Padrão “yes”;LOG_FILE_ACCESS: Caminho do access-log no container;LOG_FILE_CACHE: Caminho do cache.log no container;LOG_FILE_STORE: Caminho do store.log no container;- Se não especificar o caminho o log não é gerado (padrão “none”);
- Upstream facilitado para encadeamento de servidores proxy:
UPSTREAM_ENABLE: Ativar proxy do proxy para encaminhamento de tudo, padrão “no”;UPSTREAM_ADDRESS: Endereço IP ou nome de DNS do proxy superior;UPSTREAM_PORT: Porta do proxy superior;UPSTREAM_AUTH: Usuário para autenticação, opcional;UPSTREAM_PASS: Senha para autenticação;
- Personalização do caminho do certificado para a porta HTTPs do proxy:
CERTDIR: Pasta dentro do container para os certificados auto-assinados;TLS_KEY_PATH: Caminho do certificado específico (arquivo fullchain) desejado;TLS_KEY_PATH: Caminho da chave privada específica;
9.1 – Rede Docker
É necessário criar a rede Docker para definir como seu proxy irá lidar com o protocolo IP.
Rede somente IPv4 – Proxy não fará acessos em IPv6
# Rede de containers Squid - Somente IPv4
docker network create squidnet -d bridge \
-o com.docker.network.bridge.name=br-squidnet \
-o com.docker.network.driver.mtu=1500 \
-o com.docker.network.bridge.gateway_mode_ipv4=nat-unprotected;
Rede dual-stack – IPv4 e IPv6, o proxy escolherá por conveniência do DNS e rapidez
# Rede de containers Squid - Dual-stack IPv4 e IPv6
docker network create squidnet -d bridge --ipv6 \
-o com.docker.network.bridge.name=br-squidnet \
-o com.docker.network.driver.mtu=1500 \
-o com.docker.network.bridge.gateway_mode_ipv4=nat-unprotected;
9.2 – Certificado
O container gera certificado auto-assinado para a porta HTTPs e permite que você informe o caminho de um certificado obtido pelo Traefik (usar traefik-certs) ou por compra (Wildcard ou específico).
Se o arquivo do certificado for alterado o serviço detecta automaticamente e recarrega os novos arquivos.
9.3 – Proxy simples para containers
O propósito desse container é servir de proxy HTTP para auditar o acesso de containers e conduzi-los para outros serviços.
# variaveis
IMAGE="tmsoftbrasil/squid-gateway:latest";
NAME="squid-proxy";
# Controle de acesso do proxy
ACL_ENABLE=yes;
ACL_PERMIT_PRIVATES=yes;
ACL_PERMIT_LOCAL=yes;
ACL_PERMIT_NETWORKS="45.255.128.0/22,2804:cafe::/32";
# Opcoes gerais
# - Portas internas
HTTP_PORT="1080";
HTTPS_PORT="1443";
# - Logs
LOG_ENABLE=yes;
LOG_FILE_ACCESS="/data/logs/squid-access.log";
LOG_FILE_CACHE="none";
LOG_FILE_STORE="none";
# Volume
# - pasta de dados privados persistentes da VPS
DATADIR=/storage/$NAME;
mkdir -p $DATADIR;
# Rodar container
echo "# Iniciando container...";
docker rm -f $NAME 2>/dev/null;
docker run \
-d --restart=always \
--name=$NAME --hostname $NAME.intranet.br \
--user=root --cap-add=ALL --privileged \
--read-only \
--tmpfs /run:rw,size=8m \
\
--network squidnet \
\
-p 8001:$HTTP_PORT \
-p 8002:$HTTPS_PORT \
\
-v $DATADIR:/data \
\
-e ACL_ENABLE="$ACL_ENABLE" \
-e ACL_PERMIT_PRIVATES="$ACL_PERMIT_PRIVATES" \
-e ACL_PERMIT_LOCAL="$ACL_PERMIT_LOCAL" \
-e ACL_PERMIT_NETWORKS="$ACL_PERMIT_NETWORKS" \
\
-e HTTP_PORT="$HTTP_PORT" \
-e HTTPS_PORT="$HTTPS_PORT" \
-e CERTDIR="$CERTDIR" \
\
-e LOG_ENABLE="$LOG_ENABLE" \
-e LOG_FILE_ACCESS="$LOG_FILE_ACCESS" \
-e LOG_FILE_CACHE="$LOG_FILE_CACHE" \
-e LOG_FILE_STORE="$LOG_FILE_STORE" \
\
\
$IMAGE;
Observe que as portas publicadas externamente são 8001 (HTTP) e 8002 (HTTPs com certificado auto-assinado).
Internamente e na rede LAN do container a porta 1080 (HTTP) e 443 (HTTPs) sempre abertas via EXPOSE.
Testando no mesmo container do proxy:
# Rodar CURL dentro do container do squid-proxy:
docker exec -it squid-proxy curl -v 'http://api.ipify.org'; echo;
9.4 – Usando proxy em containers vizinhos
Crie qualquer container declarando as variáveis de ambiente para clientes HTTP e aponte para o container de proxy.
Rodando container temporário para teste na rede “squidnet“:
# Rodar container temporario vizinho ao container de proxy
docker run --rm --read-only --network squidnet \
\
-e http_proxy=http://squid-proxy:1080 \
-e https_proxy=http://squid-proxy:1080 \
\
alpine/curl \
\
curl -v 'http://api.ipify.org'; echo;
Observar o acesso no Log do container “squid-proxy“:
# Observar log do squid:
# - Mostrar tudo
cat /storage/squid-proxy/logs/squid-access.log;
# - Acompanhar em tempo real
tail -f /storage/squid-proxy/logs/squid-access.log;
.
“Todos os meus movimentos
foram friamente calculados.“
Chapolim Colorado
Terminamos por hoje!
Patrick Brandão, patrickbrandao@gmail.com
