sexta-feira, 1 de fevereiro de 2008

Roteando múltiplos links de internet

A empresa onde trabalho depende 100% da internet para seu funcionamento, devido a isso procurei escolher uma boa opção de link de internet levando em consideração o melhor preço X a melhor qualidade de serviço.
É claro que as melhores opções são sempre os links dedicados, no entanto esses serviços são caros se comparados aos serviços DSL disponíveis.

Depois de um bom tempo usando o Velox da Telemar, fui apresentado a MundiVox que até que tem um serviço de boa qualidade, só deixando a desejar no primeiro mês de uso.

Apesar da boa qualidade do serviço, inevitavelmente acontecem algumas pequenas interrupções que as vezes não passam de 1 minuto, mas as vezes pode passar dos 10. Sendo assim decidi contratar mais um link de internet de outro fornecedor para efeitos de backup.

Uma vez que o outro link já estava instalado e funcionando surgiu o desafio: Como inserir o novo link na rede de modo a garantir que a internet não pare nunca (failover), e como combinar os 2 links para aumentar a velocidade de acesso a internet (load balancing)?

Inicialmente pensei que a solução fosse utilizar o recurso de “bonding” do kernel, no entanto após ler bem a pouca documentação disponível descobri que o bonding só funciona com links que façam parte de uma mesma rede (lógica).

Pesquisando mais a fundo descobri que a solução está nas tabelas de roteamento do sistema, na verdade na parte Avançada de Roteamento do sistema (o conhecido Linux Advanced Routing and Traffic Control)

A idéia básica do sistema é de criar tabelas de roteamento separadas para cada link e utilizar um gateway multipath ( com rotas alternativas ) como rota padrão. Para isso é necessário utilizar o pacote iproute2, disponível em http://linux-net.osdl.org/index.php/Iproute2

O pacote iproute2 fornece ferramentas avançadas para a configuração de interfaces, endereços, rotas e filtros e pode substituir as ferramentas padrões já conhecidas: ifconfig, route, arp.
No kernel, a opção IP: advanced router provê o suporte necessário para o recurso.

A configuração é simples e basicamente se dá em configurar o kernel e adicionar algumas tabelas de roteamento.

Configuração do kernel

# cd /usr/src/linux
# make menuconfig

Networking —>
Networking options —>
[*] IP: advanced router
[*] IP: policy routing
[*] IP: use netfilter MARK value as routing key
[*] IP: equal cost multipath
[ ] IP: equal cost multipath with caching support (EXPERIMENTAL)

O suporte a equal cost multipath with caching ainda é experimental e não costuma funcionar corretamente, é altamente recomendado desativar essa opção.
Nos meus testes ao habilitar o recurso, as tabelas de roteamento demoravam muito mais tempo para serem trocadas (quando falhas) além de que não conseguia pingar endereços externos por ambas interfaces (embora o tráfego funcionasse).

Compile e instale o novo kernel

# make
# cp arch/i386/boot/bzImage /boot/kernel-2.6.17-gentoo-r4

Instalação do iproute2

O iproute2 está disponível na árvore do portage e portanto basta um emerge para instalar o pacote.

# emerge iproute2

Usuários de outras distribuições podem usar os devidos sistemas de pacotes para instalar o iproute2 ou instalar a partir dos fontes.

# cd /usr/src/
# wget http://developer.osdl.org/dev/iproute2/download/iproute2-2.6.18-061002.tar.gz
# tar xzf iproute2-2.6.18-061002.tar.gz
# cd iproute2
# ./configure
# make
# make install

Configurando

Supondo que temos 2 links A e B (com IPs estáticos) de provedores distintos e gostaríamos de compartilha-los para nossa rede local na interface de rede C, podemos considerar o seguinte esquema:

INTERNET         INTERNET
| |
ISP1 ISP2
10.0.0.1 172.16.0.1
eth1 eth2/
10.0.0.5 172.16.0.7
NAT ROUTER (eth0)
|192.168.0.1
----+-----------------+---

No esquema acima temos a seguinte configuração:

IP0 =  192.168.0.1
NET0 = 192.168.0.0
BCAST0 = 192.168.0.255

IP1 = 10.0.0.5
GW1 = 10.0.0.1
NET1 = 10.0.0.0
BCAST1 = 10.0.0.255

IP2 = 172.16.0.1
GW2 = 172.16.0.7
NET2 = 172.16.0.0
BCAST2 = 172.16.0.255

Onde IP(0,1,2) é o endereço IP da interface, GW(1,2) é o gateway, NET(0,1,2) é o endereço da rede e BCAST(0,1,2) é o endereço de broadcast.

Interfaces de rede

Devemos configurar as interfaces normalmente porém não deve ser adicionada uma rota default.

# ip link set eth0 up
# ip addr add IP0/24 broadcast BCAST0 dev eth0
# ip link set eth1 up
# ip addr add IP1/24 broadcast BCAST1 dev eth1
# ip link set eth2 up
# ip addr add IP2/24 broadcast BCAST2 dev eth2

(o número 24 após a barra representa o endereço de rede)

Tabelas de roteamento

Com o suporte a advanced router e policy routing no kernel, é possível criar tabelas de roteamento separadas para cada link.

O arquivo /etc/iproute2/rt_tables define as tabelas de roteamento disponiveis no sistema. Nele são definidas 4 tabelas padrões do sistema que são: local, main, default e unspec.
A tabela local armazena as rotas para as redes configuradas no sistema e é manipulada diretamente pelo kernel. As rotas padrões (configuradas pelo usuário) são inseridas na tabela main.
É possível ainda adicionar novas tabelas ao arquivo embora isso não seja extremamente necessário a menos que as tabelas sejam sempre chamadas através do nome ao invés do seu número.

# vi /etc/iproute2/rt_tables

#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
20 isp1
30 isp2
100 netgw

Certifique-se de que não existe nenhuma rota padrão configurada e defina a prioridade da tabela main para um número menor que os das interfaces de rede.

# ip route show table main|grep default
# ip route del default
# ip rule add prio 10 table main

Para que a configuração funcione corretamente é preciso se certificar de que os pacotes voltem sempre pela interface pela qual entraram. Dessa forma é necessário criar uma tabela separada para cada link especificando sua rota padrão. Também é necessário definir uma regra para cada tabela.

# ip rule add prio 20 table isp1
# ip route add route from NET1/24 default via GW1 dev eth1
# ip route append prohibit default table isp1 metric 1
# ip rule add prio 30 table isp2
# ip route add route from NET2/24 default via GW2 dev eth2
# ip route append prohibit default table isp2 metric 1

A linha com o parâmetro prohibit funciona de forma similar ao REJECT do itptables. Quando um cliente está transferindo dados por uma certa interface e ela deixa de funcionar, uma mensagem ICMP é enviada ao cliente de modo a fazer com que o mesmo termine a conexão e comece uma nova usando uma rota funcional.

Também é necessário criar uma tabela para o gateway multipath.

# ip rule add prio 100 table netgw
# ip route add default nexthop via GW1/24 dev eth1 nexthop via GW2/24 dev eth2

Pode-se utilizar o parâmetro weight de modo a especificar o peso (preferência) da rota

NAT

O compartilhamento para a rede interna pode ser feito através do iptables mascarando a saída nas interfaces eth0 e eth1.

# iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
# iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE
# echo 1 > /proc/sys/net/ipv4/ip_forward

Testando

Nesse momento já deve ser possível acessar um endereço externo por ambas as rotas.

# ping google.com -c 1 -I eth1 
PING google.com (64.233.167.99) from 10.0.0.5 eth1: 56(84) bytes of data.
64 bytes from 64.233.167.99: icmp_seq=1 ttl=243 time=191 ms

# ping google.com -c 1 -I eth2
PING google.com (64.233.167.99) from 172.16.0.1 eth2: 56(84) bytes of data.
64 bytes from 64.233.187.99: icmp_seq=1 ttl=243 time=115 ms

