Admirável Mundo Novo: Tudo Sobre Asterisk, OpenSER, Linux e Tecnologias de Voz sobre IP: janeiro 2009




Muito Bem Vindo

Prezado Leitor, a proposta desse Blog é compartilhar conhecimento com as pessoas que trabalham com Linux, Asterisk, OpenSER, e com tecnologia de voz sobre a rede IP em geral, através de tutoriais, dicas, howto, notícias entre outros assuntos.

Atente para termo de uso do conteúdo do blog no rodapé da página.

quarta-feira, 21 de janeiro de 2009

Livro de Receitas




Capítulo 15 – Receitas de Bolo

Essa seção contém entradas de ‘receitas de bolo’ que podem lhe ajudar a resolver problemas. Um livro de receita de bolo, contudo, não substitui o conhecimento, portanto tente e compreenda o que você está fazendo.


15.1. Rodando múltiplos sites com diferentes SLAs

Você pode fazer isso de várias formas. O Apache possui algum suporte para isso com um módulo, mas nós mostraremos como o Linux pode fazer isso pra você, e assim faz para outros serviços também. Esses comandos são roubados de uma apresentação do Jamal Hadi que é referenciado abaixo.

Digamos que nós temos dois clientes, com http, ftp e streaming de áudio, e desejamos vendê-los uma quantidade limitada de banda. Nós executamos, portanto, no servidor em si.

O cliente A deve ter no máximo 2 Megabits, o cliente B tem pago por 5 Megabits. Nós separamos nossos clientes criando endereços IP virtuais em nosso servidor.

# ip address add 188.177.166.1 dev eth0
# ip address add 188.177.166.2 dev eth0

Isso incumbe você a vincular aos diferentes servidores os endereços IP corretos. Todos os daemons populares têm suporte para isso.


Primeiro nós associamos uma qdisc CBQ a eth0:

# tc qdisc add dev eth0 root handle 1: cbq bandwidth 10Mbit \
cell 8 avpkt 1000 mpu 64


Nós então criamos classes para nossos clientes:

# tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 10Mbit \
rate 2MBit avpkt 1000 prio 5 bounded isolated allot 1514 weight 1 maxburst 21

# tc class add dev eth0 parent 1:0 classid 1:2 cbq bandwidth 10Mbit \
rate 5Mbit avpkt 1000 prio 5 bounded isolated allot 1514 weight 1 maxburst 21


Então adicionamos filtros as nossas duas classes:

##FIXME: Why this line, what does it do?, what is a divisor?:
##FIXME: A divisor has something to do with a hash table, and the number of
## buckets - ahu
# tc filter add dev eth0 parent 1:0 protocol ip prio 5 handle 1: u32 divisor 1
# tc filter add dev eth0 parent 1:0 prio 5 u32 match ip src 188.177.166.1
flowid 1:1
# tc filter add dev eth0 parent 1:0 prio 5 u32 match ip src 188.177.166.2
flowid 1:2


E pronto.

CORRIJAM-ME: por que nenhum filtro token bucket? Existe em algum lugar um pfifo_fast de fallback?


15.2. Protegendo seu host de SYN floods

Da documentação iproute do Alexey, adaptado para o netfilter e com mais caminhos plausíveis. Se você usa isso, cuide de ajustar os números para valores razoáveis para seu sistema.

Se você deseja proteger uma rede inteira, pule esse script, que é mais bem ajustada para um host único.

Parece que você precisa da versão mais recente das ferramentas iproute2 para conseguir que isso funcione com o kernel 2.4.0.

#! /bin/sh -x
#
# sample script on using the ingress capabilities
# this script shows how one can rate limit incoming SYNs
# Useful for TCP-SYN attack protection. You can use
# IPchains to have more powerful additions to the SYN (eg
# in addition the subnet)
#
#path to various utilities;
#change to reflect yours.
#
TC=/sbin/tc
IP=/sbin/ip
IPTABLES=/sbin/iptables
INDEV=eth2
#
# tag all incoming SYN packets through $INDEV as mark value 1
############################################################
$iptables -A PREROUTING -i $INDEV -t mangle -p tcp --syn \
-j MARK --set-mark 1
############################################################
#
# install the ingress qdisc on the ingress interface
############################################################
$TC qdisc add dev $INDEV handle ffff: ingress
############################################################

#
#
# SYN packets are 40 bytes (320 bits) so three SYNs equals
# 960 bits (approximately 1kbit); so we rate limit below
# the incoming SYNs to 3/sec (not very useful really; but
#serves to show the point - JHS
############################################################
$TC filter add dev $INDEV parent ffff: protocol ip prio 50 handle 1 fw \
police rate 1kbit burst 40 mtu 9k drop flowid :1
############################################################

#
echo "---- qdisc parameters Ingress ----------"
$TC qdisc ls dev $INDEV
echo "---- Class parameters Ingress ----------"
$TC class ls dev $INDEV
echo "---- filter parameters Ingress ----------"
$TC filter ls dev $INDEV parent ffff:

#deleting the ingress qdisc
#$TC qdisc del $INDEV ingress


15.3. Limitação de Taxa ICMP pra evitar dDoS

Recentemente, ataques de negação de serviço distribuído tem se tornado uma praga importante. Pela filtragem apropriada e pela limitação da taxa de sua rede, você pode tanto evitar ser uma vitima quanto a origem desses ataques.

Você deve filtrar suas redes de sorte que não permita que pacotes endereçados com IP origem não local deixe sua rede. Isso evita as pessoas de enviar anonimamente lixo para a Internet.

Limitação de taxa parte muito como mostrado antes. Para atualizar sua memória, nosso ASCIIgram novamente:


[The Internet] ---<E3, T3, whatever>--- [Linux router] --- [Office+ISP]
eth1 eth0


Primeiro configuramos as partes pré-requisitos:

# tc qdisc add dev eth0 root handle 10: cbq bandwidth 10Mbit avpkt 1000
# tc class add dev eth0 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate \
10Mbit allot 1514 prio 5 maxburst 20 avpkt 1000


Se você tiver interface 100 Mbit, ou mais, ajuste esses números. Agora você precisa determinar quanto de tráfego ICMP você deseja permitir. Você pode executar medições com o tcpdump, tendo que gravar essas medidas em um arquivo por enquanto, e ver quanto de tráfego ICMP passa em sua rede. Não esqueça de levantar o tamanho dos instantâneos!

Se medidas forem inexeqüíveis, você pode desejar escolher 5% de sua largura de banda disponível. Definamos nossa classe:

# tc class add dev eth0 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate \
100Kbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 250 \
bounded


Isso limita em 100kbit. Agora precisamos de um filtro para atribuir tráfego ICMP a essa classe:

# tc filter add dev eth0 parent 10:0 protocol ip prio 100 u32 match ip \
protocol 1 0xFF flowid 10:100









Autores Originais dos textos:

Bert Hubert (Netherlabs BV)
bert.hubert@netherlabs.nl

Thomas Graf (Autor de Seção)
tgraf@suug.ch

Gregory Maxwell (Autor de Seção)
greg@linuxpower.cx

Remco van Mook (Autor de Seção)
remco@virtu.nl

Martijn van Oosterhout (Autor de Seção)
kleptog@cupid.suninternet.com

Paul B Schroeder (Autor de Seção)
paulsch@us.ibm.com

Jasper Spaans (Autor de Seção)
jasper@spaans.ds9a.nl

Pedro Larroy (Autor de Seção)
piotr@member.fsf.org







Priorizando o Tráfego Interativo




15.4. Priorizando o Tráfego Interativo

Se bastante dados estiverem congestionando seu link, ou se o tráfego estiver ocupando-o um tanto e você está tentando fazer alguma manutenção via TELNET ou SSH, essa manutenção pode não ser tão bem implementada dessa forma. Os outros pacotes estarão bloqueando seu ato de teclar. Não seria uma grande idéia se houvesse uma maneira de seus pacotes interativos escaparem passando na frente do tráfego pesado? O Linux pode fazer isso para você!

Como antes, nós precisamos tratar o tráfego cursando em ambas as direções. Evidentemente, isso funciona melhor se houverem caixas Linux em ambas as pontas do seu link, muito embora outros UNIX´s sejam capazes de executar isso. Consulte seu guru Solaris/BSD local para implementá-lo.

O escalonador padrão pfifo_fast possui 3 (três) diferentes ‘bandas’. O tráfego da banda 0 é transmitido primeiro, após o qual o tráfego na banda 1 e na banda 2 serão considerados. É vital que o nosso tráfego interativo esteja na banda 0!

Nós adaptamos grosseiramente do HOWTO ipchains (logo ficará obsoleto):

Existem quatro bits usados raramente no cabeçalho IP, chamados de bits Type of Service (TOS) – Tipo de Serviço. Eles afetam a forma como os pacotes são tratados; os quatro bits são “Minimum Delay”, “Maximum Throughput”, “Maximum Reliability” e “Minimum Cost”. Somente um desses bits é permito ser configurado. Rob van Nieuwkerk, o autor do código que manipula o campo TOS no ipchains, coloca-o conforme a seguir:

Especialmente o “Minimum Delay” é importante para mim. Eu o ativo como pacotes “interativos” no tráfego sainte do meu roteador (Linux). Eu estou atrás de um link 33k6 sobre modem. O Linux prioriza os pacotes em 3 (três) filas. Dessa forma eu consigo desempenho aceitável do tráfego interativo enquanto fazendo downloads pesados ao mesmo tempo.

O uso mais comum é definir conexões TELNET e de controle FTP como “Minimum Delay” e os dados FTP como “Maximum Throughput”.

# iptables -A PREROUTING -t mangle -p tcp --sport telnet \
-j TOS --set-tos Minimize-Delay

# iptables -A PREROUTING -t mangle -p tcp --sport ftp \
-j TOS --set-tos Minimize-Delay

# iptables -A PREROUTING -t mangle -p tcp --sport ftp-data \
-j TOS --set-tos Maximize-Throughput


Agora, isso somente funciona para os dados saindo do seu servidor TELNET e indo para o seu computador local. O sentido inverso parece ser feito por você, ou seja, TELNET, SSH e Amigos todos definem o campo TOS nos pacotes saintes automaticamente.

Se você tiver uma aplicação que não faz isso; você pode sempre fazê-lo com o netfilter. Execute em sua caixa local:

# iptables -A OUTPUT -t mangle -p tcp --dport telnet \
-j TOS --set-tos Minimize-Delay

# iptables -A OUTPUT -t mangle -p tcp --dport ftp \
-j TOS --set-tos Minimize-Delay

# iptables -A OUTPUT -t mangle -p tcp --dport ftp-data \
-j TOS --set-tos Maximize-Throughput


15.5. Transparente web-caching usando netfilter, iproute2, ipchains e squid

