terça-feira, 1 de janeiro de 2013

Controlando 2 links de internet (roteados) em um gateway Linux com SQUID

Resumo

Há algum tempo atrás precisei ativar 2 links dedicados e de fornecedores diferentes. Quando meu segundo link foi ativado, começou minha dor de cabeça. Não é simplesmente colocar o ip da nova operadora e ponto. Deve-se fazer muitas configurações para que isso funcione. E através de pesquisas consegui colocar essa solução para funcionar perfeitamente, veja aqui como ficou e espero que lhe ajude!

Introdução


Este artigo tem por finalidade, mostrar como se deve configurar o iproute, iptables e SQUID para que os mesmos funcionem de forma correta com 2 links de internet roteados (dedicados ou não). Para que o mesmo funcione corretamente você deve ter instalados os seguintes pacotes:
iproute2
iptables
squid

Na elaboração deste tutorial foi utilizada a distribuição CentoOS 5.

Quando for necessário executar algum comando, será utilizado o prefixo comando# para

poder identificar o que você precisa digitar.

Configurando as Interfaces


Para esta solução nosso servidor deve ter no mínimo 3 (três) interfaces de rede, as quais serão organizadas da seguinte forma:

eth0
link1 com ip 100.100.100.2 e gateway (roteador) 100.100.100.1

eth1
link2 com ip 200.200.200.2 e gateway (roteador) 200.200.200.1

eth2
rede local com ip 192.168.0.254No CentOS, os arquivos de configuração das interfaces são respectivamente:


eth0 - /etc/sysconfig/network-scripts/ifcfg-eth0
eth1 - /etc/sysconfig/network-scripts/ifcfg-eth1
eth2 - /etc/sysconfig/network-scripts/ifcfg-eth2

Vamos abrir (criar) um por um com o seu editor de textos predileto, eu particularmente prefiro o "vi".

comando# vi /etc/sysconfig/network-scripts/ifcfg-eth0
# Esse será o conteúdo do arquivo ifcfg-eth0
# para a interface ser carregada no BOOT do sistema
ONBOOT=yes
# descrição da interface no sistema
DEVICE=eth0
# rede da interface
NETWORK=100.100.100.0
# máscara da rede
NETMASK=255.255.255.252
# endereço ip da interface
IPADDR=100.100.100.2
# broadcast da rede
BROADCAST=100.100.100.3
# endereço mac da interface
# muito bom, para evitar que em um novo boot
# as interfaces fiquem mudando de posição
# tente colocar o MAC original da placa de rede
HWADDR=00:01:02:03:04:05


comando# :wq
Para gravar e fechar o VI.

comando# vi /etc/sysconfig/network-scripts/ifcfg-eth1
# Esse será o conteúdo do arquivo ifcfg-eth1
# para a interface ser carregada no BOOT do sistema
ONBOOT=yes
# descrição da interface no sistema
DEVICE=eth1
# rede da interface
NETWORK=200.200.200.0
# máscara da rede
NETMASK=255.255.255.252
# endereço ip da interface
IPADDR=200.200.200.2
# broadcast da rede
BROADCAST=200.200.200.3
# endereço mac da interface
# muito bom, para evitar que em um novo boot
# as interfaces fiquem mudando de posição
# tente colocar o MAC original da placa de rede
HWADDR=01:02:03:04:05:06


comando# :wq
Para gravar e fechar o VI.

comando# vi /etc/sysconfig/network-scripts/ifcfg-eth2
# Esse será o conteúdo do arquivo ifcfg-eth2
# para a interface ser carregada no BOOT do sistema
ONBOOT=yes
# descrição da interface no sistema
DEVICE=eth2
# rede da interface
NETWORK=192.168.0.0
# máscara da rede
NETMASK=255.255.255.0
# endereço ip da interface
IPADDR=192.168.0.254
# broadcast da rede
BROADCAST=192.168.0.255
# endereço mac da interface
# muito bom, para evitar que em um novo boot
# as interfaces fiquem mudando de posição# tente colocar o MAC original da placa de rede
HWADDR=02:03:04:05:06:07


comando# :wq
Para gravar e fechar o VI.