Vale lembrar que como o kernel guarda um cache das rotas utilizadas é provável que quando um dos links falhar demore alguns mimnutos até que a rota indisponível seja deletada e uma nova seja criada utilizando o link funcional.

É possível definir através do arquivo /proc/sys/net/ipv4/route/gc_timeout o tempo máximo que o kernel espera até tentar uma nova rota quando perceber que a atual está morta.

Também é possível forçar a “limpeza” do cache de roteamento com o seguinte comando:

# ip route flush cache dev ethX
(onde X é o número da interface)

Dessa forma é possível criar um script que tente pingar os gateways (ou outro endereço público) e caso não haja resposta apagar o cache da tabela de roteamento.

Melhorando a detecção de rotas mortas

O kernel linux armazena as rotas de rede utilizadas em um tabela de cache que é consultada a cada acesso. Quando uma rota não é encontrada utiliza-se os gateways disponíveis para traçar uma nova rota e automaticamente ela é armazenada.

Quando tentamos acessar um endereço por uma certa rota e esta falha, não necessariamente temos problemas com o gateway ou com a interface, as vezes o problema pode ser com o endereço de destino. Dependendo do motivo da falha, certas ações são tomadas pelo sistema.

Após um certo tempo, o gateway será considerado como morto e marcado como indisponível (”unreachable”). Se o problema for com a interface o link será desativado e as rotas serão limpadas (flushed) do cache forçando a utilização de uma nova rota.
Caso o problema seja outro (um gateway “morto” no caminho por exemplo) não será possível detectar a falha e as tentativas de conexão continuarão tentando essa rota e falhan do. Após mais um certo tempo o cache de rotas irá expirar e só então uma nova rota (funcional) será tentatada.

Da mesma forma, caso a falha tenha sido da interface e/ou cabeamento, não será possível re-inserir as rotas automaticamente quando o problema se resolver automaticamente, necessitando assim de uma intervenção do administrador para ativação das mesmas.

O Julian Anastasov já há alguns anos disponibiliza alguns patchs para melhor esse recurso no kernel, tornando a detecção de gateway/rotas mortas mais inteligente. Os patches podem ser encontrados em http://www.ssi.bg/~ja/

Com os patches aplicados é possível por exemplo usar “prot static” para todas as rotas. Dessa forma, mesmo que uma interface se torne indisponível o kernel não irá remover as rotas e uma vez que a interface seja disponibilizada novamente tudo estará funcionando perfeitamente (ideal para esquemas de failover).

# cd /usr/src/
# wget http://www.ssi.bg/~ja/routes-2.6.17-12.diff
# patch -p1 < routes-2.6.17-12.diff
# cd linux
# make && make modules install
# cp arch/i386/boot/bzImage /boot/kernel-2.6.17-gentoo-r4

Configure o gerenciador de boot e reinicialize com o novo kernel

Atualizado: Gráficos Comparativos

O balanceamento de uso dos links pode ser comprovado nos gráficos abaixo. O primeiro gráfico representa as 2 semanas anteriores a instala~ao do segundo link. Os demais representam 2 semanas de uso com os 2 links.

Link 01 - 2 semanas antes

Link 01 - 2 semanas após

Link 02 - 2 semanas após

Automatizando a configuração no Gentoo

No gentoo é possível definir funções no arquivo de configurações de redes. Tais funções são executadas antes/após carregar uma interface e antes/após descarregar uma interface. Dessa forma é possível automatizar o processo de criar as rotas e regras.
A função postup que implemento abaixo não é muito inteligente, porém dá uma idéia básica de como automatizar o processo de configuração das redes.
A cada interface que for configurada as ações de adicionar/remover regra/rota são executadas.

# vi /etc/conf.d/net

config_eth0=( “192.168.0.1 netmask 255.255.255.0″ )
config_eth1=( “10.0.0.5 netmask 255.255.255.0″ )
config_eth2=( “172.16.0.1 netmask 255.255.255.0″ )
append_eth0=( “default via 10.0.0.1 src 10.0.0.5 proto static table isp1″
“prohibit default table isp1 metric 1 proto static”)
append_eth1=( “default via 172.16.0.7 src 172.16.0.1 proto static table isp2″
“prohibit default table isp2 metric 1 proto static”)
rule_eth0=( “from 10.0.0.0/24 priority 20 table isp1″ )
rule_eth1=( “from 172.16.0.0/24 priority 30 table isp2″ )
multipath_route=( “table netgw proto static nexthop via 10.0.0.1
dev eth1 nexthop via 172.16.0.7 dev eth2″ )
multipath_rule=( “prio 100 table netgw”
“prio 10 table main” )

postup() {
local x=”append_${IFVAR}[@]”
local -a appends=( “${!x}” )
if [[ -n ${appends} ]] ; then
einfo “Appending route”
eindent

for x in “${appends[@]}”; do
ip route del ${x} 1>&2 2> /dev/null
ebegin “${x}”

ip route append ${x}
eend $?
done
eoutdent

#Flush the cache
ip route flush cache dev “${IFACE}”
fi

local x=”rule_${IFVAR}[@]”
local -a rules=( “${!x}” )
if [[ -n ${rules} ]]; then
einfo “Adding IP policy routing rules”
eindent

for x in “${rules[@]}”; do
ip rule del ${x} 1>&2 2> /dev/null
ebegin “${x}”

ip rule add ${x}
eend $?
done
eoutdent
fi

if [[ -n ${multipath_route} ]]; then
for x in “${multipath_route[@]}”; do
einfo “Adding multipath route”
eindent
ip route del default 1>&2 2> /dev/null
ip route del ${x} 1>&2 2> /dev/null
ebegin “${x}”
ip route add default ${x}
eend $?
eoutdent
done
fi

if [[ -n ${multipath_rule} ]]; then
for x in “${multipath_rule[@]}”; do
einfo “Adding multipath rule”

eindent
ip rule del ${x} 1>&2 2> /dev/null
ebegin “${x}”
ip rule add ${x}
eend $?
eoutdent
done
fi
}

Referências

Controle de Tráfego

Controle de tráfego é o nome dado ao conjunto de sistemas de enfileiramento (queuing) e mecanismos pelos quais os pacotes são recebidos e transmitidos em um roteador. Isso inclui que pacotes aceitar a que velocidade e em qual interface e que pacotes devem ser priorizados. O termo QoS (Quality of Service) é frequentemente utilizado como sinônimo de Controle de Tráfego.

O controle de tráfego no Linux se encontra em um estado maduro e bastante avançado em termos de recursos.

Conceitos
Para entendermos melhor o controle de tráfego, vamos nos familiarizar com alguns conceitos utilizados nele:

Filas (queues)
Uma fila é um local (ou buffer) contendo um número finito de itens aguardando por uma ação ou serviço. Em redes, uma fila é local onde os pacotes aguardam antes de serem enviados pelo hardware.

Shapping
Shapping é o ato de "atrasar" o envio de pacotes de forma que o tráfego fique dentro de um determinado limite de velocidade. Como efeito colateral um shapper pode deixar um determinado tráfego mais regular, ao remover ou "achatar" as rajadas de pacotes.

Scheduling
Scheduling ou escalonamento é o ato de ordenar ou re-ordenar os pacotes para serem enviados. O método mais comum de escalonamento é o FIFO (First-in First-out, "o primeiro a chegar é o primeiro a sair"). Outros métodos de escalonamento incluem o SFQ, que procura dar a cada "flow" uma chance de transmitir seus pacotes, ou o RED, que procura descartar pacotes de forma randômica ao se atingir uma determinada condição de forma a evitar que o backbone fique saturado.

Classifying
Classificação (classifying) é o mecanismo pelo qual os pacotes são separados de forma a terem tratamentos diferentes, possivelmente colocando-os em diferentes filas de saída. Uma pacote ou flow pode ser classificado de várias maneiras diferentes ao atravessar um roteador ou rede.