Essa seção foi enviada pelo leitor Ram Narula da Internet for Education (Tailândia).
A técnica regular para se conseguir isso no Linux é provavelmente com o uso do ipchains DEPOIS de fazer a marcação para assegurar que o tráfego (web) “sainte” pela porta 80 seja roteado através do servidor que roda o squid.

Existem três métodos comuns para garantir que o tráfego “sainte” pela porta 80 seja roteado para o servidor rodando o squid e o quarto será introduzido aqui.
Fazendo o roteador gateway executá-lo.

Se você puder dizer a seu roteador gateway para conferir pacotes que estiver saindo pela porta destino seja enviado ap endereço IP do servidor squid.

PORÉM
Isso colocaria carga adicional no roteador e alguns roteadores comerciais podem nem mesmo suportá-lo.

Usando um Switch Camada 4.
Switch´s Camada 4 podem tratar isso sem qualquer problema.

PORÉM
O custo desse equipamento é normalmente muito elevado. Tipicamente Switch camada 4 normalmente custaria mais do que um típico servidor Linux roteador bom.

Usando servidor cache como gateway de rede.
Você pode forçar que TODO tráfego passe pelo servidor de cache.

PORÉM
Isso é totalmente arriscado porque o Squid utiliza bastante potencia de CPU que pode resultar em desempenho lento sobre toda a rede ou o servidor em si pode quebrar e mais ninguém na rede será capaz de acessar a Internet se isso acontecer.


Roteador Linux+NetFilter.
Com o uso do NetFilter uma outra técnica pode ser implementada que é usar o NetFilter para marcar “mark” os pacotes com a porta 80 de destino e usando o iproute2 para rotear os pacotes marcados com “mark” para o servidor Squid.


+---------------+
| Implementação |
+---------------+


Endereços usados

10.0.0.1 naret (Servidor NetFilter)
10.0.0.2 silom (Servidor Squid)
10.0.0.3 donmuang (Roteador conectado à Internet)
10.0.0.4 kaosarn (outro servidor na rede)
10.0.0.5 RAS
10.0.0.0/24 rede principal
10.0.0.0/19 rede total


+------------------+
| Diagrama de Rede |
+------------------+

Internet
|
donmuang
|
+-----------hub/switch---------+
| | | |
naret silom kaosarn RAS etc.


Antes de tudo, faça todo tráfego passar através de naret garantindo que ele seja o gateway padrão exceto para silom. O gateway padrão de silom precisa ser donmuang (10.0.0.3) ou isso criaria loop do tráfego web.

(todos os servidores em minha rede possui o 10.0.0.1 como o gateway padrão que era o antigo endereço IP do roteador donmuang de sorte que eu alterei o endereço IP de donmuang para 10.0.0.3 e colocou o endereço IP 10.0.0.1 para naret)

Silom
-----
- configuração do squid e do ipchains
Configure o servidor Squid em silom, assegure que ele dá suporte a fazer cache/implementa proxy transparente, a porta padrão é usualmente 3128. Assim todo o tráfego para a porta 80 precisa ser redirecionado para a porta 3128 localmente. Isso pode ser feito usando o ipchains com o seguinte:

silom# ipchains -N allow1
silom# ipchains -A allow1 -p TCP -s 10.0.0.0/19 -d 0/0 80 -j REDIRECT 3128
silom# ipchains -I input -j allow1


Ou, no jargão netfilter:

silom# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 \
-j REDIRECT --to-port 3128
(Obs.: você pode ter outras entradas também)


Para mais informações sobre configuração do servidor Squid favor consulte a pagina FAQ do Squid em http://squid.nlanr.net).

Assegure que o encaminhamento IP esteja habilitado nesse servidor e que o gateway padrão para esse servidor seja o roteador donmuang (E NÃO o naret).


Naret
-----
- configuração do iptables e do iproute2
- desabilitar mensagens REDIRECT icmp (se necessário)

1. Pacotes "mark" porta 80 destino com valor 2:

naret# iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 80 \
-j MARK --set-mark 2


2. Instale o iproute2 assim ele roteará pacotes com marcas "mark" 2 para silom:

naret# echo 202 www.out >> /etc/iproute2/rt_tables
naret# ip rule add fwmark 2 table www.out
naret# ip route add default via 10.0.0.2 dev eth0 table www.out
naret# ip route flush cache


Se donmuang e naret estiverem na mesma sub-rede então naret não deve enviar mensagens REDIRECT ICMP. Nesse caso, assim REDIRECT’s icmp precisam ser desabilitado com:

naret# echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects
naret# echo 0 > /proc/sys/net/ipv4/conf/default/send_redirects
naret# echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects


A configuração está completa, verifique a configuração:

Em naret:
naret# iptables -t mangle -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
MARK tcp -- anywhere anywhere tcp dpt:www MARK set 0x2

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

naret# ip rule ls
0: from all lookup local
32765: from all fwmark 2 lookup www.out
32766: from all lookup main
32767: from all lookup default

naret# ip route list table www.out
default via 203.114.224.8 dev eth0

naret# ip route
10.0.0.1 dev eth0 scope link
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.1
127.0.0.0/8 dev lo scope link
default via 10.0.0.3 dev eth0

(assegure que o silom pertença a uma das linhas acima, nesse caso é a linha com 10.0.0.0/24)

+----------+
|- PRONTO -|
+----------+


15.5.1. Diagrama de Fluxo de Tráfego após implementação

+-------------------------------------------------+
| Diagrama de fluxo de tráfego após implementação |
+-------------------------------------------------+

INTERNET
/\
||
\/
+----------------roteador donmuang-----------------+
/\ /\ ||
|| || ||
|| \/ ||
naret silom ||
* tráfego com destino a porta 80 ====>(cache) ||
/\ || ||
|| \/ \/
\\===================================kaosarn, RAS, etc.


Observe que a rede é assimétrica porque existe um passo extra no caminho de saída geral.

Aqui está rodando down para pacotes que atravessam a rede de kaosarn para e da Internet.


Para o tráfego web/http:

kaosarn http request->naret->silom->donmuang->internet
http replies from Internet->donmuang->silom->kaosarn



Para requisições não web/http (por exemplo, telnet):

kaosarn outgoing data->naret->donmuang->internet
incoming data from Internet->donmuang->kaosarn










Autores Originais dos textos:

Bert Hubert (Netherlabs BV)
bert.hubert@netherlabs.nl

Thomas Graf (Autor de Seção)
tgraf@suug.ch

Gregory Maxwell (Autor de Seção)
greg@linuxpower.cx

Remco van Mook (Autor de Seção)
remco@virtu.nl

Martijn van Oosterhout (Autor de Seção)
kleptog@cupid.suninternet.com

Paul B Schroeder (Autor de Seção)
paulsch@us.ibm.com

Jasper Spaans (Autor de Seção)
jasper@spaans.ds9a.nl

Pedro Larroy (Autor de Seção)
piotr@member.fsf.org








Contornando os problemas ‘Path MTU Discovery’ com ajustes por rota MTU




15.6. Contornando os problemas ‘Path MTU Discovery’ com ajustes por rota MTU

Para envio pesado de dados, a Internet geralmente funciona melhor quando usando pacotes grandes. Cada pacote implica em uma decisão de roteamento, quando enviando um arquivo de 1 megabyte; isso tanto pode significar em torno de 700 pacotes quando usando pacotes que são tão longo quanto possível, quanto 4000 se usando o menor padrão possível.

Contudo, nem todas as partes da Internet suportam 1460 bytes completos de payload por pacote. Portanto, é necessário tentar e descobrir o maior pacote que se ‘ajustaria’, a fim de otimizar uma conexão.

Esse processo é chamado ‘Path MTU Discovery’, onde MTU significa ‘Maximum Transfer Unit’, ou seja, Unidade de Transferência Máxima.

Quando um roteador encontra um pacote que é demasiado grande demais em um pedaço, E está sinalizado com o bit “Don´t Fragment” – Não Fragmentar, ele retorna uma mensagem ICMP indicando que foi forçado a descartar um pacote por causa disso. O host que envia reage sobre essa sinalização enviando pacotes menores, e por interação ele pode descobrir o tamanho de pacote ótimo para uma conexão para determinado caminho.

Isso usava para funcionar bem até a Internet ser descoberta pelos hooligans que faz a melhor deles para romper as comunicações. Isso levou os administradores ao seu tempo a tanto bloquear como shapear tráfego ICMP em uma tentativa equivocada para melhorar a segurança ou a robustez dos seus serviços Internet.

O que acontece agora é que o ‘Path MTU Discovery’ está funcionando menos e menos bem e falha em certas rotas, o que conduz a sessões TCP/IP bizarras que morrem após um tempo.

Eu não tenho qualquer evidência disso, apesar de dois sites que eu usei para testar esse problema com dois Alteon Acedirectors antes dos sistemas serem afetados – talvez alguém mais conhecedor possa fornecer pistas a respeito de como isso acontece.


15.6.1. Solução

Quando você encontrar sites que sofrem desse problema, pode desabilitar o ‘Path MTU discovery’ configurando-o manualmente. Koos van den Hout, ligeiramente editou, escreve:

O problema seguinte: Eu definir o mtu/mru da minha linha contratada rodando o ppp a 296 porque ele é somente 33k6 e eu não consigo influenciar o enfileiramento no outro site. A 296, a resposta a um pressionamento de tecla está dentro de um quadro de tempo razoável.

E no meu lado, Eu tenho um masq-router rodando o Linux (claro!).

Recentemente, Eu dividir o ‘server’ e o ‘router’ e assim muitas aplicações estão rodando em uma máquina diferente daquela sobre a qual estava ocorrendo o roteamento.

Eu tive então problemas para entrar no IRC. Grande pânico! Alguns digging descobriram que Eu estava conectado ao IRC, mesmo assim Eu era mostrado como ‘conectado’ no IRC, não recebia a motd do IRC. Eu verifiquei o que poderia ser o problema e observei que Eu já tinha tido alguns problemas anteriores para alcançar certos websites relacionados ao MTU, já que Eu não tinha problemas para alcançá-los quando o MTU era 1500, o problema era exibido justamente quando o MTU era definido como 296. Como os servidores IRC bloqueia quase todo tipo de tráfego não necessário para suas operações imediatas, eles também bloqueia o ICMP.

Eu tratei de convencer os operadores de um webserver que esse era a causa de um problema, porém os operadores do servidor IRC não se preocuparam resolver isso.

Assim, Eu tive de assegurar que o tráfego mascarado sainte partisse com o MTU mais baixo a partir do link externo. Mas Eu desejava que o tráfego Ethernet local tivesse o MTU normal (para o tráfego de aplicações como o NFS).


Solução:

ip route add default via 10.0.0.1 mtu 296
(10.0.0.1 é o endereço do gateway padrão, o endereço interno do roteador que faz masquerade)

