Squid + Bridge + TProxy no Ubuntu 10.04 amd64 25/08/2010 02:30

Depois de inúmeras tentativas, buscando por documentações na Internet usando o Google, consegui através de pedaços de documentações e testes realizados em minha casa e em um dos provedores para o qual presto serviço realizar o que essa documentação se propõe. Mostrar como podemos configurar um Ubuntu 10.04 como bridge e ao mesmo tempo servir de Proxy totalmente transparente através do TProxy. Com esse recurso a colocação do Proxy não afeta a configuração da sua topologia de rede e ao mesmo tempo permite que os acessos dos seus usuários sejam identificados do lado da Internet porque não é mais o IP do Proxy que faz a consulta e sim o IP do usuário. Também acaba com problemas como RapidShare que não permitem downloads vindos do mesmo IP sendo contas Free, pois cada cliente sairá com o seu próprio IP. Obs.: Se depois do Proxy houver algum sistema fazendo NAT N:1 vulgo Masquerade, de nada adiantará o TProxy. Este documento visa ajudar mas não serei responsável por quaisquer danos que possam vir à acontecer.

Para montar nosso servidor precisaremos ter o mínimo exigido para que este funcione. Pré-requisitos abaixo:

- Squid 3.1.x - o mais estável em http://www.squid-cache.org

Como o Ubuntu 10.04 não vem com o squid 3.1.x, seremos obrigados à baixá-lo, compilarmos e instalarmos ele. Uma outra coisa, esse tutorial não ensinará à instalar um Ubuntu 10.04, pois já existem diversas documentações por aí. O que precisaremos é de um sistema preparado para compilar programas. Precisaremos de pelo menos esses pacotes para montarmos nosso Proxy:

# aptitude install build-essential libcap2-dev libltdl-dev ebtables bridge-utils
# cd /usr/src
# apt-get build-dep squid3
# apt-get source linux-image-2.6.32-24-server
# ln -sf linux-2.6.32 linux

Uma boa prática é usar sempre um sistema atualizado com o comando:

# aptitude update; aptitude dist-upgrade

Agora veremos como está nossa rede de testes, nossa topologia antes do Servidor Proxy em Bridge:

rede1 

Nessa rede acima cada cliente sai com seu IP público e se colocássemos um Proxy Transparente mesmo que em Bridge, teríamos o problema do IP que sairia para navegação, que seria o do Proxy. Meu objetivo aqui é mostrar como configurar um Proxy 100% transparente e em bridge usando o TProxy no kernel, iptables, ebtables e Squid. Agora vejamos como ficará nossa nova topologia. Reparem que o gateway continua sendo o mesmo 186.193.x.1, porque o Proxy, para a rede, não existirá:

rede2

Então agora vamos por a mão na massa e fazer isso funcionar de vez. Rsrsrs

Primeiramente vamos configurar nossa bridge e para isso só precisaremos alterar o arquivo /etc/network/interfaces e deixá-lo como abaixo:

auto lo
iface lo inet loopback

auto br0
iface br0 inet static
        address 186.193.x.3
        netmask 255.255.255.224
        network 186.193.x.0
        broadcast 186.193.x.31
        gateway 186.193.x.1
        bridge_ports eth0 eth1
        post-up route add -net 186.194.x.0/24 gw 186.193.x.2

Fazemos um reboot no nosso proxy e continuaremos abaixo...

Vamos baixar nosso pré-requisito principal e descompactá-lo:

# cd /usr/src
# wget -c http://www.squid-cache.org/Versions/v3/3.1/squid-3.1.7-20100824.tar.bz2
# tar xvfj squid-3.1.7-20100824.tar.bz2

Agora vamos começar à compilar e instalar o squid 3.1.x:

# cd squid-3.1.7-20100824
# ./configure --build=x86_64-linux-gnu --prefix=/usr --includedir=/usr/include --infodir=/usr/share/info --localstatedir=/var --libexecdir=/usr/lib/squid3 --disable-maintainer-mode --disable-dependency-tracking --disable-silent-rules --srcdir=. --datadir=/usr/share/squid3 --sysconfdir=/etc/squid3 --mandir=/usr/share/man --with-cppunit-basedir=/usr --enable-inline --enable-async-io=8 --enable-storeio=ufs,aufs,diskd --enable-removal-policies=lru,heap --enable-delay-pools --enable-cache-digests --enable-underscores --enable-icap-client --enable-follow-x-forwarded-for --enable-auth=basic,digest,ntlm,negotiate --enable-basic-auth-helpers=LDAP,MSNT,NCSA,PAM,SASL,SMB,YP,getpwnam,multi-domain-NTLM --enable-digest-auth-helpers=ldap,password --enable-negotiate-auth-helpers=squid_kerb_auth --enable-external-acl-helpers=ip_user,ldap_group,session,unix_group,wbinfo_group --enable-arp-acl --enable-snmp --with-filedescriptors=65536 --with-large-files --with-default-user=proxy --enable-epoll --enable-linux-netfilter
# make
# make install

Dos parâmetros acima, no ./configure, o mais importante para que funcione é o --enable-linux-netfilter. Não entrarei em detalhes de cada parâmetro acima, pois sairia muito do escopo desse tutorial.