Policing
Policing é o mecanismo pelo qual o tráfego pode ser limitado. Assim é possível garantir de que um determinado tipo de tráfego não consuma mais banda do que foi destinado a ele.

Componentes do Controle de Tráfego do Linux

O Linux possui os seguintes componentes: qdisc, class e filters. Antes de vermos com mais detalhes cada um deles, vamos fazer uma rápida relação desses elementos com os conceitos expostos:

ConceitoComponente
ShappingAs "class" oferecem a capacidade de "shapping"
Schedulingum qdisc é um escalonador. Ele pode ser simples como um FIFO (fila) ou pode conter classes dentro dele
ClassifyingA classificação é feita dentro de um "filter" através de um "classificador"
PolicingO policing é implementado no Linux como uma parte de um filter


Qdisc
Os qdiscs (abreviação de Queueing Disciplines) são as filas de saída dos pacotes. Um qdisc exerce a função de escalonador de pacotes também.

O Linux possui dois tipos de qdisc: classless e classfull qdiscs. Os qdics classless não podem conter classes definidas pelo usuário, embora alguns deles possuam mais de uma fila de saída. Já os qdiscs classfull podem conter subclasses definidas pela usuário, permitindo assim a separação e a atribuição de quantidades diferentes de banda para cada tipo de fluxo.

Cada interface de rede possui um qdisc "root". O padrão do Linux é atribuir um qdisc do tipo "pfifo_fast" para o qdisc root, mas obviamente, isso pode ser mudado.

Como não pretendemos aqui fazer um "tratado" sobre QoS? no Linux veremos apenas alguns qdiscs, entre eles três classless, pfifo_fast, sfq e tbf e um classfull, o htb. Embora um dos qdiscs classfull mais populares seja o cbq (talvez por ser um dos mais antigos), não trataremos dele, pois é mais complexo e pode ser substituído com vantagens pelo htb.

Classless Qdiscs
PFIFO_FAST
O pfifo_fast é o qdisc padrão do Linux. Ele é baseado no FIFO, mas possui internamente três filas, onde determinado tipo de tráfego pode ser priorizado. Os pacotes são colocados nestas filas de acordo com o seu TOS, assim pacotes pertencentes a tráfegos do tipo interativo recebem maior prioridade e são sempre servidos primeiro. Pacotes na fila 0, são servidos primeiro, e somente quando essa fila se encontra vazia, são servidos os pacotes da fila 1. De maneira análoga são servidos os pacotes da fila 2.

SFQ
O qdisc SFQ (Stochastic Fair Queuing) é um qdisc que procura distribuir de maneira igual a oportunidade para cada flow ser servido. O SFQ mantém internamente várias filas FIFO e utiliza uma função HASH para distribuir os pacotes entre essas filas. As filas são então servidas usando uma função "round-robin". Para evitar que a função hash escolhida acabe privilegiando ou prejudicando um determinado tipo de fluxo, o SFQ possui o parâmetro "perturb" que indica de quanto em quantos segundos a função HASH deve ser recalculada.

TBF
O TBF (Token Bucket Filter) utiliza o modelo de balde de fichas para "shapear" o tráfego. Normalmente o TBF é utilizado quando desejamos simplesmente limitar a velocidade de uma determinada interface. Os principais parâmetros do TBF são

Parâmetrosignificado
limitQuantidade de bytes que podem aguardar na fila
bursttamanho do "balde" em bytes. Esse parâmetro pode ser utilizado para permitir rajadas
ratevelocidade com que os "tokens" chegam ao balde.


Classful Qdiscs

HTB
O HTB (Hierarchical Token Bucket) utiliza o conceito de balde de fichas combinado com um sistema de classes e filtros, que permite a configuração de um controle do tráfego bastante preciso e complexo.

Como o HTB é um qdisc com suporte a classes, ele pode ser utilizado como um qdisc (um escalonador/shaper) ou como uma classe. Quando utilizado como classe o htb possui apenas um parâmetro (opcional) "default" que define qual subclasse deverá ser utilizada caso um pacote não seja classificado por nenhum filtro.

Como um escalanador o HTB suporta, dentre outros, os seguintes parâmetros:

ParâmetroSignificado
ratevelocidade de transmissão dos pacotes
bursttamanho máximo de bytes que pode ser acumulado para rajadas
ceilvelocidade total da classe superior. Esse parâmetro é utilizado para permitir que uma classe tome "emprestado" banda disponível de outra classe


Class
As classes só existem dentro de qdiscs classful e são uma forma de se dividir o tráfego para um tratamento diferenciado. Uma classe não manipula um pacote diretamente, isso é feito pelo qdisc associado à ela. Além da classe "root", existem dois tipos de classes. As classes "leafs", que são classes que não possuem "filhos" e classes "inner" que são classes que possuem "filhos".

Filter
Os filtros exercem a função de separar o tráfego em classes dentro de um qdisc classful. Isso é feito com o auxílio de um "classificador". Além disso um filtro pode exercer a função de "policer" tomando uma ação sempre de acordo com os limites estabelecidos para o fluxo que ele está classificando. Normalmente um filtro tem como política descatar pacotes que excedam o limite estabelecido para o qdisc no qual ele está embutido, no entanto é possível configurar outras ações, como por exemplo, re-classificar o pacote utilizando outro filtro.

Classificadores
Dentro de um filtro, um classificador é utilizado para identificar certos padrões e/ou características dos pacotes e fluxos permitindo assim a separação em classes. Veremos a seguir apenas dois classificadores do Linux:

U32
O U32 é o principal classificador do Linux, pois ele permite a identificação de qualquer parte de um pacote IP (normalmente campos do cabeçalho). O U32 é bastante utilizado quando precisamos identificar IPs? de origem e/ou destino, portas de origem/destino ou mesmo protocolo (icmp, tcp, udp, etc). Veremos a seguir alguns dos principais parâmetros do U32:

ParâmetroSignificado
ip src IP/MASKCasa com pacotes com origem em IP/MASK
ip dst src IP/MASKCasa com pacotes com destino IP/MASK
ip sport NN 0xffffCasa com pacotes com porta de origem NN. O parametro 0xffff é uma máscara de 32 bits
ip dport NN 0xffffCasa com pacotes com porta de destino NN. O parametro 0xffff é uma máscara de 32 bits
ip protocol NN 0xffCasa com pacotes do tipo procolo NN. Olhe em /etc/protocols
ip tols 0xNN 0xMMCasa com os bits NN do campo TOS. Utilize a mascara MM para escolher quais bits se deseja comparar
flowid X:Y os pacotes que casam com essa regra devem ser colocados na class X:Y


O U32 é bastante poderoso e pode procurar por padrões dentro de qualquer lugar do cabeçalho ou mesmo do pacote inteiro. Para isso ele usa os seletores u32, u16, e u8 que casam com padrões de 32, 16 e 8 bits respectivamente. Esses seletores aceitam como parâmetros um padrão de bytes, uma máscara, um deslocamento em relação ao início do cabeçalho ou um deslocamento em relação ao próximo cabeçalho (cabeçalho da camada de transporte por exemplo). Mas vamos deixar essas opções mais avançadas para uma outra oportunidade.

FW
O classificador FW procura por "marcas" feitas por regras do netfilter. Sua utilização é bastante simples pois ele requer apenas dois parâmetros: handle N, informando qual "marca" ele deve procurar e flowid X:Y indicando em qual classe ele deverá colocar os pacotes encontrados.

Configurando o Controle de Tráfego

A configuração do controle de tráfego no Linux é toda feita através de um único comando: o "tc". O comando tc faz parte do pacote iproute2 - o mesmo do comando ip. O funcionamento do comando tc é similar ao do comando ip, e ele tem a forma geral:

# tc opções OBJETO PARÂMETROS