Em geral, é possível sobrescrever o ‘PMTU discovery’ configurando rotas especificas. Por exemplo, se somente certa sub-rede está dando problemas, isso deve ajudar:

ip route add 195.96.96.0/24 via 10.0.0.1 mtu 1000


15.7. Contornando os problemas ‘Path MTU Discovery’ com MSS Clamping (para ADSL, cable, usuários PPPoE & PPtP)

Como explicado acima, o ‘Path MTU Discovery’ não funciona ou talvez não mais funcione. Se você souber de um salto em algum ponto de sua rede que possui um MTU limitado (<1500), você não deve confiar que o ‘PMTU Discovery’ possa descobrir isso.

Além do MTU, existe ainda um outro caminho para definir o tamanho máximo de pacote (MPU), o assim chamado Tamanho Máximo de Segmento. Isso é um campo na parte de opções TCP de um pacote SYN.

Os Kernels Linux recentes, e alguns drivers PPPoE (notadamente, aquele excelente Pingüim barulhento), caracteriza a possibilidade de ‘grampear o MSS’.

A coisa boa sobre isso é que definindo o valor MSS, você está dizendo ao lado remoto de maneira inequívoca ‘para tentar de fato enviar-me pacotes maiores do que esse valor’. Nenhum tráfego ICMP é preciso para conseguir fazer isso funcionar.

A coisa ruim é que isso provoca um seccionamento óbvio – ele quebra ‘fim a fim’ modificando pacotes. Dito isso, nós usamos isso dica em muitos lugares e funciona charmosamente.

A fim de fazer isso funcionar você precisa pelo menos do iptables-1.2.1a e do Linux 2.4.3 ou superior. A linha de comando básica é:

# iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu


Isso calcula o MSS apropriado para o seu link. Se você estiver sentindo com coragem, ou acha que você conhece melhor, você pode também fazer algo igual a isso:

# iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 128

Isso define o MSS que permite passar pacotes SYN com 128. Use isso se você tiver VoIP com pacotes diminutos, e pacotes http enormes que possa estar causando picotagem em suas ligações de voz.










Autores Originais dos textos:

Bert Hubert (Netherlabs BV)
bert.hubert@netherlabs.nl

Thomas Graf (Autor de Seção)
tgraf@suug.ch

Gregory Maxwell (Autor de Seção)
greg@linuxpower.cx

Remco van Mook (Autor de Seção)
remco@virtu.nl

Martijn van Oosterhout (Autor de Seção)
kleptog@cupid.suninternet.com

Paul B Schroeder (Autor de Seção)
paulsch@us.ibm.com

Jasper Spaans (Autor de Seção)
jasper@spaans.ds9a.nl

Pedro Larroy (Autor de Seção)
piotr@member.fsf.org








O Moderno Condicionador de Tráfego




15.8. O Mais Moderno Condicionador de Tráfego: Baixa Latência, Velocidade Elevada E Downloads

Obs.: Esse script foi recentemente atualizado e anteriormente somente funcionava em clientes Linux da sua rede! Assim você pode querer atualizar se tiver máquinas Windows ou Macs em sua rede e se observou que elas não foram capazes de fazer download mais rápido enquanto as outras estavam fazendo upload.

Eu tentei inventar a Fábula:

Manter baixa latência para o tráfego interativo todas às vezes.

Isso significa que fazer download ou upload de arquivos não deve perturbar o SSH ou mesmo o TELNET. Essas são as coisas mais importantes; latência de 200ms ainda é ociosidade para a qual trabalhar.

Permitir ‘navegar’ a velocidades razoáveis enquanto faz upload ou download.

Ainda que o tráfego HTTP seja o tráfego ‘massivo’, o outro tráfego não deve torná-lo demasiado imperceptível.

Assegure que os uploads não prejudiquem os downloads, e vice-versa.

Esse é um fenômeno muito observado onde o tráfego outgress simplesmente destrói a velocidade de download.

Elimine tudo aquilo for possível, ao custo de um punhado de largura de banda estreita. A razão que uploads, downloads e SSH se degradarem é a presença de filas grandes em muitos dispositivos de acesso domésticos como modems ADSL e Cable Modems.

A próxima seção explica em profundidade o que causa os atrasos, e como nós podemos resolvê-los. Você pode seguramente saltá-lo e segue diretamente para o script se você não se preocupa como a mágica é executada.


15.8.1. Por que isso não funciona bem por padrão

Os ISPs sabem que eles são avaliados unicamente pela velocidade do serviço no que se refere a rapidez com que as pessoas podem fazer download. Além da largura de banda, velocidade de download é influenciada fortemente pela perda de pacotes, que afeta serialmente o desempenho do TCP/IP. Filas grandes podem ajudar a evitar perdas de pacotes, e a velocidade dos downloads. Por isso que os ISPs configuram filas grandes.

Essas filas grandes, contudo prejudica a interatividade. Um pressionar de tecla precisa antes atravessar a fila de saída, que pode ser longa e ir ao seu host remoto. A tecla então é exibida, que retornou de volta em um pacote, que precisa então atravessar a fila de entrada, localizada em seu ISP, antes dele aparecer em sua tela.

Esse HOWTO lhe ensina como manipular e processar a fila de muitas formas, mas infelizmente, nem todas as filas nos são acessíveis. A fila fora do nosso domínio no ISP é completamente off-limits, enquanto que a fila de subida provavelmente reside em seu dispositivo Cable Modem ou DSL. Você pode ou não ser capaz de configurá-la. Muito provavelmente não poderá configurá-la.

Então, o que isso significa? Como nós não podemos controlar nenhuma daquelas filas, elas precisam ser eliminadas, e movidas para o seu roteador Linux. Felizmente isso é possível.


Limitar a velocidade de upload

Limitando levemente a nossa velocidade de upload menos que a taxa verdadeiramente disponível, nenhuma fila será montada em nosso modem. A fila é agora movida para o Linux.




Limitar a velocidade de download

Isso é ligeiramente mais complicado porque nós não conseguiremos influenciar a Internet a nos enviar dados tanto mais rápido. Podemos descartar pacotes que estão chegando muito rápido, que faz o TCP/IP ficar lento justamente para a taxa que desejamos. Como nós não desejamos descartar tráfego desnecessariamente, dimensionamos uma ‘rajada’ que nós permitiremos nas velocidades mais elevada.



Agora, uma vez que nós tenhamos feito isso, eliminamos a fila de descida totalmente (exceto para rajadas curtas), e ganhamos a capacidade de gerenciar a fila de subida com todo o poderio que o Linux oferece.

O que permanece pra ser feito é assegurar que o tráfego interativo salte na frente da fila de subida. Para garantir que uploads não afetem os downloads, nós também movemos os pacotes ACK para frente da fila. Isso é o que normalmente causa a lentidão enorme observada quando gerando tráfego pesado em ambas as direções. Os ACKnowledgements para tráfego de descida precisa competir com o tráfego de subida, e ser atrasado no processo.

Se fizermos tudo isso nós conseguiremos as seguintes medidas usando uma conexão ADSL excelente a partir da xs4all na Holanda:

Baseline latency:
round-trip min/avg/max = 14.4/17.1/21.7 ms

Without traffic conditioner, while downloading:
round-trip min/avg/max = 560.9/573.6/586.4 ms

Without traffic conditioner, while uploading:
round-trip min/avg/max = 2041.4/2332.1/2427.6 ms

With conditioner, during 220kbit/s upload:
round-trip min/avg/max = 15.7/51.8/79.9 ms

With conditioner, during 850kbit/s download:
round-trip min/avg/max = 20.4/46.9/74.0 ms

When uploading, downloads proceed at ~80% of the available speed. Uploads
at around 90%. Latency then jumps to 850 ms, still figuring out why.

O que você pode esperar desse script depende muito da velocidade real de seu link. Quando fazendo upload a velocidade cheia, sempre haverá um único pacote a frente de seu teclar. Esse é o limite inferior para a latência que você pode conseguir – divida seu MTU por sua velocidade de subida para calcular. Valores típicos serão um tanto mais altos do que esse. Valores inferiores ao seu MTU para efeitos melhores!

Seguindo, está as duas versões desse script, um script com o excelente HTB de Devik, o outro com CBQ que está em cada kernel Linux, diferente do HTB. Ambos são testados e funciona bem.


15.8.2. O script real (CBQ)

Funciona em todos os kernels. Dentro da qdisc CBQ nós colocamos dois SFQ que assegura que múltiplas streams massivas não se afundem.

O tráfego de descida é policiado usando um comando ‘tc filter’ que contem um filtro TBF.

Você pode aperfeiçoar esse script adicionando ‘bounded’ (restrição) a linha que começa com ‘tc class add ... classid 1:20’. Se você baixou seu MTU, também baixe os números allot e avpkt!

#!/bin/bash

# The Ultimate Setup For Your Internet Connection At Home
#
#
# Set the following values to somewhat less than your actual download
# and uplink speed. In kilobits
DOWNLINK=800
UPLINK=220
DEV=ppp0

# clean existing down- and uplink qdiscs, hide errors
tc qdisc del dev $DEV root 2> /dev/null > /dev/null
tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null

###### uplink

# install root CBQ

tc qdisc add dev $DEV root handle 1: cbq avpkt 1000 bandwidth 10mbit

# shape everything at $UPLINK speed - this prevents huge queues in your
# DSL modem which destroy latency:
# main class

tc class add dev $DEV parent 1: classid 1:1 cbq rate ${UPLINK}kbit \
allot 1500 prio 5 bounded isolated

# high prio class 1:10:

tc class add dev $DEV parent 1:1 classid 1:10 cbq rate ${UPLINK}kbit \
allot 1600 prio 1 avpkt 1000

# bulk and default class 1:20 - gets slightly less traffic,
# and a lower priority:

tc class add dev $DEV parent 1:1 classid 1:20 cbq rate $[9*$UPLINK/10]kbit \
allot 1600 prio 2 avpkt 1000

# both get Stochastic Fairness:
tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10

# start filters
# TOS Minimum Delay (ssh, NOT scp) in 1:10:
tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \
match ip tos 0x10 0xff flowid 1:10

# ICMP (ip protocol 1) in the interactive class 1:10 so we
# can do measurements & impress our friends:
tc filter add dev $DEV parent 1:0 protocol ip prio 11 u32 \
match ip protocol 1 0xff flowid 1:10

# To speed up downloads while an upload is going on, put ACK packets in
# the interactive class:

tc filter add dev $DEV parent 1: protocol ip prio 12 u32 \
match ip protocol 6 0xff \
match u8 0x05 0x0f at 0 \
match u16 0x0000 0xffc0 at 2 \
match u8 0x10 0xff at 33 \
flowid 1:10

# rest is 'non-interactive' ie 'bulk' and ends up in 1:20

tc filter add dev $DEV parent 1: protocol ip prio 13 u32 \
match ip dst 0.0.0.0/0 flowid 1:20