Pronto, as interfaces já estão configuradas.

Fazendo alguns ajustes antes do iproute2

Para evitar conflitos de configuração, como vamos passar a utilizar o iproute2 para controlar as rotas, devemos fazer as seguintes alterações: 

  • Rota padrão

Quando não utilizamos o iproute2 para controlar a rota, nossa configuração de rota padrão fica gravada no arquivo /etc/sysconfig/network. Vamos editá-lo:

comando# vi /etc/sysconfig/network
# em rede IPv4
NETWORKING=yes
# em rede IPv6
NETWORKING_IPV6=no
# hostname do Linux
HOSTNAME=srv.localhost
# gateway da rede
# isto aqui vamos tirar, pois o gateway agora será controlado pelo iprouteGATEWAY=100.100.100.1 (não esqueça de remover a linha GATEWAY)

comando# :wq (para gravar e sair do vi)



Nosso arquivo /etc/sysconfig/network ficará assim:

NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=srv.localhost


  • rp_filter

Deve-se desativar também o rp_filter, senão o kernel do Linux pensa que há uma tentativa de "ip-spoofing" e bloqueia o tráfego.

comando#
if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ]; then
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
echo 0 > $f
done
fi

Obs: Vamos adicionar isto em um script no final do artigo.

  • O ip_forward e ip_dynaddr

O ip_forward e o ip_dynaddr devem ser ativados, pois sem eles os pacotes não serão repassados através do firewall.

comando# echo 1 > /proc/sys/net/ipv4/ip_dynaddr
comando# echo 1 > /proc/sys/net/ipv4/ip_forward


Obs: Vamos adicionar isto em um script no final do artigo.

O iproute2 (coração do assunto)


O iproute2 é o pacote responsável pelo controle de rotas dentro de um firewall/gateway Linux.

Na união do iproute, iptables e marcação de pacotes (eu acho marcação uma gambiarra), podemos fazer "n" coisas imagináveis com esse conjunto de ferramentas.

Como o escopo desse artigo é o roteamento estático, de links roteados (não funciona com modem em bridge) sem balanceamento de carga (precisa-se de marcações de pacotes), vamos ao que interessa.

Obs.: Todas as variáveis aqui apresentadas serão adicionadas no final do artigo em um script único para uma melhor aplicação dos ensinamentos.

  • As variáveis de roteamento

## link1
link1_iface=eth0 # interface do seu link1
link1_rede=100.100.100.0/30 # aqui você coloca sua rede, com máscara
link1_gw=100.100.100.1 # o gateway do seu link1
link1_ip_local=100.100.100.2 # o ip do seu server do link1

## link2
link2_iface=eth1 # interface do seu link2
link2_rede=200.200.200.0/30 # aqui você coloca sua rede, com máscara
link2_gw=200.200.200.1 # o gateway do seu link2
link2_ip_local=200.200.200.2 # o ip do seu server do link2

## rede locallan_iface=eth2
lan_rede=192.168.0.0/24 # aqui você coloca sua rede com máscara
lan_gw=192.168.0.254 # aqui coloca o gw da rede local


  • Configurações das tabelas de rotas do iproute2

### resetar tabelas de rotas
echo "255 local" > /etc/iproute2/rt_tables
echo "254 main" >> /etc/iproute2/rt_tables
echo "253 default" >> /etc/iproute2/rt_tables
echo "0 unspec" >> /etc/iproute2/rt_tables
echo "30 link1" >> /etc/iproute2/rt_tables
echo "31 link2" >> /etc/iproute2/rt_tables


  • Arquivo com ips dos clientes

Você deverá adicionar no arquivo /etc/ips.link1 os ips dos clientes que devem sair pelo link1 e no arquivo /etc/ips.link2 os ips dos clientes que devem sair pelo link2.

comando# vi /etc/ips.link1
192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4
192.168.0.5

comando# vi /etc/ips.link2
192.168.0.6
192.168.0.7192.168.0.8
192.168.0.9
192.168.0.10

  • Configurações do iproute2 (o coração)