Os objetos do comando tc são: qdisc, class e filter. Veremos a seguir como manipular esses objetos.

NOTA: o tc utiliza as seguintes regras para a especificação de velocidades/banda:

mbps = 1024 kbps = 1024 * 1024 bps => byte/s mbit = 1024 kbit => kilobit/s. mb = 1024 kb = 1024 * 1024 b => byte mbit = 1024 kbit => kilobit

tc qdisc
Utilizamos o objeto qdisc para adicionar, remover e listar qdiscs. Veremos como executar cada uma dessas operções:

Adicionando e removendo qdiscs
Para adicionar um qdisc precisamos indicar em que interface estamos adicionando, qual é "handle" (identificador) do qdisc, quem é o "pai" do qdisc, e finalmente o tipo de qdisc e suas opções. O pai de um qdisc pode ser "root" caso estejamos adicionando um qdisc root ou "parent X:Y" onde X:Y é a classe a qual esse qdisc está sendo adicionado. Exemplos:

Adicionando um qdisc root:

# tc qdisc add dev eth0 root handle 1: tbf rate 5mbit burst 100kbit limit 5k

Adicionando um qdisc a uma classe:

# tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10

Adicionando um qdisc classful e definindo uma classe "padrão":

# tc qdisc add dev eth0 root handle 1: htb default 10

Para remover um qdisc basta utilizar a opção "del" em vez de add.

Listando qdiscs
Para lista um qdisc basta utilizar a opção show, não esquecendo de informar o dispositivo de rede, exemplo:

# tc qdisc show dev eth0

tc class
Como vimos anteriormente as classes funcionam como uma espécie de "subdivisão" de um qdisc classful, permitindo a separação do tráfego em outras classes/qdiscs. No caso específico do qdisc classful que veremos, o htb, é nas classes "leafs" que é feita o shaping.

Adicionando e removendo classes
Para criar uma classe precisamos informar a interface, o qdisc/classe pai dessa classe, o identificador de classe, o tipo de classe e suas opções. Exemplos:

Adicionando uma classe a um qdisc root:

# tc class add dev eth0 root classid 1:0 htb rate 2mbit

Adicionando uma classe como filha de outra classe:

# tc class add dev eth0 parent 1:0 classid 1:100 htb rate 100kbit

Vale lembrar que uma classe "leaf" pode ter um qdisc anexada a ela, mas um classe "inner" não.

Listando classes
Para listar as classes, basta usar o comando com a opção show. Adicionalmente podemos utilizar as opções -s para obtermos a quantidade de bytes e pacotes enviados por cada classe. Exemplo:

# tc -s class show dev eth0

tc filter
Os filtros devem ser "anexados" às classes para efetuarem a separação do tráfego. Um ponto importante a lembrar é a de que as classes possuem os filtros e não o contrário, ou seja, somente quando os pacotes "entram" em uma classe os filtros associadas à ela serão executados. Quando temos uma configuração com classes é importante definir uma classe "raiz" (uma classe no qdisc raiz com o "minor" 0, ex: 1:0), pois a partir dela poderemos criar filtros que apontem para outras classes.

Adicionando e removendo filtros
Para adicionarmos um filtro utilizamos o comando "tc filter add" e informamos à interface, a classe na qual queremos inserir o filtro, o protocolo, o classificador a ser utilizado e suas opções. Exemplos:

Insere um filtro na classe "raiz", casando com pacotes que venham da rede 10.0.0.0/24:

# tc filter add dev eth0 parent 1:0 protocol ip u32 match ip src 10.0.0.0/24 flowid 1:10

Insere um filtro na classe 1:10, casando com pacotes que tenham como destino a porta 80 da máquina 192.168.0.1:

# tc filter add dev eth0 parent 1:10 protocol ip u32 match ip dst 192.168.0.1/32 match ip dport 80 0xffff flowid 1:100

Os filtros aceitam também o parametro "prio N" que define a prioridade com que os filtros de uma mesma classe devem ser utilizados. Exemplo:

Insere um filtro na classe 1:20 com prioriade 2. Esse filtro casa com pacotes que foram marcados pelo netfilter com a tag "6"

# tc filter add dev eth0 parent 1:20 protocol ip prio 2 handle 6 fw flowid 1:200

Para remover um filtro utilize o mesmo comando usado para criá-lo mas com a opção "del" em vez de "add".

Listando filtros
De maneira análoga aos outros objetos, para listar os filtros utilize o comando "tc filter show", como no exemplo:

# tc filter show dev eth0

Mais Exemplos

Um recurso bastante interessante do controle de tráfego no Linux, e em particular do qdisc htb é a possibilidade de se criar classes "irmãs" que podem tomar "emprestado" banda de outra classe, caso essa banda esteja disponível. Vamos criar um exemplo prático para ver como isso funciona.

Vamos supor que temos um link de 5mbits e queremos destinar 2mbits para o tráfego web, mais 2mbits para ftp e 1mbit para o "resto" , no entanto queremos que caso haja banda disponível, o tráfego web possa chegar a 4mbits e o tráfego ftp a 3 mbits. Uma possível solução para esse cenário:

# tc qdisc add dev eth0 root handle 1: htb default 30
# tc class add dev eth0 root classid 1:0 htb rate 5 mbits
# tc class add dev eth0 parent 1:0 classid 1:10 htb rate 2mbit ceil 4mbit
# tc class add dev eth0 parent 1:0 classid 1:20 htb rate 2mbit ceil 3mbit
# tc class add dev eth0 parent 1:0 classid 1:30 htb rate 1mbit

Isso define as classes e suas velocidades. O ponto principal aqui é o parametro "ceil" que define um valor máximo de banda que pode ser utilizado caso haja banda disponível para se pegar "emprestado". Basta agora criar dois filtros para separar o tráfego web e ftp. Pacotes que não pertençam a essas classes caem no padrão definido na primeira regra.

# tc filter add dev eth0 parent 1:0 protocol ip u32 match ip dport 80 0xffff flowid 1:10
# tc filter add dev eth0 parent 1:0 protocol ip u32 match ip dport 20 0xffff flowid 1:20
# tc filter add dev eth0 parent 1:0 protocol ip u32 match ip dport 21 0xffff flowid 1:20

Obs: utilizamos as portas 20 e 21 para caracterizar o tráfego ftp.

Caso não haja tráfego algum para a classe 30, esses 1mbits podem ser divididos pelas classes 1:10 e 1:20.

quinta-feira, 31 de janeiro de 2008

DICAS IPTABLES

Sobre este documento

Original em formato texto com marcações para conversão em HTML, processo automatizado com scripts e txt2tags.

Resumo de comandos e regras de iptables mais utilizados, (na minha opinião e como eu uso, copiar e colar).

Dificilmente os comandos e dicas atenderão suas necessidades, muitos nem são compativeis com sua instalação ou nem servem para seu uso, tente adaptar ao seu ambiente, use como fonte de consulta e referencia.

Dicas - Solução de problemas

Tente instalar e configurar por partes, tente isolar o problema, facilita na localização do problema e solução, na manutenção ou instalação tente seguir esta ordem.

Passo 1 - Configure o servidor para navegar e pingar as maquinas da rede interna, configure as duas placas de rede e teste com ping para a rede interna e internet, prossiga com a instalação somente depois de obter respostas do comando ping para as maquinas da rede interna e navegar normalmente, quando não tem ambiente gráfico na maquina, use o lynx para testar a navegação, wget para download, outro serviço que possa testar o funcionamento da internet, ou arrisque prosseguir com o ping, no caso do ping faça testes com ping para um dominio.

Passo 2 - Compartilhe a conexão, sem firewall, somente compartilhe para testar a navegação a partir de uma estação, em lugar do firewall utilize estas regras de iptables.

  modprobe iptable_nat
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

Ajuste o device de acordo com sua rede, ppp0 como no exemplo acima para conexões via modem discado ou ADSL conectado via pppoe, conexões de ADSL com IP fixo ou obtido por DHCP o device é eth0, altere no exemplo acima para o device em uso.