########## downlink #############
# slow downloads down to somewhat less than the real speed to prevent
# queuing at our ISP. Tune to see how high you can set it.
# ISPs tend to have *huge* queues to make sure big downloads are fast
#
# attach ingress policer:

tc qdisc add dev $DEV handle ffff: ingress

# filter *everything* to it (0.0.0.0/0), drop everything that's
# coming in too fast:

tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip \
src 0.0.0.0/0 police rate ${DOWNLINK}kbit burst 10k drop flowid :1


Se você desejar que esse script seja executado pelo PPP quando conecta, copie-o para /etc/ppp/ip-up.d.

Se as últimas duas linhas deram algum erro, atualize sua ferramenta tc para uma versão mais recente!


15.8.3. O script Real (HTB)

O script seguinte consegue todos os objetivos usando a maravilhosa fila HTB, veja o capítulo relevante. Vale realmente a pena aplicar patch ao seu kernel!


#!/bin/bash

# The Ultimate Setup For Your Internet Connection At Home
#
#
# Set the following values to somewhat less than your actual download
# and uplink speed. In kilobits
DOWNLINK=800
UPLINK=220
DEV=ppp0

# clean existing down- and uplink qdiscs, hide errors
tc qdisc del dev $DEV root 2> /dev/null > /dev/null
tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null

###### uplink

# install root HTB, point default traffic to 1:20:

tc qdisc add dev $DEV root handle 1: htb default 20

# shape everything at $UPLINK speed - this prevents huge queues in your
# DSL modem which destroy latency:

tc class add dev $DEV parent 1: classid 1:1 htb rate ${UPLINK}kbit burst 6k

# high prio class 1:10:

tc class add dev $DEV parent 1:1 classid 1:10 htb rate ${UPLINK}kbit \
burst 6k prio 1

# bulk & default class 1:20 - gets slightly less traffic,
# and a lower priority:

tc class add dev $DEV parent 1:1 classid 1:20 htb rate $[9*$UPLINK/10]kbit \
burst 6k prio 2

# both get Stochastic Fairness:
tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10

# TOS Minimum Delay (ssh, NOT scp) in 1:10:
tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \
match ip tos 0x10 0xff flowid 1:10

# ICMP (ip protocol 1) in the interactive class 1:10 so we
# can do measurements & impress our friends:
tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \
match ip protocol 1 0xff flowid 1:10

# To speed up downloads while an upload is going on, put ACK packets in
# the interactive class:

tc filter add dev $DEV parent 1: protocol ip prio 10 u32 \
match ip protocol 6 0xff \
match u8 0x05 0x0f at 0 \
match u16 0x0000 0xffc0 at 2 \
match u8 0x10 0xff at 33 \
flowid 1:10

# rest is 'non-interactive' ie 'bulk' and ends up in 1:20


########## downlink #############
# slow downloads down to somewhat less than the real speed to prevent
# queuing at our ISP. Tune to see how high you can set it.
# ISPs tend to have *huge* queues to make sure big downloads are fast
#
# attach ingress policer:

tc qdisc add dev $DEV handle ffff: ingress

# filter *everything* to it (0.0.0.0/0), drop everything that's
# coming in too fast:

tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src \
0.0.0.0/0 police rate ${DOWNLINK}kbit burst 10k drop flowid :1


Se você desejar esse script seja executando pelo PPP quando conecta, copie-o para /etc/ppp/ip-up.d.

Se as últimas duas linhas deram algum erro, atualize sua ferramenta tc para uma versão mais recente!










Autores Originais dos textos:

Bert Hubert (Netherlabs BV)
bert.hubert@netherlabs.nl

Thomas Graf (Autor de Seção)
tgraf@suug.ch

Gregory Maxwell (Autor de Seção)
greg@linuxpower.cx

Remco van Mook (Autor de Seção)
remco@virtu.nl

Martijn van Oosterhout (Autor de Seção)
kleptog@cupid.suninternet.com

Paul B Schroeder (Autor de Seção)
paulsch@us.ibm.com

Jasper Spaans (Autor de Seção)
jasper@spaans.ds9a.nl

Pedro Larroy (Autor de Seção)
piotr@member.fsf.org







Limitando Taxa a único host ou máscara de rede




15.9. Limitando Taxa a único host ou máscara de rede

Embora isso seja descrito em detalhes em outros lugares estupendamente e em nossas manpages, essa questão foi muito perguntada e felizmente existe uma resposta simples que não precisa da compreensão total de controle de tráfego.

Esse script de três linhas dá a pista:

tc qdisc add dev $DEV root handle 1: cbq avpkt 1000 bandwidth 10mbit

tc class add dev $DEV parent 1: classid 1:1 cbq rate 512kbit \
allot 1500 prio 5 bounded isolated

tc filter add dev $DEV parent 1: protocol ip prio 16 u32 \
match ip dst 195.96.96.97 flowid 1:1

A primeira linha instala uma fila baseada em classe em sua interface, e ela diz ao kernel que cálculos, ele supõe que seja uma interface 10mbit. Se você tiver esse problema, nenhum dano real acontecerá. Mas se certifique que esteja fazendo tudo o mais preciso possível.

A segunda linha cria uma classe 512kbit com alguns padrões razoáveis. Para detalhes, veja as manpages CBQ e o Capítulo 9.

A última linha diz qual tráfego deve seguir para a classe shape-ada. O Tráfego que não bateu com essa regra NÃO será shape-ado. Para implementar match´s mais complicados (sub-redes, portas origem, portas destino), veja a Seção 9.6.2.

Se você alterou qualquer coisa e deseja recarregar o script, execute ‘tc qdisc del dev $DEV root’ para limpar sua configuração existente.

O script pode ser melhorado ainda mais adicionando uma linha opcional ao comando ‘tc qdisc add dev $DEV parent 1:1 sfq perturb 10’. Veja a seção 9.2.3 para detalhes a respeito do que disso faz.


15.10. Exemplo de uma solução full nat com QoS

Eu sou o Pedro Larroy . Aqui Eu estarei descrevendo uma instalação comum onde nós temos muitos usuários em uma rede privada conectada a Internet através de um roteador Linux com um endereço IP público que está fazendo NAT. Eu uso essa instalação QoS para permitir a acesso a Internet aos 198 usuários em um dormitório universitário, no qual Eu vivo e da qual eu sou o Administrador da rede. Os usuários daqui fazem uso pesado de programas peer-to-peer, de modo que o controle de tráfego é uma necessidade. Eu espero que isso sirva como um exemplo prático para todos os leitores do LARTC interessados.

Antes de tudo, Eu faço uma abordagem prática com configuração passo a passo, e no final Eu explico como fazer que o processo suba automaticamente no bootime. A rede para a qual esse exemplo se aplica é uma rede LAN privada conectada a Internet através de um roteador Linux que possui um endereço IP público. Estendê-lo a vários endereços IP públicos deve ser muito fácil, um punhado de regras iptables deve ser adicionado. A fim de fazer que as coisas funcionem como nós precisamos:


Versão do kernel Linux 2.4.18 ou superior instalado

Se você usar o 2.4.18, você precisará aplicar patch HTB disponível aqui.



iproute

Também assegure que o binário "tc" esteja com o HTB pronto, um binário pré-compilado é distribuído com o HTB.



iptables



15.10.1. Comecemos otimizando aquela banda escassa

Primeiro nós instalamos algumas qdiscs nas quais classificaremos o tráfego. Nós criamos uma qdisc HTB com 6 classes com prioridade ascendente. Depois temos classes que sempre obterão taxa alocada, mas podemos usar a largura de banda não usada que outras classes não precisarão. Chama novamente essas classes com prioridade mais alta (ou seja, com um número prio mais baixo) que pegarão o excesso de largura de banda alocada inicialmente. Nossa conexão é ADSL com 2Mbits/s de downstream e 300kbits de upstream. Eu uso 240kbit/s como taxa ceil apenas porque é a elevada. Eu posso defini-lo antes que latência comece a crescer, devido ao preenchimento de buffer em qualquer que seja o lugar entre nós e os hosts remotos. Esse parâmetro deve ser ajustado experimentalmente, aumentando e baixando-o enquanto observa a latência entre alguns hosts próximos.

Ajuste o CEIL a 75% de sua banda de upstream limite agora, e onde Eu uso eth0, você deve usar a interface que possui um endereço da Internet pública. Para começar nosso exemplo execute os seguintes passos no shell como root:

CEIL=240
tc qdisc add dev eth0 root handle 1: htb default 15
tc class add dev eth0 parent 1: classid 1:1 htb rate ${CEIL}kbit ceil ${CEIL}kbit
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 80kbit ceil 80kbit prio 0
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 80kbit ceil ${CEIL}kbit prio 1
tc class add dev eth0 parent 1:1 classid 1:12 htb rate 20kbit ceil ${CEIL}kbit prio 2
tc class add dev eth0 parent 1:1 classid 1:13 htb rate 20kbit ceil ${CEIL}kbit prio 2
tc class add dev eth0 parent 1:1 classid 1:14 htb rate 10kbit ceil ${CEIL}kbit prio 3
tc class add dev eth0 parent 1:1 classid 1:15 htb rate 30kbit ceil ${CEIL}kbit prio 3
tc qdisc add dev eth0 parent 1:12 handle 120: sfq perturb 10
tc qdisc add dev eth0 parent 1:13 handle 130: sfq perturb 10
tc qdisc add dev eth0 parent 1:14 handle 140: sfq perturb 10
tc qdisc add dev eth0 parent 1:15 handle 150: sfq perturb 10


Nós apenas criamos uma árvore HTB com um nível de profundidade. Algo parecido com isso:


+---------+
| root 1: |
+---------+
|
+---------------------------------------+
| class 1:1 |
+---------------------------------------+
| | | | | |
+----+ +----+ +----+ +----+ +----+ +----+
|1:10| |1:11| |1:12| |1:13| |1:14| |1:15|
+----+ +----+ +----+ +----+ +----+ +----+



classid 1:10 htb rate 80kbit ceil 80kbit prio 0


Essa é a classe de prioridade mais elevada. Os pacotes nessa classe terão o atraso mais baixo e pegariam o excesso de largura de banda inicial assim é uma boa idéia limitar a taxa ceil para essa classe. Nós enviaremos através dessa classe os seguintes pacotes que se beneficia do baixo atraso como o tráfego interativo: ssh, telnet, dns, quake3, irc, e pacotes com o flag SYN.


classid 1:11 htb rate 80kbit ceil ${CEIL}kbit prio 1


Aqui nós temos a primeira classe na qual podemos começar a colocar tráfego pesado. Em meu exemplo Eu tenho tráfego do servidor web local e requisições por paginas web: porta 80 de origem, e porta 80 de destino respectivamente.


classid 1:12 htb rate 20kbit ceil ${CEIL}kbit prio 2