### remover rotas padrão - se houverip route del default &> /dev/null
ip route del default &> /dev/null
ip route del default &> /dev/null### remover tabelasip rule del lookup link1 &> /dev/null
ip rule del lookup link1 &> /dev/null
ip rule del lookup link1 &> /dev/null
ip rule del lookup link2 &> /dev/null
ip rule del lookup link2 &> /dev/null
ip rule del lookup link2 &> /dev/null

### adicionar rotas nas tabelas# tabela link1
# remover regras
# detalhe antes de cat é uma crase "`" e não uma aspas simples
for $ip in `cat /etc/ips.link1`
do
ip rule del from $ip &> /dev/null
done
ip rule del from $link1_ip_local &> /dev/null

# adicionar regras# detalhe antes de cat é uma crase "`" e não uma aspas simples
for $ip in `cat /etc/ips.link1`
do
ip rule add from $ip table link1 prio 30 &> /dev/null
done
ip rule add from $link1_ip_local table link1 prio 30

# adicionar rotasip route add $link1_ip_local via $link1_gw dev $link1_iface table link1
ip route add default via $link1_gw table link1
# tabela link2
# remover regras
# detalhe antes de cat é uma crase "`" e não uma aspas simples
for $ip in `cat /etc/ips.link2`
do
ip rule del from $ip &> /dev/null
done
ip rule del from $link2_ip_local &> /dev/null

# adicionar regras

# detalhe antes de cat é uma crase "`" e não uma aspas simples
for $ip in `cat /etc/ips.link2`
do
ip rule add from $ip table link2 prio 30 &> /dev/null
done
ip rule add from $link2_ip_local table link2 prio 30

# adicionar rotas

ip route add $link2_ip_local via $link2_gw dev $link2_iface table link2
ip route add default via $link2_gw table link2

### aplicar mudanças no iproute
ip route flush cache


O iptables


Agora vamos partir para o iptables, é onde iremos determinar com qual endereço IP os clientes vão sair, e se você tiver o SQUID é aqui que vamos redirecionar o tráfego dos clientes para o Squid.

  • O iptables é quem comanda

Quando você tinha apenas um link, para permitir acesso externo bastava usar o mascaramento no iptables (MASQUERADE), mas com o iproute e 2 links na jogada, as regras do negócio mudam.

A partir de agora será utilizado no NAT do iptables o "alvo" SNAT (Source NAT).

Como criamos no item anterior, os arquivos /etc/ips.link1 e /etc/ips.link2 que é onde guardamos os ips dos clientes que vão sair pelo link1 e pelo link2 respectivamente, agora vamos determinar no iptables como eles serão "NATeados". :)

### script do iptables
# cuidado aqui é crase e não aspas simples
for ip in `cat /etc/ips.link1`
do
iptables -t nat -A POSTROUTING -s $ip -d 0/0 -j SNAT --to $link1_ip_local
donefor ip in `cat /etc/ips.link2`
do
iptables -t nat -A POSTROUTING -s $ip -d 0/0 -j SNAT --to $link2_ip_local
done
Sobre o tratamento no iptables é basicamente isto. Agora se você utiliza o proxy SQUID, vamos ter que adicionar as seguintes regras antes destas regras acima:
for ip in `cat /etc/ips.link1`
do
iptables -t nat -A PREROUTING -s $ip -d 0/0 --dport 80 -j REDIRECT --to 3128
done
for ip in `cat /etc/ips.link2`
do
iptables -t nat -A PREROUTING -s $ip -d 0/0 --dport 80 -j REDIRECT --to 3128
done
Assim o tráfego para a porta 80 será redirecionada para a porta do SQUID. 

O SQUID

No SQUID, deveremos determinar com qual ip cada cliente sairá também.

Senão ao redirecionar a porta 80 para o Squid, os clientes sairão por apenas um link.
Antes das acls comuns, crie as seguintes acls:

# os ips devem ser os ips das interfaces dos links
# os ips devem existir no servidor (localmente) senão dá erro.
# criando as acls
acl ips_link1 src "/etc/ips.link1"
tcp_outgoing_address 100.100.100.2 ips_link1
acl ips_link2 src "/etc/ips.link2"
tcp_outgoing_address 200.200.200.2 ips_link2
# aqui entram seus filtros se tiver, tipo.
acl sexo url_regex -i "/etc/squid/lst_sexo.txt"http_access allow ips_link1 !sexo # por exemplo
# e no final das regras de http_access antes do deny all
http_access allow ips_link1
http_access allow ips_link2