Passo 3 - Configure a estação para navegar, precisa configurar o gateway e DNS, com esta configuração a estação navega sem restrição alguma, veja mais dicas sobre compartilhamento de internet em

http://www.zago.eti.br/adsl-compartilhar.txt

Somente depois que conseguir navegar a partir de uma estação, passe para a configuração do firewall.

Passo 4 - Explore os logs, não esqueça da grande fonte de informações que são registradas nos logs, no servidor abra um console e procure o que tem abaixo de /var/log, por exemplo, após configurar o Squid e implementar a regra de redirecionamento, as estações não navegam, um bom começo é analizar os logs do Squid, execute a linha de comando.

tail -f /var/log/squid/access.log

Este comando exibe no console as mensagens de log, exibe em tempo real, no momento em que estão sendo formadas, tente a navegação na estação e veja os resultados no console, até aqui fica fácil isolar o problema, se navegava antes do redirecionamento e agora não navega, já sabe onde procurar, inicie verificando se o Squid está rodando, configurações do squid, diretivas, ACL, permissões nos arquivos e diretórios utilizados pelo squid, documentação de configuração do Squid, pegue a mensagem de erro e coloque na caixa de pesquisa do Google..

Procure também nas mensagens de outros arquivos de log do sistema, qualquer dúvida volte ao inicio e vá testando passo a passo, seja um bom observador, antes de pedir ajuda, procure identificar a regra ou condição que ocorre, tente outras opções.

FAQ, dicas e indicação de material sobre log em geral.

http://www.zago.eti.br/firewall/log-iptables.txt

http://www.zago.eti.br/firewall/log.txt

Lembrando que as regras acima não tem proteção alguma, maquinas de cara para a internet precisa de um firewall minimo, os exemplos acima são regras para compartilhar e não oferece proteção, portanto precisa criar seu firewall, testar e monitorar, vejas as indicações de alguns modelos, ferramentas testes.

Criar ambiente de testes e backup da instalação

Considere criar um ambiente de testes, não adianta reclamar que não tem "verba" ou não tem maquina, não custa nada, o pouco tempo que investir agora vai lhe poupar muito mais no futuro além de evitar muitos problemas, considere um bom investimento de tempo, utilize estações da rede com instalações dual-boot.

Veja dicas de como fazer duas instalações Linux no mesmo HD, utilize estações para testes, evite em servidores embora seja possivel, passo a passo em

http://www.zago.eti.br/boot_div.txt

Dual boot Linux e windows - Aproveite e veja a dica sobre backup da instalação completa do windows na partição Linux, quando algum virus comer o windows ou precisar reinstalar, vai poupar muito tempo, basta uma simples cópia de volta para recuperar a instalação do windows, passo a passo em.

http://www.zago.eti.br/boot-dual-win-e-linux.html

Nesta estação (instalação) de testes, vai consumir somente parte do espaço do HD e nada mais, utilizando maquina que está atrás de firewall vai complicar um pouco, para não mexer na configuração atual, procure seguir uma destas opções.

A - instalar um modem discado nesta maquina de testes, lembrando que as regras de iptables são mesmas para modem discado e ADSL conectado via rp-pppoe, a única diferença pode ocorrer no device, algumas conexões utilizam o device diferente, como eth0, wlan0 ou outro, as regras são as mesmas, ajuste o device utilizado, modem discado utiliza "ppp0".

Nada de hardmodem ou sofisticação, pra testes pode utilizar aqueles modem on-board que já vem de brinde em algumas maquinas, atende muito bem, pode ser um AMR PCtel, instala facilmente na maioria das distros, complica um pouco com atualização do kernel mas tem solução, não precisa de placa de rede adicional, a única diferença fica por conta do device e lentidão.

Prontinho, com este micro conectado na net, use uma estação conectada a ele, pode usar um cabo crossover para trabalhar totalmente isolado das demais maquinas.

Pode até ser usado quando cai o link ou ADSL, embora muito mais lento permite acesso à internet enquanto o ADSL não volta.

Daqui pra frente só depende da sua criatividade para explorar as duas redes, porque não usar mais duas maquinas para criar mais uma conexão para testes com VPN, outros serviços de rede, outras distros ou novas versões, só depende de ti!.

B - Quem pode fazer os testes fora do horario de expediente ou quando a internet não está em uso, nestes casos considere duas ou mais instalações do Linux no mesmo HD ou usar outro HD na maquina, isto permite todo tipo de teste sem comprometer a instalação que funciona, quando terminar os testes, volta facilmente ao estado que era antes.

C - Utilizando estação com dual-boot e duas placas de rede, quando o cabo do modem não alcaça a maquina de testes, para não levar o micro até o local do modem, ou para não levar o modem até o local do micro, faça um cabo de rede para ligar o ADSL a este micro de testes, normalmente é um cabo crossover, utilize emendas RJ45 ou cabo especifico e do tamanho necessário, lembre que isto deve fazer parte do seu kit de sobrevivencia, utilize também para testes de atualização dos pacotes e outros fins, considere manter como backup do firewall, qualquer problema com a maquina principal, basta trocar o cabo de micro.

Existem outras opções, os exemplos acima servem como base para pensar no assunto, observe o que tem à sua volta, seja criativo e mãos à obra.

Lembre que não precisa repetir todo o processo na maquina principal, simplesmente faça copia do script e arquivos de configuração.

Considere manter esta instalação como backup, em casos de emergencia, nunca se sabe quando vai ocorrer acidentes, queimar a maquina, HD ou uma pane na configuração que pare tudo, nestas situações basta alterar o IP que as estações nem ficam sabendo da troca, em menos de um minuto se faz a troca do IP e sobe a segunda maquina do firewall.

Porque não pensei nisso antes!

Resumo - Dicas - Comandos de uso frequente...

Salvar regras em arquivo; iptables-save > meufire.txt

Carregar configurações que salvou com iptables-save > meufire.txt use iptables-restore <>

Listar no console as regras em uso; iptables -L

Salvar em arquivo; iptables -L > listmeufire.txt

Configuração via ambiente gráfico e remotamente

webmin tem modulo especifico sobre iptables/firewall e outros recursos..., Veja mais sobre webmin, como acessar remotamente e outras dicas em

http://www.zago.eti.br/webmin.txt

SSH - Considere o uso do ssh, permite executar aplicativos do ambiente gráfico remoto, tem varios aplicativos para windows, tanto em ambiente gráfico como texto (shell) é a mais segura e melhor ferramenta para acesso remoto, altamente configurável.

Acesso remoto via ssh em ambiente gráfico, cliente windows utilizando - Winscp - putty - Freenx - tutorial em

http://www.zago.eti.br/ssh/ssh-gui.html

FAQ, instalar, configurar, dicas e exemplos de uso do SSH em

http://www.zago.eti.br/ssh/ssh.html

http://www.zago.eti.br/ssh/ssh.txt

Edição de script, utilize editores simples, no shell local ou em conexões remotas via ssh, utilize o editor "vi" ou "mc", veja dicas sobre eles em.

http://www.zago.eti.br/vi.txt

http://www.zago.eti.br/mc.txt

Arquivos de configuração podem ser editados e manipulados com simples editor de texto, seja para fazer toda a configuração ou simples ajustes, pode utilizar ferramentas como webmin e refinar os ajustes com seu editor de texto preferido, pode copiar estes arquivos de outra instalação, portanto fique à vontade para fazer a seu modo, veja mais dicas de como manipular arquivos de configuração em

http://www.zago.eti.br/modelos/A-menu-modelos.html

Iniciar, parar, reiniciar, status

Comandos úteis

Onde ficam as regras de iptables

Em scripts precisa informar o caminho completo para chamar o Iptables. Dependendo da distro ou versão, pode estar em locais diferentes, utilize o comando whereis para localizer, exemplo.

  [zago@aula zago]$ whereis iptables