Nessa classe Eu colocarei o tráfego com o bit TOS marcado como máximo throughput e o resto do tráfego que segue de processos locais no roteador para a Internet. Assim as classes seguintes somente terão o tráfego que é “roteado através” da caixa.


classid 1:13 htb rate 20kbit ceil ${CEIL}kbit prio 2


Essa classe é para o tráfego de outras máquinas NATeadas que precisam de prioridade alta para seus tráfegos pesados.


classid 1:14 htb rate 10kbit ceil ${CEIL}kbit prio 3


Aqui segue o tráfego de email (SMTP, pop3, ...) e pacotes com o bit TOS definido para custo mínimo.


classid 1:15 htb rate 30kbit ceil ${CEIL}kbit prio 3


E finalmente aqui nós temos tráfego pesado das máquinas NATeadas atrás do roteador. Tudo de kazaa, de edonkey, e outros seguirão por aqui, a fim de não interferir com outros serviços.


15.10.2. Classificação de pacotes

Nós criamos a instalação da qdisc, mas nenhuma classificação de pacote foi feita, assim agora todos os pacotes saintes são enviados pela classe 1:15 (porque usamos: tc qdisc add dev eth0 root handle 1: htb default 15). Agora precisamos diz quais pacotes seguirão por esse lugar. Essa é a parte mais importante.

Agora nós definimos os filtros assim nós podemos classificar os pacotes com o iptables. Eu realmente prefiro fazer isso com o iptables, porque eles são mais flexíveis e você tem contagem de pacote para cada regra. Também com a flecha RETURN os pacotes não precisarão atravessar todas as regras. Nós executaremos os seguintes comandos:


tc filter add dev eth0 parent 1:0 protocol ip prio 1 handle 1 fw classid 1:10
tc filter add dev eth0 parent 1:0 protocol ip prio 2 handle 2 fw classid 1:11
tc filter add dev eth0 parent 1:0 protocol ip prio 3 handle 3 fw classid 1:12
tc filter add dev eth0 parent 1:0 protocol ip prio 4 handle 4 fw classid 1:13
tc filter add dev eth0 parent 1:0 protocol ip prio 5 handle 5 fw classid 1:14
tc filter add dev eth0 parent 1:0 protocol ip prio 6 handle 6 fw classid 1:15


Nós apenas dissemos ao kernel que os pacotes que tenham um valor específico FWMARK (handle x fw) entram na classe especificada (classid x:x). Seguindo você verá como marcar pacotes com o iptables.

Primeiro você precisa entender como os pacotes atravessam os filtros com o iptables:


+------------+ +---------+ +-------------+
Packet -| PREROUTING |--- routing-----| FORWARD |-------+-------| POSTROUTING |- Packets
input +------------+ decision +-¬-------+ | +-------------+ out
| |
+-------+ +--------+
| INPUT |---- Local process -| OUTPUT |
+-------+ +--------+


Eu assumi que criou todas as suas tabelas e com o policiamento padrão ACCEPT (-P ACCEPT) se você não tiver batido com o iptables ainda, deve ser OK por padrão. Nossas redes privadas são de uma classe B com endereço 172.17.0.0/16 e o endereço IP público é 212.170.21.172.

Prosseguindo nós instruiremos o kernel para realmente executar NAT, assim os clientes na rede privada podem começar a falar com o mundo externo.


echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s 172.17.0.0/255.255.0.0 -o eth0 -j SNAT \
--to-source 212.170.21.172


Agora verificaremos que os pacotes estão fluindo através de 1:15.


tc -s class show dev eth0


Você pode começar marcando pacotes adicionando regras à chain PREROUTING na tabela mangle.


iptables -t mangle -A PREROUTING -p icmp -j MARK --set-mark 0x1
iptables -t mangle -A PREROUTING -p icmp -j RETURN


Agora você deve ser capaz de ver contagem de pacote aumentando quando fazendo ping de máquinas dentro da rede privada para algum site na Internet. Verifique a contagem de pacote aumentando em 1:10:


tc -s class show dev eth0


Nós temos feito um -j RETURN assim os pacotes não atravessam todas as regras. Pacotes icmp não casarão com outras regras abaixo de RETURN. Tenha isso em mente. Agora podemos começar adicionar mais regras, vamos fazer a manipulação do TOS:


iptables -t mangle -A PREROUTING -m tos --tos Minimize-Delay -j MARK --set-mark 0x1
iptables -t mangle -A PREROUTING -m tos --tos Minimize-Delay -j RETURN
iptables -t mangle -A PREROUTING -m tos --tos Minimize-Cost -j MARK --set-mark 0x5
iptables -t mangle -A PREROUTING -m tos --tos Minimize-Cost -j RETURN
iptables -t mangle -A PREROUTING -m tos --tos Maximize-Throughput -j MARK --set-mark 0x6
iptables -t mangle -A PREROUTING -m tos --tos Maximize-Throughput -j RETURN


Agora prioriza pacotes SSH:

iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 22 -j MARK --set-mark 0x1
iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 22 -j RETURN


Uma idéia boa é priorizar pacotes que começam conexões TCP, aquelas com flag SYN definido:

iptables -t mangle -I PREROUTING -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j MARK --set-mark 0x1
iptables -t mangle -I PREROUTING -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j RETURN


E assim por diante. Quando tivermos adicionado regras a PREROUTING na tabela mangle, nós concluímos a tabela PREROUTING com:

iptables -t mangle -A PREROUTING -j MARK --set-mark 0x6


Assim o tráfego não marcado anteriormente entra na classe 1:15. De fato esse último passo é desnecessário já que a classe padrão era 1:15, mas Eu os marcarei a fim de ficar consistente com todas a instalação, e além do mais é útil ver o contador nessa regra.

Será um idéia boa fazer o mesmo na regra OUTPUT, assim repita aqueles comandos com -A OUTPUT em vez de PREROUTING. Execute o comando egrep (s/PREROUTING/OUTPUT/). Então o tráfego gerado localmente (no roteador Linux) será também classificado. Eu finalizo a chain OUTPUT com -j MARK --set-mark 0x3 de sorte que o tráfego local tenha prioridade mais alta.


15.10.3. Melhorando nossa instalação

Agora temos toda nossa instalação funcionando. Gaste tempo analisando os gráficos, e assistindo onde sua banda é consumida e como você deseja-a. Fazer isso por muitas horas, Eu finalmente conseguir que a conexão Internet funcionasse realmente bem. Do contrário, timeouts contínuos e allotment próximo à zero de banda para conexões TCP criada recentemente ocorrerão.

Se você descobrir que algumas classes ficam cheias na maioria das vezes, seria uma idéia boa anexar uma outra disciplina de enfileiramento a elas de modo que o compartilhamento de banda fique mais justo:

tc qdisc add dev eth0 parent 1:13 handle 130: sfq perturb 10
tc qdisc add dev eth0 parent 1:14 handle 140: sfq perturb 10
tc qdisc add dev eth0 parent 1:15 handle 150: sfq perturb 10


15.10.4. Fazendo tudo subir no boot

Isso pode ser feito de várias maneiras obviamente. Na minha, Eu tenho um script shell em /etc/init.d/packetfilter que aceita [start | stop | stop-tables | start-tables | reload-tables] que configura as qdiscs e que carrega os módulos necessários do kernel, assim ele se comporta muito parecido como um daemon. O mesmo script carrega as regras iptables de /etc/network/iptables-rules que podem ser salvas com o script iptables-save e podem ser recuperadas com iptables-restore.










Autores Originais dos textos:

Bert Hubert (Netherlabs BV)
bert.hubert@netherlabs.nl

Thomas Graf (Autor de Seção)
tgraf@suug.ch

Gregory Maxwell (Autor de Seção)
greg@linuxpower.cx

Remco van Mook (Autor de Seção)
remco@virtu.nl

Martijn van Oosterhout (Autor de Seção)
kleptog@cupid.suninternet.com

Paul B Schroeder (Autor de Seção)
paulsch@us.ibm.com

Jasper Spaans (Autor de Seção)
jasper@spaans.ds9a.nl

Pedro Larroy (Autor de Seção)
piotr@member.fsf.org







terça-feira, 20 de janeiro de 2009

Disciplinas de Enfileiramento Avançadas & Menos Comum




Capítulo 14 – Disciplinas de Enfileiramento Avançadas & Menos Comum

Se você descobrir que você tem necessidades não abarcadas pelas filas mencionadas anteriormente, o kernel possui algumas outras filas mais especializadas que serão mencionadas aqui.


14.1. bfifo/pfifo

Essas filas classless são de fato mais simples do que pfifo_fast em que elas carecem das bandas internas – todo tráfego é realmente igual. Elas têm algum beneficio importante embora, elas possuam algumas estatísticas. Assim mesmo que você não precise shappar ou priorizar, você pode usar essa qdisc para determinar o backlog em sua interface.

O pfifo possui um comprimento medido em pacotes, bfifo em bytes.


14.1.1. Parâmetros & Uso

limit

Especifica o comprimento da fila. Medido em bytes para bfifo, em pacotes para pfifo. É padronizado o txqueuelen da interface (veja o capítulo pfifo_fast) com pacotes longos ou txqueuelen * mtu bytes para bfifo.




14.2. Algoritmo Clark-Shenker-Zhang (CSZ)

Esse é tão teórico que nem mesmo o Alexey (o autor principal do CBQ) se queixou para compreendê-lo. De sua fonte:

David D. Clark, Scott Shenker and Lixia Zhang Supporting Real-Time Applications in an Integrated Services Packet Network: Architecture and Mechanism.

Como eu o entendi, a idéia principal é criar fluxos WFQ para cada serviço garantido e alocar o resto da largura de banda para abstrair o flow-0. O flow-0 engloba os serviços preditivos e o tráfego de melhor esforço; ele é manipulado por um escalonador de prioridade com a banda de prioridade mais alta para serviços preditivos, e o resto – para os pacotes de melhor esforço.

Observe que nos fluxos CSZ NÃO são limitados a sua largura de banda. É suposto que o fluxo passou por controle de admissão na borda da rede com QoS e ele não precisa mais ser shape-adado. Qualquer tentativa para melhorar o fluxo ou para shapê-lo em um balde de fichas em saltos intermediários introduzirá atrasos indesejados e aumentará o jitter.

No momento o CSZ é o único escalonador que fornece serviço garantido verdadeiramente. Nenhum outro esquema (incluindo o CBQ) não fornece nenhuma garantia contra atraso e jitter randômico.

Atualmente não aparece como um bom candidato a usar, a não ser que você tenha lido e entendido o artigo mencionado.


14.3. DSMARK

Esteve Camps
marvin@grn.es


Esse texto é um extrato da minha tese sobre QoS Support in Linux, Setembro de 2000.

Fontes dos documentos:

• Draft-almesberger-wajhak-diffserv-linux-01.txt.
• Examples in iproute2 distribution.
• White Paper-QoS protocols e architectures and IP QoS Frequently Asked
Questions ambos pelo Quality of Service Forum.


Esse capítulo foi escrito por Esteve Camps esteve@hades.udg.es.


14.3.1. Introdução

Antes de tudo, é uma grande idéia você ler as RFC´s escritas sobre esse assunto (RFC2474, RFC2475, RFC2597 e RFC2598) no site web IETF DiffServ working Group e no site web do Werner Almesberger (esse escreveu o código para suportar Serviços Diferenciados no Linux).


14.3.2. Com que Dsmark está relacionado?

O dsmark é uma disciplina de enfileiramento que oferece as capacidades necessárias em Serviços Diferenciados (também chamado DiffServ ou, simplesmente, DS). O DiffServ é um dos duas arquiteturas de QoS atuais (a outra é chamada Serviços Integrados) que é baseada em um valor transportado pelos pacotes no campo DS do cabeçalho IP.

Uma das primeiras soluções em IP projetava oferecer algum nível de QoS era o campo Type of Service (byte TOS) no cabeçalho IP. Alterando esse valor, nós poderíamos escolher um nível alto/baixo de transferência, atraso ou confiabilidade. Mas isso não fornecia flexibilidade suficiente para as necessidades dos novos serviços (como aplicações de tempo real, aplicações interativas, entre outras). Depois disso, novas arquiteturas apareceram. Uma dessas foi o DiffServ que manteve os bits TOS e que renomeou o campo DS.


14.3.3. Orientações para Serviços Diferenciados

Os Serviços Diferenciados é orientado a grupo. Eu quis dizer que não sabemos nada a respeito de fluxos (isso seria a finalidade dos Serviços Integrados); nós sabemos sobre as agregações de fluxo e nós aplicaremos diferentes comportamentos dependendo de qual agregação um pacote pertence.

Quando um pacote chega a um nó de borda (nó de entrada a um domínio DiffServ) entra em um Domínio DiffServ que nós precisaremos policiar, shape-ar e/ou marcar esses pacotes (marcação se refere a atribuir um valor ao campo DS. É justamente igual a ferrar gado ). Essa será a marca/valor que os nó´s internos/núcleo no nosso Domínio DiffServ examinará para determinar qual comportamento ou nível de QoS aplicar.

Como você pode deduzir, os Serviços Diferenciados envolvem um domínio em que todas as regras DS precisarão ser aplicadas. De fato você pode pensar que classificarei todos os pacotes que entram no meu domínio. Uma vez que eles tenham entrado em meu domínio eles ficarão sujeitos as regras que minha classificação ditar e todo nó atravessado aplicará aquele nível de QoS.

De fato, você pode aplicar suas próprias políticas nos seus domínios locais, mas alguns Acordos de Níveis de Serviços (Service Level Agreements) devem ser considerados quando se conectando a outros domínios DS.

Nesse ponto, você talvez tenha um monte de questões. O DiffServ é mais do que eu tenho explicado. De fato, você pode compreender que eu não posso resumir mais do que 3 RFC´s em apenas 50 linhas .


14.3.4. Trabalhando com Dsmark

Como a bibliografia DiffServ especifica, nós diferenciamos nó´s fronteira e nó´s interior. Existem dois pontos importantes no caminho do tráfego. Ambos os tipos executam uma classificação quando os pacotes chegam. Seu resultado pode ser usado em diferentes lugares junto com o processo DS antes que o pacote seja liberado na rede. É justamente por causa disso que o código diffserv fornece uma estrutura chamada sk_buff, que inclui um novo campo chamado skb->tc_index onde armazenaremos o resultado da classificação inicial que pode ser usado em vários pontos no tratamento DS.

O valor do campo skb->tc_index será inicialmente definido pela qdisc DSMARK, que o recupera do campo DS no cabeçalho IP de cada pacote recebido. Além do mais, o classificador cls_tcindex lerá todo ou parte do valor do campo skb->tcindex e usa-o para selecionar classes.

Mas, antes de tudo, examine o comando qdisc DSMARK e seus parâmetros:

... dsmark indices INDICES [ default_index DEFAULT_INDEX ] [ set_tc_index ]



O que significa esses parâmetros?

• indices: tamanho da tabela de pares (mask,value). Valor máximo é 2ˆn, onde n>=0.
• default_index: o índice de entrada da tabela padrão se o classificador não encontrou nenhum match.
• set_tc_index: instrui a disciplina dsmark para recuperar o valor do campo DS e armazená-lo em skb->tc_index.


Vejamos o processo DSMARK.











Autores Originais dos textos:

Bert Hubert (Netherlabs BV)
bert.hubert@netherlabs.nl

Thomas Graf (Autor de Seção)
tgraf@suug.ch

Gregory Maxwell (Autor de Seção)
greg@linuxpower.cx

Remco van Mook (Autor de Seção)
remco@virtu.nl

Martijn van Oosterhout (Autor de Seção)
kleptog@cupid.suninternet.com

Paul B Schroeder (Autor de Seção)
paulsch@us.ibm.com

Jasper Spaans (Autor de Seção)
jasper@spaans.ds9a.nl

Pedro Larroy (Autor de Seção)
piotr@member.fsf.org








Como funciona SCH_DSMARK




14.3.5. Como funciona SCH_DSMARK


Essa qdisc aplicará os passos seguintes:

• Se tivermos declarado a opção set_tc_index no comando qdisc, o valor do campo DS será recuperado e armazenado dentro da variável skb->tc_index.

• O Classificador é invocado. O classificador será executado e retornará um class ID que será estocado na variável skb->tc_index. Se nenhum filtro matches for encontrado, consideramos a opção default_index para determinar o classId a estocar. Se nem set_tc_index e nem default_index foram declaradas os resultados podem ser imprevisível.

• Depois de ter sido enviado as qdiscs internas onde você pode reusar o resultado do filtro, o classid retornado pela qdisc interna é estocado em skb->tc_index. Nós usaremos esse valor no futuro para indexar uma tabela mask-value. O resultado final a atribuir ao pacote será o resultado dessa operação seguinte:
    New_Ds_field = ( Old_DS_field & mask ) | value

• Portanto, novo valor resultará da operação "AND" entre os valores ds_field e mask e prosseguindo, esse resultado é submetido à operação "OR" com o parâmetro value. Veja o diagrama seguinte compreender todo esse processo:


skb->ihp->tos
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >
| | ^
| -- If you declare set_tc_index, we set DS | | <-----May change
| value into skb->tc_index variable | |O DS field
| A| |R
+-|-+ +------+ +---+-+ Internal +-+ +---N|-----|----+
| | | | tc |--->| | |--> . . . -->| | | D| | |
| | |----->|index |--->| | | Qdisc | |---->| v | |
| | | |filter|--->| | | +---------------+ | ---->(mask,value) |
-->| O | +------+ +-|-+--------------^----+ / | (. , .) |
| | | ^ | | | | (. , .) |
| | +----------|---------|----------------|-------|--+ (. , .) |
| | sch_dsmark | | | | |
+-|------------|---------|----------------|-------|------------------+
| | | <- tc_index -> | |
| |(read) | may change | | <--------------Index to the
| | | | | (mask,value)
v | v v | pairs table
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->
skb->tc_index


Como fazer a marcação? Apenas alterando o mask e o value da classe que você deseja remarcar. Veja a próxima linha do código:

tc class change dev eth0 classid 1:1 dsmark mask 0x3 value 0xb8

Isso altera o par (mask,value) na tabela hash, para remarcar pacotes pertencentes a classe 1:1. Você precisa alterar “change” esses valores por causa do valores padrões que o par (mask,value) possuem inicialmente (veja a tabela abaixo).

Agora, explicaremos como o filtro TC_INDEX funciona e como ajusta nisso. Além do mais, o filtro TCINDEX pode ser usado em outras configurações além daquelas que inclui os serviços DS.


14.3.6. Filtro TC_INDEX

Esse é o comando básico para declarar um filtro TC_INDEX:

... tcindex [ hash SIZE ] [ mask MASK ] [ shift SHIFT ]
[ pass_on | fall_through ]
[ classid CLASSID ] [ police POLICE_SPEC ]


Prosseguindo, mostraremos o exemplo usado para explicar o modo de operação TC_INDEX. Preste atenção às palavras destacadas em itálico:

tc qdisc add dev eth0 handle 1:0 root dsmark indices 64 set_tc_index

tc filter add dev eth0 parent 1:0 protocol ip prio 1 tcindex mask 0xfc shift 2

tc qdisc add dev eth0 parent 1:0 handle 2:0 cbq \
bandwidth 10Mbit cell 8 avpkt 1000 mpu 64


1: Classe de tráfego EF

tc class add dev eth0 parent 2:0 classid 2:1 cbq \
bandwidth 10Mbit rate 1500Kbit avpkt 1000 \
prio 1 bounded isolated allot 1514 weight 1 maxburst 10


2: Pacote qdisc fifo para o tráfego EF

tc qdisc add dev eth0 parent 2:1 pfifo limit 5

tc filter add dev eth0 parent 2:0 protocol ip prio 1 \
handle 0x2e tcindex classid 2:1 pass_on
(Esse código não está completo. É apenas um extrato do exemplo EFCBQ incluído na distribuição iproute2).


Antes de tudo, suponha que recebemos um pacote marcado como EF. Se você ler a RFC2598, verá que o valor recomendado de DSCP para tráfego EF é 101110. Isso significa que o campo DS será 10111000 (lembre-se que os bits menos significativos no byte TOS não são usados em DS) ou 0xb8 na codificação hexadecimal.


TC INDEX
FILTER
+---+ +-------+ +---+-+ +------+ +-+ +-------+
| | | | | | | |FILTER| +-+ +-+ | | | |
| |----->| MASK | -> | | | -> |HANDLE|->| | | | -> | | -> | |
| | . | =0xfc | | | | |0x2E | | +----+ | | | | |
| | . | | | | | +------+ +--------+ | | | |
| | . | | | | | | | | |
-->| | . | SHIFT | | | | | | | |-->
| | . | =2 | | | +----------------------------+ | | |
| | | | | | CBQ 2:0 | | |
| | +-------+ +---+--------------------------------+ | |
| | | |
| +-------------------------------------------------------------+ |
| DSMARK 1:0 |
+-------------------------------------------------------------------------+


O pacote que chega, então, é definido com o valor 0xb8 no campo DS. Como explicado antes, a qdisc dsmark identificada por 1:0 no exemplo, recupera o valor do campo DS e o armazena na variável skb->tc_index. O próximo passo no exemplo corresponderá ao filtro associado a essa qdisc (segunda linha no exemplo). Isso executará as operações seguintes:


Value1 = skb->tc_index & MASK
Key = Value1 >> SHIFT