Pronto, não há muito mistério no SQUID.

Agora vamos para a parte mais interessante de tudo, o script do iptables + iproute2 completos e unidos em um único arquivo.

O script final

Edite o arquivo /etc/fw e coloque nele o conteúdo abaixo:

comando# vi /etc/fw

#!/bin/bash
clear
echo "------------ FIREWALL ------------"

## iptables

ipt=iptables

## link1link1_iface=eth0 # interface do seu link1
link1_rede=100.100.100.0/30 # aqui você coloca sua rede, com máscara
link1_gw=100.100.100.1 # o gateway do seu link1
link1_ip_local=100.100.100.2 # o ip do seu server do link1

## link2link2_iface=eth1 # interface do seu link2
link2_rede=200.200.200.0/30 # aqui você coloca sua rede, com máscara
link2_gw=200.200.200.1 # o gateway do seu link2
link2_ip_local=200.200.200.2 # o ip do seu server do link2

## rede locallan_iface=eth2
lan_rede=192.168.0.0/24 # aqui você coloca sua rede com máscara
lan_gw=192.168.0.254 # aqui coloca o gw da rede local

# carregar módulosecho "Carregando módulos..."
modprobe ip_tables
modprobe iptable_nat
modprobe iptable_mangle
modprobe ip_nat_ftp
modprobe ip_nat_h323
modprobe ipt_limit
modprobe ipt_tos
# limpar regras
echo "Limpando regras antigas..."
$ipt -F
$ipt -t nat -F
$ipt -t mangle -F
$ipt -X
$ipt -t nat -X
$ipt -t mangle -X
# ação padrão - dropar tudo
$ipt -P INPUT DROP
$ipt -P FORWARD DROP
$ipt -P OUTPUT ACCEPT

# aceitar pacotes de retorno$ipt -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$ipt -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

# proteções# anti-ip spoofing - desativar por causa do iproute2
if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ]; then
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
echo 0 > $f
done
fi

$ipt -A INPUT -i $link1_iface -s 192.168.0.0/255.255.0.0 -j DROP$ipt -A INPUT -i $link2_iface -s 192.168.0.0/255.255.0.0 -j DROP
$ipt -A INPUT -i $link1_iface -s 172.0.0.0/255.0.0.0 -j DROP
$ipt -A INPUT -i $link2_iface -s 172.0.0.0/255.0.0.0 -j DROP
$ipt -A INPUT -i $link1_iface -s 10.0.0.0/255.0.0.0 -j DROP
$ipt -A INPUT -i $link2_iface -s 10.0.0.0/255.0.0.0 -j DROP
# ativando repasse de pacotes
echo 1 > /proc/sys/net/ipv4/ip_dynaddr
echo 1 > /proc/sys/net/ipv4/ip_forward
# QoS
$ipt -I FORWARD -p tcp --tcp-flags SYN,RST SYN --dport 1863 -j TCPMSS --clamp-mss-to-pmtu
$ipt -I FORWARD -p tcp --tcp-flags SYN,RST SYN --dport 5190 -j TCPMSS --clamp-mss-to-pmtu
$ipt -I FORWARD -p tcp --tcp-flags SYN,RST SYN --dport 7001 -j TCPMSS --clamp-mss-to-pmtu
# liberar acesso interno
echo "Liberando acesso local..."
$ipt -A INPUT -i loopback -j ACCEPT
$ipt -A INPUT -s 127.0.0.1 -j ACCEPT
$ipt -A INPUT -s $link1_ip_local -j ACCEPT
$ipt -A INPUT -s $link2_ip_local -j ACCEPT
# serviços externos
echo "Liberando acesso aos serviços..."

# dns
$ipt -A INPUT -p tcp --dport 53 -j ACCEPT
$ipt -A INPUT -p udp --dport 53 -j ACCEPT
$ipt -A INPUT -p tcp --sport 53 -j ACCEPT
$ipt -A INPUT -p udp --sport 53 -j ACCEPT

