
visitas desde 24 Abr 05
A versão mais recente deste arquivo pode ser encontrada em http://cunha17.cristianoduarte.pro.br/ipsec
Você pode perguntar:
"Olha, trabalho legal, mas eu não quero aprender o básico
de IPSec e não quero entender o que vou fazer, apenas quero um
IPSec bem simples e fácil entre duas máquinas Linux!" e
eu te responderei "Pegue qualquer um dos exemplos do Apêndice A! Para segurança com criptografia pegue aqueles que contêm ESP... ;)"
Introdução
Este tutorial
tem a finalidade de mostrar como é fácil criar uma VPN
entre máquinas utilizando o padrão KAME IPSec presente no
kernel 2.6 do Linux.
No item
"Montando sua VPN passo a
passo" será mostrado como montar uma VPN (modo túnel)
entre
gateways utilizando o
KAME IPSec, o Racoon e um Segredo Compartilhado.
Este tutorial
foi implementado em uma VPN entre uma máquina
Linux Debian
"testing"
(sarge) e uma máquina FreeBSD com firewall Aker 5.0 (o
procedimento é praticamente o mesmo para uma outra
máquina com Fedora Core, Debian, etc.)
Testes foram
feitos com sucesso entre duas máquinas rodando
Fedora Core 2. Nesses testes, foram criados canais em modo túnel
e transporte, no entanto não foram feitos testes com o IKE
(racoon), as chaves utilizadas eram fixas. Os scripts de
criação dos canais se encontram no Apêndice A.
Finalidade
O IPSec pode trabalhar em dois modos:
Modo Túnel: a principal
finalidade é criar uma
comunicação segura entre redes remotas utilizando um meio
não confiável. Um exemplo:
 |

|

|
  
  
|

|
  
   |
 |

|
 |
Rede1
|
Gw1
|
Canais IPSec
|
Internet
|
Canais IPSec
|
Gw2
|
Rede2
|
IPSec
em modo túnel entre os gateways Gw1 e Gw2
Modo Transporte: a principal
finalidade é criar uma
comunicação segura fim-a-fim, ou seja, entre uma
máquina e outra,
utilizando um meio não confiável. Um exemplo:

|
  
   |

|
  
   |
 |
  
  |