Precisaremos acertar o squid.conf, vou usar o padrão para vocês terem uma idéia mas as optimizações vai de cada um. Vamos editar o /etc/squid.conf e deixá-lo como este abaixo:

cache_effective_user proxy
cache_effective_group proxy
access_log /var/log/squid3/access.log squid
cache_store_log /var/log/squid3/store.log
cache_log /var/log/squid3/cache.log
error_directory /usr/share/squid3/errors/pt-br
acl manager proto cache_object
acl localhost src 127.0.0.1/32
acl localhost src ::1/128
acl to_localhost dst 127.0.0.0/8 0.0.0.0/32
acl to_localhost dst ::1/128
acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
acl localnet src fc00::/7   # RFC 4193 local private network range
acl localnet src fe80::/10  # RFC 4291 link-local (directly plugged) machines

# Abaixo vou colocar as redes de teste como nos meus desenhos do tuto, mas alterem para o teste de vocês
acl localnet src 186.194.x.0/24
acl localnet src 186.193.x.0/27

acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 21          # ftp
acl Safe_ports port 443         # https
acl Safe_ports port 70          # gopher
acl Safe_ports port 210         # wais
acl Safe_ports port 1025-65535  # unregistered ports
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 CONNECT method CONNECT
http_access allow manager localhost
http_access deny manager
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localnet
http_access allow localhost
http_access deny all
http_port 3128
http_port 3129 tproxy
hierarchy_stoplist cgi-bin ?
cache_dir ufs /var/spool/squid3 30000 64 256
coredump_dir /var/spool/squid3
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320

Reparem na configuração acima: a linha em vermelho (http_port 3129 tproxy) porque ela é muito importante!

Agora vamos criar uns diretórios com suas permissões:

# mkdir -p /var/spool/squid3
# chown proxy:proxy /var/spool/squid3
# mkdir -p /var/log/squid3
# chown proxy:proxy /var/log/squid3

Precisaremos inicializar o squid e nesse momento preste atenção para ver se ele mostrará alguma mensagem de erro:

# squid -z

Para colocarmos iniciando no boot adicionamos no /etc/rc.local a linha:

/usr/sbin/squid

Pronto!!! Agora temos tudo que precisamos no sistema. Só precisamos fazer mais uns acertos e uns scripts e pronto teremos nossa bridge funcionando com Squid + TProxy. Vamos adicionar os 2 parâmetros abaixo em /etc/sysctl.conf, no fim dele: 

net.ipv4.ip_forward = 1
net.ipv4.conf.lo.rp_filter = 0

Para finalizar vamos criar 2 scripts no /root/ e colocá-los em /etc/rc.local para serem executados no boot do sistema:

/root/frw1.sh

#!/bin/bash
iptables -F -t mangle
iptables -X -t mangle
iptables -t mangle -N DIVERT
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
 
iptables -t mangle -A DIVERT -j MARK --set-mark 1
iptables -t mangle -A DIVERT -j ACCEPT
 
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 3129

 

/root/frw2.sh

#!/bin/bash
ebtables -t broute -A BROUTING -i eth1 -p ipv4 --ip-proto tcp --ip-dport 80 -j redirect --redirect-target ACCEPT
 
ebtables -t broute -A BROUTING -i eth0 -p ipv4 --ip-proto tcp --ip-sport 80 -j redirect --redirect-target ACCEPT
 
cd /proc/sys/net/bridge/
for i in *
do
  echo 0 > $i
done
unset i

Atenção numa coisa, reparem as 2 interfaces de rede em vermelho acima. A primeira, eth1, é a interface da rede interna que vai para os clientes e a interface eth0 é a que está ligada pro lado da Internet. Se a sua ligação estiver diferente, altere o script.

# chmod +x /root/frw1.sh /root/frw2.sh 

Agora colocamos os scripts para serem executados no boot. Para isso editem o /etc/rc.local e adicionem as linhas abaixo: 

/sbin/modprobe xt_TPROXY
/usr/sbin/squid
ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
/root/frw1.sh
/root/frw2.sh
/sbin/route add -net 186.194.x.0/24 gw 186.193.x.2
exit 0

Uma observação muito importante para que tudo isso funcione: o proxy precisa ter rota dele até o cliente, porque ele fará um spoofing do IP do cliente e quando retornar a resposta ao proxy, este entregará ao cliente. Para isso todo o caminho de retorno do proxy até o cliente precisará estar certo. Um modo de testar seria: fazer um ping do proxy para o cliente... se este estiver online e sem firewall, deverá pingar. 

Façam um último reboot no servidor e pronto, terminado. Agora só testarem.

Abaixo as referências que usei:

http://wiki.squid-cache.org/ConfigExamples/Intercept/CentOsTproxy4?action=show&redirect=ConfigExamples%2FTPROXYPatchingCentOS#TPROXY_v4_with_CentOS_5.3

http://wiki.squid-cache.org/Features/Tproxy4

http://techfree.com.br/wordpress/2009/01/18/tuning-no-squid/

Bem espero ter ajudado :)

Marcelo Gondim <gondim at linuxinfo.com.br>