# retorno proxy$ipt -A INPUT -p tcp --dport 3128 --sport 80 -j ACCEPT
$ipt -A INPUT -p tcp --dport 3128 --sport 8080 -j ACCEPT
# serviços internos
# coloque aqui para permitir acesso aos seus serviços internos

$ipt -A INPUT -i $lan_iface -p tcp --dport 22 -j ACCEPT$ipt -A INPUT -i $lan_iface -p tcp --dport 53 -j ACCEPT
$ipt -A INPUT -i $lan_iface -p udp --dport 53 -j ACCEPT
$ipt -A INPUT -i $lan_iface -p tcp --dport 80 -j ACCEPT
$ipt -A INPUT -i $lan_iface -p tcp --dport 3128 -j ACCEPT
### rotas
# resetar tabelas de rotas
echo "255 local" > /etc/iproute2/rt_tables
echo "254 main" >> /etc/iproute2/rt_tables
echo "253 default" >> /etc/iproute2/rt_tables
echo "0 unspec" >> /etc/iproute2/rt_tables
echo "30 link1" >> /etc/iproute2/rt_tables
echo "31 link2" >> /etc/iproute2/rt_tables

# remover rotas padrão - se houverip route del default &> /dev/null
ip route del default &> /dev/null
ip route del default &> /dev/null

# remover tabelasip rule del lookup link1 &> /dev/null
ip rule del lookup link1 &> /dev/null
ip rule del lookup link1 &> /dev/null
ip rule del lookup link2 &> /dev/null
ip rule del lookup link2 &> /dev/null
ip rule del lookup link2 &> /dev/null
# adicionar rotas nas tabelas
# tabela link1
# remover regras
# detalhe antes de cat é uma crase "`" e não uma aspas simples
for $ip in `cat /etc/ips.link1`
do
ip rule del from $ip &> /dev/null
done
ip rule del from $link1_ip_local &> /dev/null

# adicionar regras# detalhe antes de cat é uma crase "`" e não uma aspas simples
for $ip in `cat /etc/ips.link1`
do
ip rule add from $ip table link1 prio 30 &> /dev/null
done
ip rule add from $link1_ip_local table link1 prio 30

# adicionar rotasip route add $link1_ip_local via $link1_gw dev $link1_iface table link1
ip route add default via $link1_gw table link1
# tabela link2
# remover regras# detalhe antes de cat é uma crase "`" e não uma aspas simples
for $ip in `cat /etc/ips.link2`
do
ip rule del from $ip &> /dev/null
done
ip rule del from $link2_ip_local &> /dev/null

# adicionar regras# detalhe antes de cat é uma crase "`" e não uma aspas simples
for $ip in `cat /etc/ips.link2`
do
ip rule add from $ip table link2 prio 30 &> /dev/null
done
ip rule add from $link2_ip_local table link2 prio 30

# adicionar rotasip route add $link2_ip_local via $link2_gw dev $link2_iface table link2
ip route add default via $link2_gw table link2
# aplicar mudanças no iproute
ip route flush cache
# liberando acesso clientes
echo -n "Liberando acesso para clientes..."

# clientes link1
for ip in `cat /etc/ips.link1`
do

# liberação de FORWARD

$ipt -A FORWARD -s $ip -j ACCEPT

# marcar pacotes para gráfico de consumo de banda
$ipt -t mangle -A PREROUTING -s $ip -j ACCEPT # down $ipt -t mangle -A POSTROUTING -d $ip -j ACCEPT # up

# mascaramento - radio uol
$ipt -t nat -A PREROUTING -p tcp -s $ip -d 200.221.5.71 -j ACCEPT
$ipt -t nat -A PREROUTING -p tcp -s $ip -d 200.221.8.74 -j ACCEPT
$ipt -t nat -A PREROUTING -p tcp -s $ip -d 200.221.8.75 -j ACCEPT
$ipt -t nat -A PREROUTING -p tcp -s $ip -d 200.221.8.118 -j ACCEPT

# nat caixa econômica federal (conectividade)

