11 de outubro de 2009

O Problema do MTU do PPPoE

Por Lucas Sabino


Caros leitores, se você nunca ficou sabendo de tal coisa é necessário ler e aprender. Eu não tinha a mínima idéia (ideia para quem já está seguindo à risca a nova língua portuguesa) que isso existia. Mas, existe. Meu chefe (meus dois chefes) mandaram eu fazer um monte de firewall em um monte de servidores pelo Brasil a fora (esse a fora foi exagero, é só Brasil mesmo) (devo mais essa pro SSH, imagina eu indo pro Acre, Curitiba ou sei lá mais onde!!??). Acho que são uns 15 firewall. Na realidade não preciso fazer propriamente dito, preciso traduzir do modelo FERM (For Easy Rule Making) para o modelo Iptables. Bom esse ferm até que em bem mais fácil. Você configura um firewall em 20 linhas.

Enquanto no iptables você faria isso numas 50. Mas, ainda sim, sou mais o grande IPTABLES. Me deparei com a seguinte linha no conf fo FERM: "table mangle { chain FORWARD { interface $LAN_IF proto tcp tcp-flags (SYN RST) SYN TCPMSS clamp-mss-to-pmtu;" Aí eu falei, fudeu!! E agora??? que bagaça é essa???? mangle blz é table mas TCPMSS, mss pmtu mtu??? que que é isso? Bom, vamos ao que interessa, a introdução já foi feita! O PROBLEMA DO EMPACOTAMENTO DA PPPoE A fonte desse texto eu traduzi do link a seguir --> http://www.akadia.com/services/pppoe_iptables.html. Quem quiser poderá ler em sua fonte original em inglês. Quem não quiser leia a tradução aqui mesmo.  


Alguns termos devem estar na ponta da língua: MTU PPP PPPoE.  

MTU
Em redes de computadores, MTU significa Unidade Máxima de Transmissão, e refere-se ao tamanho do maior datagrama que uma camada de um protocolo de comunicação pode transmitir. O protocolo IP permite a fragmentação de pacotes, possibilitando que um datagrama seja dividido em pedaços.

PPP
O protocolo ponto-a-ponto (point-to-point protocol, em inglês), também conhecido como PPP, foi desenvolvido e padronizado através da RFC 1661(1993) com o objetivo de transportar todo o tráfego entre 2 dispositivos de rede através de uma conexão física única. Na prática, a interface PPP é implementada através de conexões físicas do tipo RS-232 ou modens. Atualmente é possível usar conexões PPP até sobre Ethernet (PPPoE). Em suma, é a conexão discada slowmotion que todo mundo conhece só pelo barulinho agradável.

PPPoE
PPPoE (Point-to-Point Protocol over Ethernet) é um protocolo para conexão de usuários em uma rede Ethernet a Internet. Seu uso é típico nas conexões de um ou múltiplos usuários em uma rede LAN à Internet através de uma linha DSL, de um dispositivo wireless (sem fio) ou de um modem de cabo broadband comum. O protocolo PPPoE deriva do protocolo PPP. O PPPoE estabelece a sessão e realiza a autenticação com o provedor de acesso a Internet. Em suma, é o Speedy (SP) ou Velox (RJ, MG, nordeste, aonde a Oi é operadora padrão).


Com esses termos na ponta da língua, vamos ao texto: O PROBLEMA MTU

Uma interface Ethernet pode ter um pacote que tem no máximo 1518 bytes. 14 bytes desses são usados pelo cabeçalho, e 4 para uma seqüência de pacotes de checagem. Ou seja, temos ainda 1500 bytes a serem usados. 1500 é o padrão para conexões PPPoE.

Esse é o tamanho que o pacote PPPoE possui quando a interface não fragmenta ele. A conexão PPPoE adiciona outros 6 bytes a essa perda, além do protocolo PPP consumir 2 bytes. Assim, nosso datagrama possui 1492 bytes. O MTU da conexão PPPoE é então 1492 bytes.