iptables: /usr/sbin/iptables

COMO INICIAR (CARREGAR) O MODULO IPTABLES? Coloque no inicio do script o comando correspondente a cada modulo, carregue somente os modulos necessários.

Como fazer NAT (compartilhar internet) modprobe iptable_nat

INSTALAR: qualquer regra de firewall que utilize Iptables requer a instalação do modulo ou compilar o kernel com ele embutido, prefira trabalhar com modulos, este procedimento é adotado pela maioria das distros.

Dependendo do perfil de instalação, pode incluir o não este modulo, use as ferramentas de sua distro para conferir se já está instaladou ou instalar quando for o caso.

Alguns exemplos via linha de comando, precisa tornar root no console para instalar pacotes;

Instalar via apt-get apt-get install iptables

Via smart. smart install iptables

Via Synaptic, procure, selecione e instale o pacote iptables.

Via rpm a partir do diretório onde salvou ou download ou montou o CD, rpm -ivh iptables-versão.rpm --replacepkgs

Como ver se está instalado? Use a ferramenta de sua distro, exemplo no CL9, via synaptic procure pelo pacote iptables ou via rpm, exemplo:

# rpm -qa | grep iptables iptables-1.2.7a-26694cl

ajuda: iptables -h

Iptables não foi iniciado, execute antes o comando ou inclua no rc.local:

modprobe ip_tables

modulos e ajuda

IPtables pode ser compilado com diversas bibliotecas.

Precisa carregar o modulo antes da regra que o utiliza, o local pode ser diferente conforme a distro, no SUSE 10.1 procure em /sys/module/, tente filtrar os modulos sobre iptables com ls -la /sys/module/ip*

Quando falhar o comando, procure identificar se foi compilado com a biblioteca ou terá que compilar seu iptables novamente.

Copia de parte de um firewall, (carregar modulos)

  ##### carregar modulos
/sbin/modprobe iptable_nat
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_conntrack_ftp
/sbin/modprobe ip_nat_ftp
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_REJECT
/sbin/modprobe ipt_MASQUERADE

Obter ajuda sobre opções do iptables,

iptables -h

iptables --help

ajuda sobre mac

iptables -m mac --help

log do iptables

Para registrar as ocorrencias em log precisa carregar o ipt_LOG, no inicio do firewall ou antes de regra acrescente.

/sbin/modprobe ipt_LOG

Exemplo de uma regra para registrar log de todos acessos na porta 80, identificar o registro com "FIREWALL: http: ".

  $iptables -A INPUT -p tcp --dport 80 -i $EXTERNA -j LOG --log-level 6 --log-prefix "FIREWALL: http: "

Esta regra registra as ocorrencias em /var/log/firewall, cada acesso tem um registro neste formato.

  Jun 15 19:20:15 linux-speedy kernel: FIREWALL: http: IN=eth0 OUT= MAC=00:02:e3:0f:0b:26:00:04:16:00:c0:54:08:00 SRC=201.68.202.124 DST=200.204.198.164 LEN=44 TOS=0x00 PREC=0x00 TTL=252 ID=2 PROTO=TCP SPT=33049 DPT=80 WINDOW=7957 RES=0x00 SYN URGP=0

Use tail ou outra ferramenta para acompanhamento ou filtro.

veja os resultados de:

iptables -t filter -L INPUT

iptables -L INPUT -n

Dicas sobre log do sistema.

http://www.zago.eti.br/log.html

Como fazer um script (firewall) com regras de iptables

Tem sites que auxiliam na criação de script, segue algumas indicações.

Iptables script generator

http://www.linuxit.com.br/modules.php?name=Tux_BR_Iptables

Algumas dicas.

Em testes as regras podem ser executadas na linha de comando, mas isto tem um incoveniente, toda vez que reinicar a maquina as regras se perdem, o ideal e executa-las junto com o boot da maquina.

Quando for poucas regras pode acrescenta-las no final do script de inicialização, no CL é o rc.local que fica em /etc/rc.d/rc.local, este local muda conforme a distro, veja o local correto em sua instalação.

A maneira mais elegante é criar um script com as regras de firewall, torne-o executavel e acrescente no final de /etc/rc.d/rc.local, uma linha para executar o script junto com boot da maquina, exemplo para executar o script com nome iptfirewall.sh que está no sub-diretório /etc/rc.d, basta acrescentar no final de rc.local, esta linha:

/etc/rc.d/iptfirewall.sh

Como criar script, dicas, exemplos e documentação.

http://www.zago.eti.br/script/A-menu-scripts.html

Modelo 1 - compartilhar internet sem firewall

Este topico (MODELO 1) não é um firewall, são somente regras pra compartilhar uma conexão, ideal em testes de instalação e solução de problemas quando suspeitar de regras do firewall, com estas regras a maquina fica totalmente vulneravel a invasão, veja neste documento outros modelos com indicação da segurança.

Compartilhar uma conexão de internet para os demais micros da rede, precisa no minimo destas regras:

      modprobe iptable_nat
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

Explicando:

A primeira linha carrega o modulo pra fazer NAT. A segunda linha faz o mascaramento a tercera linha ativa o IP forward, repasse de pacote pras demais maquinas da rede interna, veja mais exemplos abaixo.

Conexão via modem discado ou ADSL com IP dinamico que requer rp-pppoe, nestas conexões a interface é ppp0, segue o exemplo com ppp0

      modprobe iptable_nat
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

Conexão via ADSL com IP fixo e outras conexões que utiliza a interface eth0.

      modprobe iptable_nat
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

A diferença entre as duas regras acima é a interface de saida pra internet, eth0 ou ppp0

Existem outras regras e maneiras, nos proximos exemplos tem mais exemplos sobre uso da regra com NAT.

a tercera linha ativa o IP forward, repasse de pacotes para as demais maquinas da rede interna.

Outras maneiras de ativar o mesmo serviço (acionar o IP forwarding).

alterar em /etc/sysctl.conf, de

net.ipv4.ip_forward = 0

para

net.ipv4.ip_forward = 1

Ou altere em /etc/sysconfig/network, de

# FORWARD_IPV4=no # not used anymore. see /etc/sysctl.conf

para

FORWARD_IPv4="yes"

Lembre que somente uma deverá ser utilizada, prefiro acrescentar no escript esta regra:

echo 1 > /proc/sys/net/ipv4/ip_forward

e não utilizo as outras mencionadas acima.

Conferir se repasse está habilidade (forward), execute:

cat /proc/sys/net/ipv4/ip_forward

Exemplo de comando e o que retorna quando habilitado.

  [zago@faq zago]$ cat /proc/sys/net/ipv4/ip_forward
1

Retornando 1 está habilitado, retornando zero não está habilitado, caso tenha dado o comando para fazer forward e no resultado acima está retornando 1, então tem algum erro, provavel erro de digitação.

regras do mascaramento cat /proc/net/ip_masquerade

ver as regras do iptables iptables --list -n -v

iptables --list

iptables -L

Regra para barrar um IP especifico acrescente a linha abaixo em seu script depois do ip_forward:

/usr/bin/iptables A -OUTPUT -p tcp -s IPBLOQUEADO -j DROP

Redirecionamento - regras por porta, IP e etc..

Existem diversas opções e regras para redirecionar um pedido que chega da internet para chegar a uma estação ou servidor que estão atrás do firewall. Segue alguns exemplos;
Redirecionar ssh, tudo que chega na porta 22 (usada pelo ssh) redirecionar para a estação com IP 192.168.1.53 $iptables -t nat -A PREROUTING -p tcp -s 0/0 --dport 22 -i eth0 -j DNAT --to 192.168.1.53:22
Onde:

eth0 = placa de rede de cara pra net, ajuste na sua instalação

22 é a porta que quero redicionar pra outra maquina (22 é a porta default utilizada nas conexões por ssh), pode ser alterada.