No exemplo, MASK=0xFC e SHIFT=2.


Value1 = 10111000 & 11111100 = 10111000
Key = 10111000 >> 2 = 00101110 -> 0x2E in hexadecimal


O valor retornado corresponderá a um handle de filtro da qdisc interna (no exemplo, identificador 2:0). Se existir um filtro com esse id, condições de policiamento e metering serão verificadas (caso em que o filtro inclui isso) e o classid será retornado (nosso exemplo, classid 2:1) e armazenado na variável skb->tc_index.

Mas se nenhum filtro com esse identificador não for encontrado, o resultado dependerá da declaração do flag fall_through. Se existir, a chave valor é retornada como classid. Se não, um erro é retornado e o processo continua com o resto dos filtros. Tenha cuidado se você usar o flag fall_through; isso pode ser feito se uma relação simples existir entre valores da variável skb->tc_index e classid´s.

Os últimos parâmetros a comentar são hash e pass_on. O primeiro relaciona com o tamanho da tabela hash. O parâmetro pass_on será usado para indicar que se nenhum classid for encontrado que se iguale ao resultado desse filtro, será tentado o próximo filtro. A ação padrão é fall_through (olhe a tabela seguinte).

Finalmente, vejamos quais possíveis valores podem ser definidos a todos os parâmetros TCINDEX:


TC Name Value Default

-----------------------------------------------------------------
Hash 1...0x10000 Dependente de Implementação
Mask 0...0xffff 0xffff
Shift 0...15 0
Fall through / Pass_on Flag Fall_through
Classid Major:minor None
Police ..... None


Esse tipo de filtro é muito poderoso. É necessário explorar todas as possibilidades. Além disso, esse filtro não é somente usado em configurações DiffServ. Você pode usá-las com qualquer outro tipo de filtro.

Eu recomendo você olhar todos os exemplos DiffServ incluídos na distribuição iproute2. Eu prometo que tentarei complementar esse texto tão logo eu possa. Além do mais, tudo que eu tenho explicado é o resultado de um monte de testes. Eu agradeceria por você dizer-me se me equivoquei em algum ponto.


14.4. qdisc Ingress

Todas qdiscs discutidas até aqui são qdiscs egress. Cada interface, contudo, pode também ter uma qdisc ingress que não é usada para enviar pacotes pra fora do adaptador de rede. Em vez disso, ela permite você aplicar filtros tc a pacotes entrantes pela interface, não importando se os pacotes tiverem um destino local e nem se eles forem encaminhados.

Como os filtros tc contém uma implementação completa do Filtro Bucket Token, e também podem de bater com o estimador de fluxo do kernel, existe um monte de funcionalidades disponíveis. Isso efetivamente permite a você policiar o trafego entrante, antes que ele de fato entre na pilha IP.


14.4.1. Parâmetros & Uso

A qdisc ingress em si não exige qualquer parâmetros. Ela difere de outras qdiscs pelo fato de que ela não ocupa a root qdisc de um dispositivo. Vincule-a como aqui:

# tc qdisc add dev eth0 ingress

Isso permite você ter outra, a que envia, qdiscs sobre seu dispositivo além da qdisc ingress.

Para um exemplo esperto de como a qdisc ingress pode ser usada, veja o Cookbook.










Autores Originais dos textos:

Bert Hubert (Netherlabs BV)
bert.hubert@netherlabs.nl

Thomas Graf (Autor de Seção)
tgraf@suug.ch

Gregory Maxwell (Autor de Seção)
greg@linuxpower.cx

Remco van Mook (Autor de Seção)
remco@virtu.nl

Martijn van Oosterhout (Autor de Seção)
kleptog@cupid.suninternet.com

Paul B Schroeder (Autor de Seção)
paulsch@us.ibm.com

Jasper Spaans (Autor de Seção)
jasper@spaans.ds9a.nl

Pedro Larroy (Autor de Seção)
piotr@member.fsf.org







Random Early Detection




14.5. Random Early Detection (RED)

Essa seção é pensada como uma introdução ao enfileiramento em redes de backbone, que frequentemente envolvem mais de 100 Megabit de banda, que requer uma abordagem diferente do que a de seu modem ADSL de casa.

O comportamento normal em filas de roteador na Internet é chamado tail-drop. O tail-drop funciona enfileirando até certa quantidade, então começa a descartar todo o tráfego que exceder (spills over) o limite. Isso é bastante injusto, e também leva a sincronização de retransmissão. Quando a sincronização de retransmissão ocorre, a rajada repentina de descartes a partir de um roteador que alcançou sua capacidade provocará uma rajada de retransmissões atrasada, o que transbordará o roteador congestionado novamente.


Da Wikipedia http://en.wikipedia.org/wiki/Tail_drop:

Tail Drop, ou Drop Tail, é um algoritmo de gerenciamento de fila usado nos roteadores da Internet para decidir quando descartar pacotes. Em contaste com os algoritmos mais complexos como o RED e WRED, no Tail Drop todo o tráfego não é diferenciado. Cada pacote é tratado de modo idêntico. Com o Tail Drop, quando a fila enche até a sua capacidade máxima, os pacotes novos que chegam são descartados até a fila ficar suficientemente livre para aceitar tráfego entrante.

O nome advém do efeito do policiamento sobre os datagramas entrantes. Uma vez uma fila tenha ficado cheia, o roteador começa a descartar todos os datagramas adicionais, e conseqüentemente começar a descartar o rabo da seqüência de datagramas. A perda de datagramas faz que o transmissor TCP entre em slow-start, o que reduz a taxa de transmissão na sessão TCP até que o transmissor comece a receber ACK´s novamente e aumente a sua janela de congestionamento. Um problema mais severo ocorre quando datagramas de múltiplas conexões TCP são descartados, causando sincronização global, ou seja, todos os transmissores TCP envolvidos entram em slow-start. Isso acontece porque, em vez de descartar vários segmentos de uma conexão, o roteador tenderia a descartar um segmento de cada conexão.

A fim de lidar com o transiente de congestionamento nos links, roteadores do backbone freqüentemente implementam grandes filas. Infelizmente, ao tempo que essas filas são boas para taxa de transmissão, por outro lado podem aumentar de forma substancial a latência e pode se comportar causando rajadas muito fortes durante o congestionamento nas conexões TCP.

Esses problemas com o tail-drop está se tornando uma dor de cabeça enorme na Internet devido ao uso de aplicações exigentes da rede estar aumentando. O Kernel Linux oferece-nos o RED, que é a contração para Random Early Detect – Detecção Randômica Antecipada –, também chamado de Random Early Drop – Descarte Randômico Antecipado –, porque é assim como ele funciona.

O RED não é a cura total para tudo, aplicações que falha na implementação de backoff exponencial ainda possuem uma distribuição não justo da banda, no entanto, com o RED elas não causam tanto dano à taxa de transmissão e latência das outras conexões.

O RED estatisticamente descarta pacotes dos fluxos antes deles alcançarem seu limite rígido. Isso provoca a um link do backbone congestionado ficar lento mais suavemente, e evita sincronização de retransmissão. Isso também ajuda ao TCP encontrar a sua velocidade ‘justa’ mais rápida permitindo que alguns pacotes sejam descartados rapidamente mantendo o tamanho baixo da fila e latência sob controle. A probabilidade de um pacote ser descartado de uma conexão particular é proporcional ao seu uso de largura de banda e não o número de pacotes que ele transmite.

O RED é uma boa fila para backbones, onde você não tem a complexidade da monitoração de estado por sessão necessária pelo enfileiramento justo.

A fim de usar o RED, você precisa decidir sobre três parâmetros: Min, Max e burst. Min define o tamanho de fila mínimo em bytes antes de começar a descartar, Max é um mínimo soft sobre o qual o algoritmo tentará ficar, e burst define o número máximo de pacotes que pode ‘burst through’.

Você deve definir o valor min calculando que latência de enfileiramento base mais alta aceitável que você deseja, e multiplicá-la por sua largura de banda. Por exemplo, no meu link ISDN 64kbit/s, eu posso desejar uma latência de enfileiramento base de 200ms assim eu defino em 1600 bytes. Definir min muito pequeno degradará a taxa de transmissão e muito grande degradará a latência. Definição de um min pequeno não é uma troca pela redução do MTU em um link lento para melhorar a resposta interativa.

Você deve tornar max pelo menos duas vezes o valor de min para evitar sincronização. Em links lentos com pequeno Min´s pode ser esperto para tornar max talvez quatro ou mais vezes maior do que min.

O parâmetro burst controla como o algoritmo RED responde a rajadas. O parâmetro burst precisa ser definido maior do que min/avpkt. Experimentalmente, eu encontrei (min+min+max)/(3*avpkt) para funcionar ok.

Adicionalmente, você precisa definir limit e avpkt. O parâmetro limit é um valor seguro, depois existirá limit bytes na fila, RED ‘entra’ em tail-drop. Eu tipicamente defino limit em oito vezes o valor de max. O parâmetro avpkt deve ser seu tamanho médio de pacote. 1000 funcionam OK em links Internet de lata velocidade com MTU de 1500 bytes.

Leia o artigo sobre Enfileiramento RED de autoria de Sally Floyd e de Van Jacobson para informações técnicas.


14.6. Generic Random Early Detection

Não é sabido muito coisa sobre o GRED. Ele parece com RED com várias filas internas, em que a fila interna é escolhida baseada no campo tcindex do DiffServ. De acordo com uma apresentação aqui, ele possui as habilidades do ‘Distributed Weighted RED’ da Cisco, bem como do RIO do Dave Clark.

Cada fila virtual pode ter especificado seus próprios Parâmetros Drop.

CORRIJAM-ME: Jamal ou Werner nos ensine mais a respeito.


14.7. Emulação VC/ATM

Isso é esforço principal inteiramente de Werner Almesberger para permitir você construir Circuitos Virtuais sobre os soquetes TCP/IP. Um Circuito Virtual é um conceito da teoria da rede ATM.

Para mais informação, veja o site ATM sobre o Linux.


14.8. Weighted Round Robin (WRR)

Essa qdisc não é incluída nos kernels padrão, mas pode ser baixada daqui. Atualmente a qdisc é testada somente com os kernels Linux 2.2, mas provavelmente funcionará com os kernels 2.4/2.5 também.

A qdisc WRR distribui largura de banda entre suas classes usando o esquema cíclico ponderado. Isto é, igual ao CBQ que contém classes em que qdiscs arbitrárias podem ser plugadas. Todas as classes que tenham demanda suficiente ganharão largura de banda proporcional aos pesos associados com as classes. Os pesos podem ser definidos manualmente usando programa tc. Mas eles podem também ser feitos automaticamente decrementado pra classes que transferem muitos dados.