Quando uma conexão TCP é inicializada, cada lado dos agentes/clientes do TCP pode ter o seu próprio tamanho de fragmentação do seu pacote (MSS - Maximum Segment Size). O TCP é respnsável por ouvir/conversar com esses fragmentos, enquanto o MSS determina o tamanho máximo para que ele seja aceito. Por padrão, o MSS é escolhido como o MTU a partir de uma interface de saída menos usual do TCP e cabeçalhos IP (40 bytes), que resulta num MSS de 1460 bytes para a interface de Ethernet.

O TCP não quer fragmentação, quanto menos pra ele melhor! Então, ele usa o MSS para não causar fragmentações a mais na sua interfae de saída. Eventualmente, eles podem trabalhar como MTU causando uma fragmentação nos seus pacotes. O TCP descobre o caminho MTU. No caminho da descoberta do MTU, uma pilha TCP define um especial ponto de "não fragmente" (DF) em datagramas IP. Roteadores que não pode encaminhar o datagrama sem fragmentá-lo é suposto largá-lo e enviar um ICMP Fragmentation "necessário" datagrama ao host de origem.

Nesse estágio, os hosts de origem tentam um valor baixo para MTU. Eventualmente, muitos roteadores são "anti-sociais" e não geram a fragmentação dos datagramas como foi mandado. Eles são rebeldes! (rs). Muitos Firewall são igualmente anti-sociais e bloqueiam todos os pacotes ICMP.

Agora vamos considerar uma estação cliente conectada de uma Ethernet LAN até um gateway PPPoE. O cliente abre, depois de conectado, uma conexão para com um servidor web. Ele sugere um MSS de 1460 bytes porque seu MTU é 1500. O servidor web possui também uma interface Ethernet e sugere um MSS de 1460. A máquina cliente então pede a página web. Essa requisição é tipicamente pequena e aproxima o servidor web. O servidor responde com muitos fragmentos TCP, a maioria sendo do tamanho 1460 bytes.

O tamanho máximo de fragmentação do pacote é 1500 bytes no datagrama IP, porém o pacote é segmentado em menos bytes por eles. E daí vai para o provedor DSL que não manda ICMP para o servidor web.

A internet silencia o pacote, ele é dropado (rejeitado, apagado). O cliente web fica esperando pelos dados, e o servidor web transmite os dados finalmente, ou a conexão é fechada pelo usuário.

Uma maneira de contornar isso é criar um outro MSS para definir a rota padrão em todos os hosts LAN atrás do gateway PPPoE. Isso é chato, pois requer mudanças em cada host. Em vez disso, RP-PPPoE "em escuta" sobre a negociação MSS e modifica a MSS se for demasiado grande. Ajustar o MSS é um hack. Ela quebra o conceito de transporte da camada ser final-para-final (client-server). Não vai funcionar com o IPSec, IPSec, porque não vai deixar você danos pacotes IP (eles não conseguirão autenticar.) No entanto, é uma solução bastante eficaz para um problema , e é usado por padrão no RP-PPPoE."

- Mas, ok ok ok... Mas, Sabino você não disse como resolve no Iptables!

- Calma Pequeno gafanhoto... Espere um pouco...



Agora! Vamos à solução no Iptables:

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

ou

iptables -t nat -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu TCPMSS --clamp-mss-to-pmtu -o ppp0

ou

iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -o eth1 -j TCPMSS --set-mss 1472
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -o eth1 -j TCPMSS --clamp-mss-to-pmtu
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o eth1 -j TCPMSS --set-mss 1472
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o eth1 -j TCPMSS --clamp-mss-to-pmtu


Vai depender do que você quer fazer e como você quer fazer. Depende da sua tabela, se é filter | nat | mangle.

Espero ter ajudado! flw!

4 comentários:

Minha vida disse...

Fala Sabino, bom artigo...me esclareceu umas duvidas. Posso pedir um artigo sobre rede básica?

Tipo imagens e textos mostrando como funciona uma rede q usa speedy e virtual?
Brigado mano

Marcio Cosenza disse...

Excelente artigo,

Foi muito util!!

Anônimo disse...

Obrigado Márcio.

E Pablo, já fiz o artigo. Acredito que já tenha visto. Esqueci de colocar aqui que já havia escrito.

abraços

Leandro Jaraguá disse...

Ótimo artigo!
E lá vai o Sabinux mais uma vez... hehehe!