192.168.1.53 é o IP reservado da maquina interna que vai atender a conexão.
Na maquina remota (internet) a conexão é disparada para o IP do firewall, a regra acima redireciona para a estação, um exemplo de linha de comando para conexão via ssh; ssh user@IP, ou ssh zago@200.200.200.200, quando este pedido chega no Firewall com IP 200.200.200.200 é automaticamente redirecionado para a estação com IP 192.168.1.53 que atenderá o pedido e completará a conexão. $iptables -t nat -A PREROUTING -p tcp -s 0/0 --dport 22 -i eth0 -j DNAT --to 192.168.1.53:22 Outra opção, usar porta diferente no cliente, assim pode redirecionar cada porta para estações especificas, também pode redirecionar com troca de porta, neste exemplo a 2222 será redirecionada para 22, nesta regra vai redirecionar para a estação, somente os pedidos que chegam na porta 2222, os demais pedidos na porta 22 ou outra qualquer serão tratados por outras regras. $iptables -t nat -A PREROUTING -p tcp -s 0/0 --dport 2222 -i eth0 -j DNAT --to 192.168.1.53:22 Pode configurar o ssh para ouvir em outra porta, ou até mesmo manter a default, neste exemplo foram mantidas, tanto o firewall como estação estão ouvindo na porta 22, o uso da porta 2222 foi utilizando somente na linha de comando e na regra de iptables, a regra de redirecionamento funciona somente para os pedidos que chegam na porta 2222, a linha de comando na internet tem que indicar a porta, exemplo; ssh -p 2222 zago@200.200.200.200 o (-p 2222) serve para indicar a porta, os pedidos que chegarem na porta 22 seguem outras regras, pode ser redirecionada para outra maquina ou atendida pela própria maquina do firewall. Restringindo o redirecionamento somente a determinado IP, permitindo que somente conexões com origem no IP 200.204.198.164 sejam redirecionadas para a estação, qualquer conexão com origem em IP diferente não serão redirecionadas, exemplo da regra; $iptables -t nat -A PREROUTING -p tcp -s 200.204.198.164 --dport 2222 -i eth0 -j DNAT --to 192.168.1.3:22 Como pode notar, são varias opções, nem todos os serviços permitem a troca da porta, alguns requer regras mais complexas, mas sempre tem meios de dificultar o acesso de estranhos, mesmo sobre ssh tem muito mais. Somente voce sabe o que tem a proteger, portanto implemente as medidas de segurança, a finalidade aqui é dicas sobre redirecionamento, sobre segurança e outras dicas, continue pesquisando.... Para facilitar a organização por assunto, algumas regras estão no FAQ especifico sobre o pacote ou serviço, como exemplo, as regras de redirecionamento sobre VNC estão no FAQ sobre VNC, Bittorrent idem, consulte o tutorial ou FAQ especifico. Veja algumas indicações abaixo.
FAQ com mensagens da Linux-br

http://www.zago.eti.br/firewall/redirecionamento.txt

VNC - redirecionar pedidos que chegam da internet para estação atras de firewall

http://www.zago.eti.br/vnc.txt

Bittorrent - regras para habilitar acessarem à rede

http://www.zago.eti.br/bittorrent.html

Indicações...

Documentation about the netfilter/iptables project

Tem alguns documentos em Português.

http://www.netfilter.org/documentation/

L7-filter - classifica pacotes como Kazaa, HTTP, Jabber, Citrix, Bittorrent, FTP, Gnucleus, eDonkey2000, etc., identifica e permite criar regras de firewall, veja mais em;

http://l7-filter.sourceforge.net/

Excelente tutorial, vale a pena consultar - (em Inglês)

http://iptables-tutorial.frozentux.net/iptables-tutorial.html

Página principal sobre iptables e firewall.

http://www.zago.eti.br/A-menu-firewall.html

Acesso aos FAQ montado com seleção de respostas esclarecedoras na lista Linux-br.

http://www.zago.eti.br/firewall/

Pááina principal deste site (FAQ)

http://www.zago.eti.br/menu.html

INTEGRANDO O SAMBA E SQUID COM O ACTIVE DIRECTORY USANDO O KERBEROS E WINBIND

PREPARAÇÃO PARA O AMBIENTE

Será necessário um servidor Windows 2000 ou 2003 atuando como Domain Controller e um servidor Linux para Proxy.

Neste caso específico, o servidor Linux está rodando Debian Etch e ou CentOS 4, mas o tutorial também pode ser utilizado com outras versões de Linux. yt


Obs.: É obrigatório que exista um SERVIDOR WINS na REDE!

Vamos instalar as dependências para dar seqüência ao tutorial:

Primeiro, edite o arquivo /etc/hosts colocando o nome e o ip do seu Domain Controller:

# vi /etc/hosts

10.100.0.165 nelinho-sp.com.br nelinho-sp

10.100.0.165 server01. nelinho-sp.com.br server01

127.0.0.1 localhost.localdomain localhost prx


Em seguida, vamos instalar o NTPDATE para efetuar o sincronismo de horário entre o

Servidor Linux e um NTP Server:

# apt-get install ntpdate


Instalação do Kerberos

- Kerberos p/ Linux (Debia Sarge e Etch)

# apt-get install krb5-kdc krb5-config krb5-clients libpam-krb5 krb5-user


  • Kerberos p/ Linux Centos 4 e 5

#yum install krb5-libs

#yum install krb5-workstation

#yum install krb5-server


Após a instalação edite o arquivo krb5.conf:

#vi /etc/krb5.conf


[libdefaults]

ticket_lifetime = 24000

default_realm = NELINHO-SP.COM.BR

dns_lookup_realm = false

dns_lookup_kdc = false


[realms]

NELINHO-SP.COM.BR = {

kdc = 10.100.0.165

admin_server = 10.100.0.165:749

default_domain = 10.100.0.165

}

[domain_realm]

.nelinho-sp.com.br = NELINHO-SP.COM.BR

nelinho-sp.com.br = NELINHO-SP.COM.BR

[login]

krb4_convert = true

krb4_get_tickets = false

[logging]

kdc = FILE:/var/log/krb5kdc.log

admin_server = FILE:/var/log/kadmin.log

default = FILE:/var/log/krb5lib.log


Salve e feche.


Vamos editar alguns dos arquivos de configuração e efetuar a comunicação entre o Proxy e o Domain Controller via Kerberos.

Primeiro, é necessário que o horário do servidor Linux e do Servidor Windows estejam sincronizados. Para isto, iremos utilizar um servidor NTP, seguindo os seguintes passos:

- Servidor Linux

# ntpdate ntp.cais.rnp.br


- Servidor Windows

C:\Winnt> net time /setsntp:ntp.cais.rnp.br

C:\Winnt> net stop w32time & net start w32time


Em seguida, vamos iniciar a comunicação entre o Linux e o Domain Controller utilizando Kerberos. (Lembrando que o domínio utilizado neste tutorial chama NELINHO-SP.COM.BR)

# kinit administrator@NELINHO-SP.COM.BR


Será solicitada a senha do usuário “administrator”. Se tudo correu bem, você irá rodar o comando “klist” e o retorno será semelhante ao que obtivemos, conforme abaixo:

# kinit administrator@LAB.VIRTUAL

Password for administrator@LAB.VIRTUAL:

# klist

Ticket cache: FILE:/tmp/krb5cc_0

Default principal: administrator@LAB.VIRTUAL

Valid starting Expires Service principal

02/22/07 14:25:47 02/23/07 00:25:47 krbtgt/LAB.VIRTUAL@LAB.VIRTUAL

Kerberos 4 ticket cache: /tmp/tkt0

klist: You have no tickets cached


Se a saída do comando for diferente do apresentado acima, verifique:

  • Se não há erro no arquivo krb5.conf

  • Se o horário não está sincronizado entre as máquinas;

  • Se a senha do administrador foi alterada.