|
Cliente
|
Canais IPSec |
Dial-up
|
Canais IPSec |
Internet
|
Canais IPSec |
Servidor
|
IPSec
em modo transporte entre as máquinas Cliente e Servidor
OBS: Normalmente VPN's são montadas em modo túnel.
Montando sua VPN passo a passo
Serão mostrados os passos necessários para se estabelecer
uma VPN em modo túnel entre a Rede1(10.67.112.0) e a
Rede2(10.0.0.0) utilizando o daemon IKE racoon. Os gateways
serão conectados via internet, onde o endereço IP do
Gateway1 é 100.100.100.100 e do Gateway2 é
200.200.200.200.
Passo 1:
Instalação dos pacotes
- Pacotes
que todo servidor deveria ter:
# apt-get install
ntpdate ntp-server
- Pacotes
essenciais para a VPN:
# apt-get
install
ipsec-tools
racoon iproute iptables kernel-image-2.6
OBS1: durante a instalação do racoon, informe que
você não deseja utilizar o racoon-tool, e sim uma
configuração manual do racoon.
OBS2: se o kernel instalado anteriormente não for 2.6, é
necessário reiniciar o computador com o kernel 2.6 antes de
prosseguir.
- Pacotes
para testar e "debugar" a conexão:
# apt-get
install dnsutils lynx tcpdump
Passo 2:
Configuração das políticas
O IPSec é composto por duas bases de dados distintas:
- SPD(Security
Policy Database) ou Base de Dados de Políticas de
Segurança
As políticas dizem ao IPSec quando este deve ou não atuar
sobre um pacote IP.
Palavra
chave: QUANDO
Uma Política de Segurança(SP) constitui-se, basicamente
dos seguintes aspectos:
- Faixa de
endereços de origem (src): Se o endereço de origem do
pacote estiver nessa faixa, então...
- Faixa de
endereços de destino (dst): Se o endereço de destino do
pacote estiver nessa faixa, então...
- Protocolo
da camada superior: Se o protocolo do pacote for [tcp,udp,icmp,any],
então...
- Política
a ser utilizada:
- Direção
do canal a ser criado: canal de entrada (in) ou de saída (out)
- Ação:
que será realizada com o pacote, pode ser:
- discard
(descarte o pacote)
- none
(não aplique IPSec sobre o pacote)
- ipsec
(aplique IPSec sobre o pacote) seguida de uma regra de como processar o
pacote:
- Protocolo
IPSec a ser aplicado: pode ser ah, esp ou ipcomp
- Modo
IPSec a ser utilizado
- tunnel
- IP
real da máquina Gateway 1 (início do túnel)
- IP
real da máquina Gateway 2 (término do túnel)
- transport
- Nível
do IPSec:
- default
- use:
utilizar uma associação de segurança(SA) somente
se estiver disponível, caso contrário enviar o pacote
normalmente
- require:
é obrigatório a utilização de uma SA para o
envio do pacote
- unique
OBS:
se uma SA não estiver disponível, o kernel solicita o
estabelecimento de uma SA ao daemon IKE (racoon)
- SAD(Security
Association Database) ou Base de Dados de Associações de
Segurança
As associações dizem ao IPSec como este deve criar um
canal entre duas máquinas.
Palavra
chave: COMO
Uma Associação de Segurança(SA) constitui-se,
basicamente, dos seguintes aspectos:
- Endereço
IP de origem
- Endereço
IP de destino
- Protocolo
IPSec a ser utilizado: ah, esp, ipcomp
- Índice
numérico (SPI - Security Parameter Index)
- Modo do
protocolo: tunnel, transport, any(qualquer um dos modos)
- Algoritmos
- Autenticação
com a chave a ser utilizada
- Encriptação
com a chave a ser utilizada
- Encriptação
e Autenticação com as chaves a serem utilizadas
- Compressão
|
ATENÇÃO: uma SA só
é utilizada se estiver "associada"
a uma política, ou seja, somente se
existir uma política cuja regra tenha os mesmos parâmetros
da SA.
|
NOTA: Pode existir SP
funcional sem SA de duas formas:
- Quando
a SP é do tipo none ou discard, onde não existe SA
a ser utilizada já que o IPSec não será aplicado
- Quando a SA é
criada dinamicamente pelo daemon IKE(racoon)
Em
qualquer outra hipótese, uma SP sem uma SA faz com que o
pacote fique enfileirado até ser descartado.
|
Para configurar a SPD e/ou a SAD, utilizamos um aplicativo chamado
setkey. Este aplicativo pode ser chamado como se fosse um "script
processor"(como o bash). Exemplo:
#!/sbin/setkey
-f
flush ah;
flush esp;
spdflush;
O código acima
pode ser gravado em um arquivo chamado ipsec-off, com atributos rwx para o root. Ao se executar ./ipsec-off, serão removidas
todas as regras existentes na SAD(tanto AH quanto ESP) e na SPD.
Como vamos utilizar o
racoon para criar nossas entradas na SAD, basta
que criemos as nossas políticas na SPD. Portanto o arquivo ipsec-on ficará assim:
#!/sbin/setkey -f
flush;
spdflush;
#REDE1 para REDE2
spdadd
10.67.112.0/22[any] 10.0.0.0/8[any] any -P in ipsec
esp/tunnel/100.100.100.100-200.200.200.200/require;
#REDE2 para
REDE1
spdadd
10.0.0.0/8[any] 10.67.112.0/22[any] any -P out ipsec
esp/tunnel/200.200.200.200-100.100.100.100/require;
OBS: "flush;"
tem o mesmo efeito de "flush ah;" seguido de "flush esp;"
Passo 3:
Configuração do Racoon
Antes de
configurarmos o racoon, precisamos modificar o script de
carregamento do racoon. Edite o arquivo /etc/init.d/racoon e altere a
seguinte linha:
start-stop-daemon
--start --quiet --exec /usr/sbin/racoon
para:
start-stop-daemon
--start --quiet --exec /usr/sbin/racoon -- -l /var/log/racoon.log
Com isso, colocamos qualquer informação de log no arquivo
/var/log/racoon.log.
Agora, o racoon
será configurado para utilizar um segredo
compartilhado para a autenticação inicial entre os
gateways. Eis o arquivo /etc/racoon/racoon.conf:
path
pre_shared_key "/etc/racoon/psk.txt";
log debug2;
listen {
isakmp 200.200.200.200 [500];
strict_address;
}
remote
100.100.100.100 {
exchange_mode main;
send_cr off;
send_cert off;
proposal {
encryption_algorithm blowfish;
hash_algorithm sha1;
authentication_method pre_shared_key;
dh_group 2;
lifetime time 300 seconds;
}
}
A linha 1 diz a
localização do arquivo onde se encontra o
segredo compartilhado. Este arquivo é composto de duas colunas
separadas por espaço/tabulação, onde a primeira
coluna é o endereço IP do gateway e a segunda o segredo
compartilhado desse gateway. Então o arquivo
/etc/racoon/psk.txt ficará assim:
200.200.200.200 1234567890
100.100.100.100
1234567890
A linha 2 configura o
log do racoon para debug2(depois
pode ser colocado em
outro nível, como por exemplo notify)
onde o daemon gera toneladas de informações de log.
A cláusula listen,
informa ao racoon em que IP e porta ele deve esperar
requisições IKE. Neste exemplo o endereço
utilizado foi 200.200.200.200 e a porta 500/udp, que é a porta
padrão IPSec para IKE. A entrada strict_address força o
racoon a abortar se não conseguir escutar neste IP e porta.
Agora a cláusula remote. Ela começa com o IP do gateway
remoto e contém diversas diretivas:
- exchange_mode: diz o modo de troca
para a fase 1 do IKE. Pode ser main, aggressive ou base. O Firewall
Aker utiliza, por padrão, o modo main, por isso este foi
utilizado aqui.
- send_cr: diz se enviaremos ou
não uma requisição de certificado. Como vamos
utilizar um segredo compartilhado, esta diretiva é desligada.
- send_cert: diz se enviaremos ou
não um certificado. Como vamos utilizar um segredo
compartilhado, esta diretiva é desligada.
- proposal: esta é a proposta
que será enviada ao Gateway remoto. Se, no Gateway remoto,
houver uma entrada no racoon.conf com as mesmas características
dessa proposta, então ela será aceita. Na proposta
encontramos:
- encryption_algorithm:
qual o algoritmo de criptografia será utilizado.
- hash_algorithm: qual o
algoritmo de hash será utilizado
- authentication_method:
qual o método de autenticação utilizado e, no
caso, será um segredo compartilhado.
- dh_group: o grupo
utilizado nas exponenciações do modelo Diffie-Hellman. O
padrão do Firewall Aker é 2.
- lifetime_time:
define o tempo de vida da fase 1 da proposta SA. O padrão do
Firewall Aker é 300 segundos.
Passo 4:
Configuração das regras no firewall
O IPSec em modo túnel utiliza o protocolo número 50 (ESP)
para encriptar os dados do pacote IP.
Atenção: é
protocolo 50 e não porta 50 !!!
O Racoon utiliza a porta 500/udp para troca de chaves (IKE) entre os
gateways.
Basta
acrescentar estas linhas no seu arquivo de regras do iptables:
#configura parâmetros do kernel
echo 1 >
/proc/sys/net/ipv4/ip_forwad
echo 0 >
/proc/sys/net/ipv4/ip_dynaddr
echo 0 >
/proc/sys/net/ipv4/conf/all/rp_filter
echo 0 >
/proc/sys/net/ipv4/conf/all/accept_source_route
echo 1 >
/proc/sys/net/ipv4/conf/all/accept_redirects
echo 0 >
/proc/sys/net/ipv4/conf/all/log_martians
echo 1 >
/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 0 >
/proc/sys/net/ipv4/icmp_echo_ignore_all
echo 0 >
/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
#aceitar
pacotes ESP
iptables -I INPUT 1 -j ACCEPT -p 50
iptables
-I OUTPUT 1 -j ACCEPT -p 50
iptables -I FORWARD 1 -j ACCEPT -p 50
#aceitar pacotes IKE
iptables -I INPUT
1 -j ACCEPT -p udp --dport 500
iptables
-I OUTPUT 1 -j ACCEPT -p udp --dport 500
iptables -I
FORWARD 1 -j ACCEPT -p udp --dport 500
#aceitar pacotes ICMP
iptables -I INPUT
1 -j ACCEPT -p icmp
iptables
-I OUTPUT 1 -j ACCEPT -p icmp
iptables -I
FORWARD 1 -j ACCEPT -p icmp
ATENÇÃO:
se você
quiser criar regras mais restritivas(e você deve), basta
adicionar o
endereço de origem e destino nas regras acima. Não se
esqueça que os
endereços de origem e destino são os endereços de
Internet(ou da rede
não confiável) dos gateways.
|
CUIDADO:
o parâmetro do kernel /proc/sys/net/ipv4/conf/all/rp_filter
verifica
por IP spoofing e, como foi desativado, a verificação
deverá ser feita via regras do próprio IPTABLES!
Porém estas regras deverão aparecer depois das regras que
liberam a VPN.
|
|
NOTA IMPORTANTE
1: O cabeçalho IP de um pacote ESP não pode ser
modificado pelo NAT, portanto,
não se
pode fazer NAT de um
canal IPSec(pelo
menos diretamente, para isso existe o NATT) e por conseguinte,
não pode
haver NAT entre os Gateways. Se você usa NAT em
seu firewall adicione as seguintes
regras antes de qualquer outra para que não seja feito NAT de
pacotes da sua VPN:
#Não
fazemos NAT para ESP
iptables -t nat -I PREROUTING 1 -j ACCEPT -p 50
iptables -t nat -I
POSTROUTING 1 -j ACCEPT -p 50
|
Passo 5: Carregar a VPN
Executar seu script de carregamento de regras do iptables (acrescido
das regras do passo 4).
Executar o script ipsec-on.
Executar o racoon (/etc/init.d/racoon
restart).
A VPN ainda
não está estabelecida, precisamos que um
pacote passe pelo firewall para que a SA seja estabelecida pelo racoon.
Portanto é o momento de executar:
# ping
100.100.100.100
ou
# ping
200.200.200.200
conforme o caso.
A primeira resposta pode demorar vários segundos, já que
antes o racoon precisa estabelecer o túnel.
Passo 6: Testar a VPN
Se o ping funcionar,
é hora de testar uma pagina web. Portanto
execute o aplicativo lynx
seguindo de um endereço de uma página na rede remota.
Se a página
abrir, e for possível navegar nos links,
é hora de testarmos em modo gráfico com o bom e velho
Mozilla. Se você conseguir abrir as páginas do site remoto
no Mozilla, com texto e figuras, sua VPN está funcionando!
Parabéns !
No entanto se
ocorrer qualquer tipo de problema, verifique o arquivo de
log do racoon(/var/log/racoon.log), o arquivo de log do
kernel(/var/log/kern.log) e consulte a seção Solução de Problemas.
OBS: Este tutorial
pressupõe um Firewall Aker configurado
corretamente e da mesma maneira. Se quiser utilizar um sistema Linux
com kernel 2.6 como Gateway2, basta executar os mesmos passos acima
nesta segunda máquina, apenas invertendo in para out
e vice-versa no passo 2 e o endereço remoto no passo
3.
|
Solução
de Problemas
- Consigo
apenas "pingar" o outro gateway
- Se você consegue
pingar o endereço internet do gateway remoto, mas não
consegue pingar o
endereço de rede local desse gateway, provavelmente:
- Não foi estabelecida a VPN
Verifique o log do
racoon em /var/log/racoon.log e procure por
problemas. Se o Firewall remoto não for configurado para deixar
passar
pacotes ESP e IKE, a VPN não será estabelecida.
- O gateway remoto possui um Firewall bloqueando seus "pings"
No gateway
remoto: verifique o log do firewall e rode o TCPDUMP para ver se o
pacote ICMP ECHO REQUEST chega e se o pacote ICMP ECHO REPLY sai.
- Se
você consegue
pingar o endereço de rede local do Gateway remoto mas não
consegue
pingar outras máquinas na rede remota, provavelmente:
- O gateway remoto não está fazendo forwarding
dos pacotes recebidos.
Execute o comando: cat
/proc/sys/net/ipv4/ip_forwad e veja se o
resultado é "1". Caso contrário execute:
echo 1 >
/proc/sys/net/ipv4/ip_forwad
- O
gateway remoto possui um Firewall bloqueando seus "pings"
No gateway remoto:
verifique o log do firewall e rode o
TCPDUMP para ver se o pacote ICMP ECHO REQUEST chega e se o pacote ICMP
ECHO REPLY sai.
- Consigo apenas
"pingar" máquinas na outra rede
- Abro apenas a
página frame, não consigo abrir figuras nem outras
páginas
- Abro
apenas páginas pequenas
- Pacotes
pequenos passam, mas pacotes maiores não.
| Antes
de prosseguir verifique se o gateway remoto possui
um Firewall bloqueando seus pacotes. Verifique o log do
firewall e rode o
TCPDUMP para ver se o pacote ICMP ECHO REQUEST chega e se o pacote ICMP
ECHO REPLY sai. |
Estes são sintomas do mesmo
problema: MSS(ou Maximum Segment
Size).
O MSS normalmente é calculado
com base no MTU(Maximum
Transfer Unit). O MTU é configurado em cada placa de rede ou
dispositivo de rede e possui, para redes Ethernet, o valor
padrão de 1500. Esse valor é o tamanho máximo de
bytes que o procotolo de camada física, ou Interface de Rede(na
arquitetura TCP/IP), pode enviar no
meio físico de cada vez. Portanto, se desejarmos enviar mais do
que isso, devemos fragmentar os dados em blocos de 1500 bytes antes de
enviarmos para o protocolo Ethernet.
|
Aplicação |
Mensagem
|
|
|
Transporte |
Segmento
|
|
|
Inter-rede |
Datagrama
|
|
|
Placa
de rede |
Quadro
|
|
|
Intra-rede |
Arquitetura
do TCP/IP
No entanto, acima da camada Placa de
rede(Ethernet) possuimos a camada Inter-rede(IP), que adiciona, no
mínimo,
20 bytes de cabeçalho antes de enviá-los para o protocolo
da Placa de rede. Ainda, acima da camada Inter-rede, possuímos a
camada de transporte(TCP ou UDP) que adiciona, no mínimo, 20
bytes de cabeçalho para o TCP.
Com isso, o tamanho real de dados que
podem ser enviados será o
MTU menos todos os bytes utilizados como cabeçalho nas camadas
superiores até chegar no TCP. Esse valor final é o MSS(ou
Maximum Segment Size).
Mas, além disso, o MSS deve
ser o mesmo entre os dois lados
da conexão e, por isso, negociado entre estes antes do
estabelecimento da conexão. Cada um sabe seu MTU, com isso
calcula seu MSS e o envia para a outra ponta durante o estabelecimento
da conexão. O menor MSS será o
escolhido, para evitar fragmentações nas pontas da
conexão. Mas, mesmo assim, se houver outros equipamentos de rede
intermediários que possuam MTU menor, esses causarão
fragmentações no meio do caminho. Como fazer para evitar
essas fragmentações? A resposta é o "Path MTU
Discovery".
O Path MTU Discovery envia um pacote
de tamanho máximo para o
segmento (1500 bytes se Ethernet) ou de tamanho igual ao MSS informado
no estabelecimento da conexão, marcado para não ser
fragmentado,
e aguarda que algum host no trajeto responda dizendo que não
consegue enviar o pacote sem realizar fragmentação. Este
aviso é uma mensagem de erro ICMP "Can't Fragment" de tipo 3
(destino inalcançável) e código
4(fragmentação necessária, mas bit de
não-fragmentação ativado). Normalmente, essa
mensagem ICMP carrega, também, o MTU que causou o erro. Com
isso, o Path MTU Discovery envia um novo pacote de tamanho igual ao MTU
recebido na mensagem ICMP. Esse processo se repete até que o
pacote atinja o host de destino e o Path MTU Discovery receba um
pacote-resposta desse host.
Por isso,
não é
inteligente desabilitar todos os ICMP no seu firewall, como a
maioria dos administradores de rede o fazem. Nunca deixe de receber
pacotes do tipo 3(destino inalcançável) nem do tipo
5(redirecionamento). Caso contrário, você pode acabar com
o problema relatado no item 6.
No entanto, o Path MTU Discovery calcula o MSS sobre os
cabeçalhos IP e TCP somente. Como estamos acrescentando uma
camada adicional IPSec, devemos diminuir o tamanho do cabeçalho
IPSec do valor do MSS.
Isso deve ser
feito manualmente e é por isso que o Path MTU Discovery
não funciona sobre IPSec.
Pacotes menores que o menor MSS do canal não gerarão este
erro e, por isso, vão funcionar. Como é o caso do "ping"
e páginas web pequenas.
A solução desse problema para o Path MTU Discovery
é habilitar a recepção de pacotes
ICMP tipo 3 e código 4, no
mínimo. Mas isso não resolve o problema para IPSec
já que o Path MTU Discovery desconhece essa camada adicional.
Portanto, a solução é forçar um MSS manual
quando for tentado o estabelecimento de qualquer conexão entre
as pontas do canal IPSec. Para isso, basta chamar o seguinte
código(com as modificações em GATEWAY_REMOTO e REDE_REMOTA para
a sua rede) a partir do script que carrega as regras do seu firewall:
#!/bin/bash
#Força um MSS fixo para remediar o problema do Path MTU Discovery
#ATENÇÃO:
# 1.Você deve permitir troca de pacotes ICMP do tipo echo-request e echo-reply entre os gateways LOCAL e REMOTO
# 2.Você deve permitir pacotes ICMP do tipo redirect e destination-unreachable vindos da INTERNET
# 3.Você vai precisar dos pacotes BC e IPROUTE instalados
#definição do gateway remoto e da rede remota
GATEWAY_REMOTO=200.200.200.200
REDE_REMOTA=172.16.0.0/24
#opcao de DEBUG: coloque como 1 para ativar mensagens
DEBUG=0
function compute_mss() {
#calcula o MSS para IPSec baseado no MTU fornecido como parâmetro
#retorna o valor calculado na variável MSS
local MTU
local IP_HEADER_LENGTH
local ESP_HEADER_LENGTH
local AH_HEADER_LENGTH
local IPSEC_HEADER_LENGTH
local ENCRYPTION_HEADER_LENGTH
local SUBTOTAL_DATA_LENGTH
local DISCARDED_DATA_LENGTH
local DATA_LENGTH
MTU=$1
#tamanho médio do header IP(20<->60)
IP_HEADER_LENGTH=40
#tamanho do header ESP
ESP_HEADER_LENGTH=8
#tamanho do header AH
AH_HEADER_LENGTH=12
#tamanho do header IPSec = ESP + AH
IPSEC_HEADER_LENGTH=`echo "$ESP_HEADER_LENGTH + $AH_HEADER_LENGTH" | bc`
#tamanho do header do algoritmo de encriptação
ENCRYPTION_HEADER_LENGTH=16 #CBC initial value
#cálculo do tamanho final = MSS
SUBTOTAL_DATA_LENGTH=`echo "$MTU - $IP_HEADER_LENGTH - $IPSEC_HEADER_LENGTH - $ENCRYPTION_HEADER_LENGTH" | bc`
DISCARDED_DATA_LENGTH=`echo "$SUBTOTAL_DATA_LENGTH % 16" | bc`
DATA_LENGTH=`echo "$SUBTOTAL_DATA_LENGTH - $DISCARDED_DATA_LENGTH" | bc`
MSS=$DATA_LENGTH
}
function pmtu_discovery()
{
#Efetua um PMTU discovery através de pacotes ICMP entre os gateways LOCAL e REMOTO.
#Na verdade, utiliza um algoritmo de pesquisa binária para calcular o tamanho máximo do PAYLOAD de um pacote ICMP no canal
#e, através dessa informação, calcula o PMTU
local MIN
local MAX
local MTU
local TARGET
local OK
local MEDIA
local IP_HEADER_LENGTH
local ICMP_PAYLOAD_MAX
#tamanho MÍNIMO do cabeçalho IP (20<->60 bytes)
IP_HEADER_LENGTH=20
#tamanho do cabeçalho ICMP (echo-request/echo-reply)
ICMP_HEADER_LENGTH=8
#declaracao de uma funcao em BC para retornar o valor absoluto de um número, ou seja, o valor sem sinal
LOADABS="
define abs(x) {
if (x>=0) return(x)
return(-x)
}
"
#host de destino (firewall -> interface internet)
TARGET=$1
#valor mínimo para o PAYLOAD ICMP
MIN=400
#obtem o valor do MTU da interface que será utilizada na comunicação entre os gateways
MTU=`ip route get $TARGET | xargs | sed "s/.*mtu \([[:digit:]]\+\) .*/\1/"`
#valor máximo para o PAYLOAD ICMP => MTU - IP HEADER - ICMP HEADER
MAX=`echo "$MTU-$IP_HEADER_LENGTH-$ICMP_HEADER_LENGTH" | bc`
#Path MTU Discovery através de pesquisa binaria
while [ `echo "$LOADABS abs($MIN - $MAX)" | bc` -gt 1 ]; do
#Calculamos a média entre MIN e MAX
MEDIA=`echo "scale=0;($MIN + $MAX) / 2" | bc`
if [ $DEBUG -eq 1 ]; then
echo -n "MEDIA=$MEDIA "
fi
#Enviamos o pacote ICMP:
# -s $MEDIA : com o PAYLOAD de tamanho $MEDIA
# -q : Quiet
# -M do : Com a flag DF(Don't Fragment) setada
# -W 2 : Aguardamos até 2 segundos pela resposta
# -c 1 : apenas 1 pacote
# $TARGET : para o host $TARGET
#e redirecionamos a saída para /dev/null, porque precisamos apenas do código de saída(Exit Code ou $?)
ping -s $MEDIA -q -M do -W 2 -c 1 $TARGET 1>/dev/null 2>/dev/null
OK=$?
if [ $OK == 0 ]; then
#Funcionou! Portanto, o mínimo passa a ser a média, ou seja, MIN=MEDIA
if [ $DEBUG -eq 1 ]; then
echo "[OK]"
fi
MIN=$MEDIA
else
#Não funcionou... portanto, o máximo passa a ser a média menos 1, ou seja, MAX=MEDIA-1
if [ $DEBUG -eq 1 ]; then
echo "[NOK]"
fi
MAX=`echo "$MEDIA-1" | bc`
fi
#enviamos um pacote ICMP a cada 0.5 segundos para tentar não despertar nenhum IDS ou FIREWALL
sleep 0.5
done
#o valor de $MIN será o máximo PAYLOAD do pacote ICMP que conseguiu trafegar do gateway LOCAL para o REMOTO e vice-versa
ICMP_PAYLOAD_MAX=$MIN
#agora calculamos o PMTU => PAYLOAD + ICMP HEADER + IP HEADER
PMTU=`echo "$ICMP_PAYLOAD_MAX+$ICMP_HEADER_LENGTH+$IP_HEADER_LENGTH" | bc`
}
#inicialização das variáveis
MSS=-1
PMTU=-1
#efetua o PMTU discovery até o gateway remoto. PMTU conterá o valor final.
pmtu_discovery $GATEWAY_REMOTO
#calcula o MSS baseado no PMTU retornado. MSS conterá o valor final.
compute_mss $PMTU
#incluímos as seguintes regras no IPTABLES para forçar o MSS em qualquer estabelecimento de conexões com a rede remota
iptables -I FORWARD 1 -p tcp -d $REDE_REMOTA --tcp-flags SYN,RST SYN -j TCPMSS --set-mss $MSS
iptables -I FORWARD 2 -p tcp -s $REDE_REMOTA --tcp-flags SYN,RST SYN -j TCPMSS --set-mss $MSS
iptables -I OUTPUT 1 -p tcp -d $REDE_REMOTA --tcp-flags SYN,RST SYN -j TCPMSS --set-mss $MSS
iptables -I OUTPUT 2 -p tcp -s $REDE_REMOTA --tcp-flags SYN,RST SYN -j TCPMSS --set-mss $MSS
if [ $DEBUG -eq 1 ]; then
echo "PMTU=$PMTU"
echo "MSS=$MSS"
fi
exit 0
- Sem mais nem menos, os gateways
começam a fazer "flooding" de
pacotes entre si
Na
verdade, este problema é, também, devido ao Path MTU
Discovery e, portanto, relacionado aos itens 2 a 5.
Esse sintoma aparece quando um host tenta enviar um pacote de tamanho
máximo para o segmento. Este pacote, em algum ponto
intermediário, ou até no gateway destino, é
descartado por ser grande demais. Quem descartou o pacote envia uma
resposta ICMP Can't Fragment
de retorno. O problema é que essa resposta nunca chega devido a
regras de firewall que impedem que a mesma alcance a maquina de
destino. Leia com atenção o tópico anterior que
fala sobre a ignorância de alguns administradores de rede em
relação aos pacotes ICMP.
O que acontece
quando uma mensagem resposta ICMP
"Can't
Fragment" é descartada? O Path MTU Discovery roda
sobre o TCP e, portanto, aguardará pelo "timeout" e
repetirá o envio do
mesmo segmento. Esse processo poderá se repetir indefinidamente.
Para resolver esse problema, force um MSS como mostrado no
tópico anterior.
- Consigo abrir
páginas entre as duas redes conectadas, mas
não de redes conectadas a essas
Outro problema
relacionado ao Path MTU Discovery, só que agora, não tem
nada a ver com a sua configuração. O problema é
que, provavalmente, a rede conectada que está tentando ser
acessada tem regras de firewall bloqueando qualquer tipo de pacote ICMP
e, portanto, impedindo o tráfego de segmentos TCP. Os sintomas
descritos acima também ocorrerão, porém entre sua
rede e a rede remota, não se manifestando diretamente sobre o
canal VPN.
Para resolver esse problema, utilize a solução dos itens
2 a 5.
Apêndice
A
VPN no Fedora Core 2 com SA fixas (sem IKE)
Este
apêndice disponibilizará alguns arquivos "script" para se
criar todas as possibilidades de canais IPSec sem o uso do IKE. Esses
scripts foram utilizados como forma de "prova de conceito" para o
padrão IPSec entre máquinas Fedora Core 2.
Esses scripts podem ser executados em quaisquer duas máquinas
que estejam em um mesmo domínio de colisão ethernet(mesma
rede física sem VLAN's) sem a necessidade de se interromper o
uso normal desses equipamentos. Para isso é criado um
endereço IP adicional em cada placa de rede para que estas
possam estabelecer os canais IPSec.
A máquina1 possuirá o seguinte endereço IP:
10.0.0.216
configurado através do seguinte comando:
# ifconfig eth0:1
10.0.0.216 netmask 255.255.255.0 broadcast 10.0.0.255
A máquina2 possuirá o seguinte endereço IP:
10.0.0.11
configurado através do seguinte comando:
# ifconfig eth0:1
10.0.0.11 netmask 255.255.255.0 broadcast 10.0.0.255
As seguintes combinações foram implementadas:
- AH/transport
- ESP/transport
- AH/ESP/transport
- ESP/tunnel
- ESP+Auth/tunnel
- AH/ESP/tunnel
Modo
|
máquina1
(10.0.0.216) |
máquina2
(10.0.0.11): |
| AH/transport |
ipsec-transport-on-ah-216
#!/sbin/setkey -f
flush;
spdflush;
#AH
add 10.0.0.11 10.0.0.216 ah 15700 -A hmac-sha1 "12345678901234567890";
add 10.0.0.216 10.0.0.11 ah 24500 -A hmac-sha1 "12345678901234567890";
spdadd 10.0.0.216 10.0.0.11 any -P out ipsec
ah/transport//require;
spdadd 10.0.0.11 10.0.0.216 any -P in ipsec
ah/transport//require;
|
ipsec-transport-on-ah-11
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;
#AH
add 10.0.0.11 10.0.0.216 ah 15700 -A hmac-sha1 "12345678901234567890";
add 10.0.0.216 10.0.0.11 ah 24500 -A hmac-sha1 "12345678901234567890";
spdadd 10.0.0.216 10.0.0.11 any -P in ipsec
ah/transport//require;
spdadd 10.0.0.11 10.0.0.216 any -P out ipsec
ah/transport//require;
|
| ESP/transport |
ipsec-transport-on-esp-216
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;
#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -E rijndael-cbc
"123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -E rijndael-cbc
"123456789012123456789012";
spdadd 10.0.0.216 10.0.0.11 any -P out ipsec
esp/transport//require;
spdadd 10.0.0.11 10.0.0.216 any -P in ipsec
esp/transport//require;
|
ipsec-transport-on-esp-11
#!/sbin/setkey -f
flush
ah;
flush
esp;
spdflush;
#ESP
add
10.0.0.11 10.0.0.216 esp 15701 -E rijndael-cbc
"123456789012123456789012";
add
10.0.0.216 10.0.0.11 esp 24501 -E rijndael-cbc
"123456789012123456789012";
spdadd
10.0.0.216 10.0.0.11 any -P in ipsec
esp/transport//require;
spdadd
10.0.0.11 10.0.0.216 any -P out ipsec
esp/transport//require;
|
| AH/ESP/transport |
ipsec-transport-on-ah-esp-216
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;
#AH
add 10.0.0.11 10.0.0.216 ah 15700 -A hmac-sha1 "12345678901234567890";
add 10.0.0.216 10.0.0.11 ah 24500 -A hmac-sha1 "12345678901234567890";
#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -E rijndael-cbc
"123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -E rijndael-cbc
"123456789012123456789012";
spdadd 10.0.0.216 10.0.0.11 any -P out ipsec
esp/transport//require
ah/transport//require;
spdadd 10.0.0.11 10.0.0.216 any -P in ipsec
esp/transport//require
ah/transport//require;
|
ipsec-transport-on-ah-esp-11
#!/sbin/setkey -f
flush
ah;
flush
esp;
spdflush;
#AH
add
10.0.0.11 10.0.0.216 ah 15700 -A hmac-sha1 "12345678901234567890";
add
10.0.0.216 10.0.0.11 ah 24500 -A hmac-sha1 "12345678901234567890";
#ESP
add
10.0.0.11 10.0.0.216 esp 15701 -E rijndael-cbc
"123456789012123456789012";
add
10.0.0.216 10.0.0.11 esp 24501 -E rijndael-cbc
"123456789012123456789012";
spdadd
10.0.0.216 10.0.0.11 any -P in ipsec
esp/transport//require
ah/transport//require;
spdadd
10.0.0.11 10.0.0.216 any -P out ipsec
esp/transport//require
ah/transport//require;
|
| ESP/tunnel |
ipsec-tunnel-on-esp-216
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;
#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc
"123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc
"123456789012123456789012";
spdadd 10.0.0.216 0.0.0.0/0 any -P out ipsec
esp/tunnel/10.0.0.216-10.0.0.11/require;
spdadd 0.0.0.0/0 10.0.0.216 any -P in ipsec
esp/tunnel/10.0.0.11-10.0.0.216/require;
|
ipsec-tunnel-on-esp-11
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;
#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc
"123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc
"123456789012123456789012";
spdadd 10.0.0.216 0.0.0.0/0 any -P in ipsec
esp/tunnel/10.0.0.216-10.0.0.11/require;
spdadd 0.0.0.0/0 10.0.0.216 any -P out ipsec
esp/tunnel/10.0.0.11-10.0.0.216/require;
|
| ESP+Auth/tunnel |
ipsec-tunnel-on-esp-auth-216
#!/sbin/setkey -f
flush
ah;
flush
esp;
spdflush;
#ESP+AUTH
add
10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc
"123456789012123456789012" -A hmac-sha1 "12345678901234567890";
add
10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc
"123456789012123456789012" -A hmac-sha1 "12345678901234567890";
spdadd
10.0.0.216 0.0.0.0/0 any -P out ipsec
esp/tunnel/10.0.0.216-10.0.0.11/require;
spdadd
0.0.0.0/0 10.0.0.216 any -P in ipsec
esp/tunnel/10.0.0.11-10.0.0.216/require;
|
ipsec-tunnel-on-esp-auth-11
#!/sbin/setkey -f
flush
ah;
flush
esp;
spdflush;
#ESP+AUTH
add
10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc
"123456789012123456789012" -A hmac-sha1 "12345678901234567890";
add
10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc
"123456789012123456789012" -A hmac-sha1 "12345678901234567890";
spdadd
10.0.0.216 0.0.0.0/0 any -P in ipsec
esp/tunnel/10.0.0.216-10.0.0.11/require;
spdadd
0.0.0.0/0 10.0.0.216 any -P out ipsec
esp/tunnel/10.0.0.11-10.0.0.216/require;
|
| AH/ESP/tunnel |
ipsec-tunnel-on-ah-esp-216
#!/sbin/setkey -f
flush
ah;
flush
esp;
spdflush;
#AH
add
10.0.0.11 10.0.0.216 ah 15700 -m tunnel -A hmac-sha1
"12345678901234567890";
add
10.0.0.216 10.0.0.11 ah 24500 -m tunnel -A hmac-sha1
"12345678901234567890";
#ESP
add
10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc
"123456789012123456789012";
add
10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc
"123456789012123456789012";
spdadd
10.0.0.216 0.0.0.0/0 any -P out ipsec
esp/tunnel/10.0.0.216-10.0.0.11/require
ah/tunnel/10.0.0.216-10.0.0.11/require;
spdadd
0.0.0.0/0 10.0.0.216 any -P in ipsec
esp/tunnel/10.0.0.11-10.0.0.216/require
ah/tunnel/10.0.0.11-10.0.0.216/require;
|
ipsec-tunnel-on-ah-esp-11
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;
#AH
add 10.0.0.11 10.0.0.216 ah 15700 -m tunnel -A hmac-sha1
"12345678901234567890";
add 10.0.0.216 10.0.0.11 ah 24500 -m tunnel -A hmac-sha1
"12345678901234567890";
#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc
"123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc
"123456789012123456789012";
spdadd 10.0.0.216 0.0.0.0/0 any -P in ipsec
esp/tunnel/10.0.0.216-10.0.0.11/require
ah/tunnel/10.0.0.216-10.0.0.11/require;
spdadd 0.0.0.0/0 10.0.0.216 any -P out ipsec
esp/tunnel/10.0.0.11-10.0.0.216/require
ah/tunnel/10.0.0.11-10.0.0.216/require;
|
IMPORTANTE: A
execução dos scripts deve ser feita de maneira
relacionada, ou seja, a
execução de um script que cria um canal ESP/tunnel na
máquina1 deve ser
correspondida com um script que crie um canal ESP/tunnel na
máquina2.
|
Cristiano da Cunha Duarte é
formado em Ciência da Computação pela PUC/MG,
especializado em Projeto e Aplicação de Redes de
Comunicação pela UnB e trabalha com
programação em C, C++, PHP5, Java, CORBA
e
Servidores Linux. Mais informações visite: http://cunha17.cristianoduarte.pro.br/.

Search Engine Optimization and
Free Submission