$ipt -t nat -A PREROUTING -p tcp -s $ip -d 200.201.0.0/16 --dport 80 -j ACCEPT

# redirecionamento para o proxy $ipt -t nat -A PREROUTING -p tcp -s $ip --dport 80 -j REDIRECT --to-port 3128
$ipt -t nat -A PREROUTING -p tcp -s $ip --dport 8080 -j REDIRECT --to-port 3128
$ipt -t nat -A POSTROUTING -s $ip -d 0/0 -j SNAT --to $link1_ip_local
echo -n "."
done

# clientes link2for ip in `cat /etc/ips.link2`
do
# liberação de FORWARD
$ipt -A FORWARD -s $ip -j ACCEPT

# marcar pacotes para gráfico de consumo de banda
$ipt -t mangle -A PREROUTING -s $ip -j ACCEPT # down
$ipt -t mangle -A POSTROUTING -d $ip -j ACCEPT # up

# mascaramento - radio uol
$ipt -t nat -A PREROUTING -p tcp -s $ip -d 200.221.5.71 -j ACCEPT
$ipt -t nat -A PREROUTING -p tcp -s $ip -d 200.221.8.74 -j ACCEPT
$ipt -t nat -A PREROUTING -p tcp -s $ip -d 200.221.8.75 -j ACCEPT
$ipt -t nat -A PREROUTING -p tcp -s $ip -d 200.221.8.118 -j ACCEPT

# nat caixa econômica federal (conectividade)
$ipt -t nat -A PREROUTING -p tcp -s $ip -d 200.201.0.0/16 --dport 80 -j ACCEPT

# redirecionamento para o proxy
$ipt -t nat -A PREROUTING -p tcp -s $ip --dport 80 -j REDIRECT --to-port 3128
$ipt -t nat -A PREROUTING -p tcp -s $ip --dport 8080 -j REDIRECT --to-port 3128
$ipt -t nat -A POSTROUTING -s $ip -d 0/0 -j SNAT --to $link2_ip_local
echo -n "."
done

echo ""

echo "----------------------------------"



Script pronto, agora temos que torná-lo executável:
comando# chmod +x /etc/fw

Vamos colocar ele no patch pra poder executar apenas digitando "fw" no prompt.
comando# ln -s /etc/fw /sbin/fw

Pronto. Agora basta testar e correr para o abraço.

Obs: No SQUID basta adicionar o que está no item 6 e pronto.
Espero que tenha ajudado alguém!

Referências

Postado originalmente neste link pelo Viva o Linux em 21/05/2008.

Peguei como conteúdo principal deste artigo, meu próprio post feito na "linux-br" em 21 de novembro de 2007 [1].

Fiz aqui as devidas adaptações, incluindo um script de firewall completo para um melhor entendimento.

[1] http://lie-br.conectiva.com.br/pipermail/linux-br/2007-November/045239.html
[2] http://www.gulbf.com.br/?q=node/26
[3] http://www.linux-foundation.org/en/Net:Iproute2
[4] http://lartc.org/howto/lartc.rpdb.multiple-links.html
[5] http://www.dicas-l.com.br/dicas-l/20030730.php
[6] http://www.dicas-l.com.br/dicas-l/20061006.php

Agradecimentos


Aos "linuxistas" de plantão que me adicionaram no MSN para tirar dúvidas sobre o meu post na "linux-br" sobre este assunto.

Mais especificamente ao "timidboy" do Viva o Linux, que foi quem me deu a idéia de escrever esse artigo.

Ao Google, que nunca me deixa na mão quando preciso de mais informações pelo mundo.

A Deus por ter me dado vontade de aprender sempre e sempre.

Sobre o autor


Nome: Wenderson Souza
Idade: 30 anos (em 01/01/2013)
Profissão: Gerente de TI
Atuo na área de informática desde 1998.
Trabalho com distribuições Linux desde 2000.
Atuo na área de telecomunicações desde 2006.
Distribuição Linux: CentOS
Atualmente atuo mais em FreeBSD
e-mail: wendersonsouza at gmail.com
msn: wendersonsouza at msn.com

Nenhum comentário:

Postar um comentário