Vamos instalar o winbind:

#apt-get install winbind


Em seguida, vamos editar o arquivo nsswitch.conf

# vi /etc/nsswitch.conf

E alterar as linhas:

DE:

passwd: compat

group: compat

PARA:

passwd: compat winbind

group: compat winbind


Obs.: NÃO INICIE O WINBIND


Vamos instalar o samba no Debian Sarge ou Etch:

#apt-get install samba samba-common


Vamos instalar o samba no CentOS 4 ou 5:

#yum install samba


Edite o arquivo smb.conf:

#vi /etc/samba/smb.conf


[global]

workgroup = nelinho-sp

server string = squid server

netbios name = dvto2

log level = 2

log file = /var/log/samba/%m.log

max log size = 50

security = ads

password server = 10.100.0.165

encrypt passwords = true

socket options = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192

winbind uid = 10000-20000

winbind gid = 10000-20000

winbind enum users = yes

winbind enum groups = yes

template homedir = /dev/null

template shell= /dev/null

winbind use default domain = yes

interfaces = 10.100.0.0/16

bind interfaces only = yes

realm = nelinho-sp.com.br


#======= Share Definitions=========


[homes]

comment = Home Directories

browseable = no

writable = yes

valid users = %S

create mode = 0664

directory mode = 0775


[printers]

comment = All Printers

path = /var/spool/samba

browseable = yes

guest ok = yes

writable = no

printable = yes


Obs: ANTES DE INICIAR O SAMBA DEVEMOS INGRESSAR O SAMBA NO DOMÍNIO. ANTES DE INGRESSAR FAÇA AS SEGUINTES VERIFICAÇÕES:

  • VERIFIQUE SE O ARQUIVO /etc/samba/secrets.tdb FOI CRIADO, SE SIM APAGUE-O. ESTE ARQUIVO PRECISA SER EXCLUIDO PORQUE ELE GUARDA AS CONFIGURAÇÕES DE DOMÍNIOS ANTERIORES.

  • VERIFIQUE NA MÁQUINA WINDOWS SE A MÁQUINA SAMBA JÁ ESTÁ INGRESSADA, SE SIM EXCLUA.


Para incluir a máquina no domínio execute:

#net ads join -Uadministrator%password [senha do administrador]


Se a máquina ingressou com sucesso uma mensagem de sucesso vai aparecer, um novo arquivo secrets.tdb vai ser criado e a máquina vai aparecer no AD.

Inicie o samba e o winbind:

#/etc/init.d/smb start

#/etc/init.d/winbind start


DETALHES QUE DEVEM SER LEVADOS EM CONSIDERAÇÃO


Na máquina windows o domínio nelinho-sp.com.br deve ser pingado e a resposta deve ser algo como:

ping nelinho-sp.com.br

PING nelinho-sp.com.br (10.100.0.165) 56(84) bytes of data.

64 bytes from nelinho-sp.com.br (10.100.0.165): icmp_seq=0 ttl=128 time=1.59 ms

64 bytes from nelinho-sp.com.br (10.100.0.165): icmp_seq=1 ttl=128 time=0.680 ms

64 bytes from nelinho-sp.com.br (10.100.0.165): icmp_seq=2 ttl=128 time=0.825 ms


--- nelinho-sp.com.br ping statistics ---

3 packets transmitted, 3 received, 0% packet loss, time 2001ms

rtt min/avg/max/mdev = 0.680/1.032/1.592/0.401 ms, pipe 2


Se não pinga o mesmo não está resolvendo nomes. Verifique o DNS se está como autoritarivo (se o dns que estiver apontado está instalado na mesma máquina do AD). A resolução de nomes é importante para o funcionamento do AD com a integração.


CONFIGURANDO O SQUID PARA AUTENTICAR VIA NTLM


A versão instalada para os devidos funcionamentos foi a 2.5.

- Efetuando backup do arquivo de configuração original

# cd /etc/squid

# mv squid.conf squid.original

- Limpando todas as linhas comentadas do squid.original e gerando o squid.conf

# egrep -v "^#|^$" squid.original > squid.conf


Editando o arquivo squid.conf e colocando as linhas abaixo (As linhas em vermelho são as linhas utilizadas pela autenticação NTLM:

# vi /etc/squid/squid.conf


http_port 3128

cache_effective_user squid

cache_effective_group squid

cache_log /var/log/squid/cache.log

cache_access_log /var/log/squid/access.log

cache_store_log /var/log/squid/store.log

hierarchy_stoplist cgi-bin ?

acl QUERY urlpath_regex cgi-bin \?

no_cache deny QUERY

auth_param ntlm program /usr/bin/ntlm_auth -d NELINHO-SP --helper-protocol=squid-2.5-ntlmssp

auth_param ntlm use_ntlm_negotiate off

auth_param ntlm children 10

auth_param ntlm max_challenge_reuses 0

auth_param ntlm max_challenge_lifetime 5 minutes

auth_param basic program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-basic

auth_param basic children 5

auth_param basic realm Digite o LOGIN/SENHA

auth_param basic credentialsttl 2 hours

auth_param basic casesensitive off

refresh_pattern ^ftp: 1440 20% 10080

refresh_pattern ^gopher: 1440 0% 1440

refresh_pattern . 0 20% 4320

acl all src 192.168.88.0/255.255.255.0

acl manager proto cache_object

acl localhost src 127.0.0.1/255.255.255.255

acl to_localhost dst 127.0.0.0/8

acl SSL_ports port 443 563

acl Safe_ports port 80 # http

acl Safe_ports port 21 # ftp

acl Safe_ports port 443 563 # https, snews

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

acl acesso proxy_auth REQUIRED # Solicitando a autenticação

http_access allow manager localhost

http_access deny manager

http_access deny !Safe_ports

http_access deny CONNECT !SSL_ports

http_access allow acesso # Liberando usuários autenticados

http_access allow all

http_reply_access allow all

icp_access allow all

coredump_dir /usr/local/squid/var/cache

Criando o cache e iniciando o squid.

# squid -z


Para utilizar as regras baseadas em Grupos do Active Directory, utilize as seguintes linhas no seu squid.conf:


external_acl_type nt_group %LOGIN /usr/lib/squid/wbinfo_group.pl

acl AllowedWindowsGroups external nt_group GrupodoAD

http_access allow AllowedWindowsGroups


Depois de editar o seu squid.conf, não esqueça de recarregá-lo:

# squid –k reconfigure


Para verificar se a autenticação ntlm_auth está funcionando execute:

#/usr/bin/ntlm_auth --domain=nelinho-sp.com.br –username=[informe o login do AD]

Password:[digite a senha]

NT_STATUS_OK: Success (0x0)

Se a informação acima aparecer quer dizer que o usuário está autenticando, caso contrário não. Se aparecer a mensagem abaixo, a senha está errada:

NT_STATUS_WRONG_PASSWORD: Wrong Password (0xc000006a)


ANALISES DE ERROS E SOLUÇÕES

Para analisar se o squid vai iniciar com algum erro, execute ele em modo de debug:

#squid -d 2


ERROS

winbind client not authorized to use winbindd_pam_auth_crap Ensure permissions on /var/lib/samba/winbindd_privileged are set correctly – Este erro aparece quando a permissão de grupo para a pasta winbindd_privileged não está o grupo squid. Execute:

#chgrp chgrp proxy winbindd_privileged

#chmod 750 winbindd_privileged


REFERÊNCIA BIBLIOGRÁFICA

KANETO, Guilherme. Autenticando o Squid no Active Directory via NTLM. Data 09/06/2007.

MELO, Sandro. BS7799, da Tática a Prática em Servidores Linux. Alta Books.

FAHDAZIZ. Configuring Samba 3.0 To Use The ADS Security Mode (CentOS). Endereço Eletrônico: http://www.howtoforge.com/samba_ads_security_mode. Data: 10/12/2007.