A qdisc possui um classificador embutido que atribui pacotes chegando de ou enviado para diferentes máquinas para diferentes classes. Tanto o endereço MAC quanto o IP e tanto os endereços origem quanto destino pode ser usado. Contudo, o endereço MAC pode ser usado somente quando a máquina Linux está agindo como uma ponte Ethernet. As classes são automaticamente atribuídas nas maquinas baseados nos pacotes observados.

A qdisc pode ser bastante útil em sites como de dormitórios de estudantes onde muitos indivíduos não relacionados compartilham conexão Internet. Um conjunto de scripts define um comportamento relevante quando um site é uma parte central da distribuição WRR.










Autores Originais dos textos:

Bert Hubert (Netherlabs BV)
bert.hubert@netherlabs.nl

Thomas Graf (Autor de Seção)
tgraf@suug.ch

Gregory Maxwell (Autor de Seção)
greg@linuxpower.cx

Remco van Mook (Autor de Seção)
remco@virtu.nl

Martijn van Oosterhout (Autor de Seção)
kleptog@cupid.suninternet.com

Paul B Schroeder (Autor de Seção)
paulsch@us.ibm.com

Jasper Spaans (Autor de Seção)
jasper@spaans.ds9a.nl

Pedro Larroy (Autor de Seção)
piotr@member.fsf.org







Parametros OnFly de Rede no Kernel



Capítulo 13. Parâmetros OnFly de Rede no Kernel

O kernel possui muitos parâmetros que podem ser feitos ajustes finos para diferentes situações. Ao tempo que, como usual, os parâmetros padrões servem muito bem 99% das instalações, nós não o chamaríamos de ‘HOWTO Avançado’ só pelo prazer de chamá-lo!

Os bits de interesse estão em /proc/sys/net, dê uma olha lá. Nem tudo estará documentando aqui inicialmente, mas estamos trabalhando com eles.

No meio tempo você pode desejar dá uma olhada nos fontes do Kernel Linux; leia o arquivo Documentation/filesystems/proc. txt. Muitas das funcionalidades são explicadas lá.

(CORRIJAM-ME)


13.1. Filtragem do Caminho Reverso

Por padrão, roteadores roteiam tudo, mesmo pacotes que ‘obviamente’ não pertencem a sua rede. Um exemplo comum é o espaço IP privado que escapa para a Internet. Se você tiver uma rede com uma rota 195.96.96.0/24 pra ela, você não espera pacotes de 212.64.94.1 para chega até ela.

Muitas pessoas desejarão desativar essa funcionalidade, porque os hackers do kernel fazem isso facilmente. Existem arquivos em /proc onde você pode informar ao kernel para fazer isso pra você. O método é chamado de “Reverse Path Filtering”, ou seja, Filtragem do Caminho Inverso. Basicamente, se a resposta a um pacote saísse pela interface que esse pacote chegou, então ele é um pacote falso e deve ser ignorado.

O fragmento seguinte ativará isso para todas as interfaces atuais e futuras.


# for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
> echo 2 > $i
> done


Seguindo com o exemplo acima, se um pacote chegou ao roteador Linux pela interface eth1 que declara vir da sub-rede Office+ISP, ele seria descartado. De forma similar, se um pacote chegar da sub-rede Office, declarando ser de algum lugar externo ao seu firewall, ele seria descartado também.

O exemplo acima é a filtragem total do caminho reverso. O padrão é filtrar somente baseado nos endereços IP´s que estão diretamente conectados as redes. Isso é porque a filtragem total quebra no caso de roteamento assimétrico (quando acontece dos pacotes chegando por um caminho e saindo por outro, como tráfego de satélite, ou se você tiver rotas dinâmicas (BGP, OSPF, RIP) em sua rede. Os dados que desce pela antena do satélite e as respostas voltam através de linhas terrestres normais).

Se essa exceção se aplica a você (e provavelmente saberá se funciona) você pode simplesmente desativar o parâmetro rp_filter na interface por aonde chegam os dados do satélite. Se você deseja ver se algum pacote está sendo descartado, o arquivo log_martians no mesmo diretório dirá ao kernel para registrá-lo no seu syslog.


# echo 1 >/proc/sys/net/ipv4/conf/<interfacename>/log_martians


CORRIJA-ME: Setando os arquivos conf/{default,all}/* é suficiente? – Martian









Autores Originais dos textos:

Bert Hubert (Netherlabs BV)
bert.hubert@netherlabs.nl

Thomas Graf (Autor de Seção)
tgraf@suug.ch

Gregory Maxwell (Autor de Seção)
greg@linuxpower.cx

Remco van Mook (Autor de Seção)
remco@virtu.nl

Martijn van Oosterhout (Autor de Seção)
kleptog@cupid.suninternet.com

Paul B Schroeder (Autor de Seção)
paulsch@us.ibm.com

Jasper Spaans (Autor de Seção)
jasper@spaans.ds9a.nl

Pedro Larroy (Autor de Seção)
piotr@member.fsf.org







Parametros Obscuros OnFly




13.2. Parâmetros Obscuros OnFly

Certo, existem muitos parâmetros que podem ser modificados. Nós tentaremos listá-los todos. Também está documentado (parcialmente) em Documentation/ip-sysctl.txt

Alguns desses parâmetros possuem valores padrões diferentes baseados na resposta que você respondeu à opção ‘Configure as router e not host’ se foi ‘Yes’ quando esteve compilando o seu kernel.

Oskar Anderson também possui uma página a respeito de todos esses flags e parece ser melhor do que a nossa lista, então verifique também http://ipsysctl-tutorial.frozentux.net/.


13.2.1. O ipv4 Genérico

Como uma nota genérica, muitas funcionalidades limitação de taxa não funciona na interface loopback, portanto não teste-os localmente. Os limites são fornecidos em ‘jiffies’, e são forçado usar o filtro token bucket mencionado anteriormente.

O kernel possui um clock interno que roda em ‘HZ’ ticks (ou ‘jiffies’) por segundo. Nas placas Intel, ‘HZ’ é frequentemente 100. Assim configurar um arquivo *_rate para, digamos 50, permitiria 2 pacotes por segundos. O filtro token bucket é também configurado para levar em conta uma rajada de no máximo 6 pacotes, se tokens suficientes foram conseguidos.

Várias entradas na lista seguinte foram copiadas de /usr/src/linux/Documentation/networking/ip-sysctl.txt, escrita por Alexey Kuznetsov e Andi Kleen ak@muc.de.


/proc/sys/net/ipv4/icmp_destunreach_rate

Se o kernel decidir que não pode entregar um pacote, ele o descartará, e envia a origem do pacote um aviso ICMP notificando sobre esse problema.




/proc/sys/net/ipv4/icmp_echo_ignore_all

Não atua sobre os pacotes echo de hipótese alguma. Favor não configure tal parâmetro por padrão, mas se você for usado como um transmissor quando de um ataque DoS, ele pode ser útil.




/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts [Useful]

Se você pingar o endereço de broadcast de uma rede, todos os hosts são suposto responder. Isso contribui como uma elegante ferramenta negação de serviço. Defina esse parâmetro como 1 para ignorar essas mensagens de broadcast.




/proc/sys/net/ipv4/icmp_echoreply_rate

A taxa em que as respostas echo são enviadas para qualquer que seja o destino.




/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

Defina esse parâmetro para ignorar erros ICMP provocados por hosts na rede os quais reagem duramente a quadros enviados quando eles percebem ser o endereço de broadcast.




/proc/sys/net/ipv4/icmp_paramprob_rate

Uma mensagem ICMP relativamente desconhecida, que é enviada em resposta a pacotes incorretos com cabeçalho IP ou TCP. Com esse arquivo você pode controlar a taxa na qual ela é enviada.




/proc/sys/net/ipv4/icmp_timeexceed_rate

Esse parâmetro é a causa famosa do ‘Solaris middle star’ em traceroutes. Limita a taxa de mensagens ‘ICMP Time Exceeded’ enviadas.




/proc/sys/net/ipv4/igmp_max_memberships

Número máximo de soquetes de escuta IGMP (multicast) no host. CORRIJAM-ME: Isso é verdade?




/proc/sys/net/ipv4/inet_peer_gc_maxtime

CORRIJAM-ME:
Adiciona uma explanação pequena a cerca do inet peer storage? Intervalo máximo entre passagens garbage collection. Esse intervalo está de fato sob pressão de memória baixa (ou ausência) no pool. Medida em jiffies.




/proc/sys/net/ipv4/inet_peer_gc_mintime

Intervalo mínimo entre passagens garbage collection. Esse intervalo está de fato sob pressão por memória alta no pool. Medido em jiffies.




/proc/sys/net/ipv4/inet_peer_maxttl

Máximo time-to-live de entradas. Entradas não usadas vão expirar após esse período de tempo se não existir nenhuma pressão por memória no pool (ou seja, quando o número de entradas no pool for pequeno). Medido em jiffies.




/proc/sys/net/ipv4/inet_peer_minttl

Mínimo time-to-live de entradas. Deve ser suficiente para cobrir fragmentos time-to-live no lado reassembling. Esse time-to-live mínimo é garantido se o tamanho do pool for menor do que inet_peer_threshold. Medido em jiffies.




/proc/sys/net/ipv4/inet_peer_threshold

O tamanho aproximado do INET peer storage. Começando a partir dessa threshold as entradas serão lançadas agressivamente. Esse threshold também determina entradas time-to-live e intervalos de tempo entre passagem de coleção garbage. Quanto mais entradas, menos time-to-live, e menos intervalo GC.




/proc/sys/net/ipv4/ip_autoconfig

Esse arquivo contém o número um se o host recebeu sua configuração IP por RARP, BOOTP, DHCP ou um mecanismo similar. Do contrário, esse parâmetro será zero.




/proc/sys/net/ipv4/ip_default_ttl

Time To Live de pacotes. Configure para um valor seguro 64. Aumente-o se você tiver uma rede enorme. Não faça isso só por diversão – loops de roteamento causam muito mais danos desse jeito. Você pode até mesmo considerar baixá-lo em algumas situações.











Autores Originais dos textos:

Bert Hubert (Netherlabs BV)
bert.hubert@netherlabs.nl

Thomas Graf (Autor de Seção)
tgraf@suug.ch

Gregory Maxwell (Autor de Seção)
greg@linuxpower.cx

Remco van Mook (Autor de Seção)
remco@virtu.nl

Martijn van Oosterhout (Autor de Seção)
kleptog@cupid.suninternet.com

Paul B Schroeder (Autor de Seção)
paulsch@us.ibm.com

Jasper Spaans (Autor de Seção)
jasper@spaans.ds9a.nl

Pedro Larroy (Autor de Seção)
piotr@member.fsf.org










Creative Commons License
Admirável Mundo Novo: Tudo Sobre Asterisk, OpenSER, Linux e Tecnologias de Voz sobre IP
by Cléviton Mendes de Araújo is licensed under a Creative Commons Atribuição 2.5 Brasil License.