Evitando o encaminhamento infinito com dois roteadores

3

A rede em quesiton parece basicamente assim:

                     /----Inet1
                    /
H1---[111.0/24]---GW1---[99.0/24]
                                 \----GW2-----Inet2

Explicação do dispositivo

  • H1: Host com IP 192.168.111.47
  • GW1: caixa do Linux com os IPs 192.168.111.1 e 192.168.99.2, bem como o seu próprio caminho para a Internet.
  • GW2: Roteador sem fio genérico com IP 192.168.99.1 e sua própria rota para a Internet.
  • Inet1 & Inet2: Duas rotas possíveis para a internet

Em suma: H tem mais de um caminho possível para a internet.

H deve acessar somente a Internet via GW2 quando o link estiver ativo, então o GW1 tem algum roteamento baseado em política especial apenas para H1:

ip rule add from 192.168.111.47 table 991
ip route add default via 192.168.99.1 table 991

Embora isso funcione enquanto o GW2 tiver um link direto para a Internet, o problema ocorre quando esse link está inativo. O que acontece então é que o GW2 encaminha o pacote de volta ao GW1, que novamente encaminha de volta para o GW2, criando um loop infinito de TCP-pingpong. O resultado preferido é que o pacote acabou de ser descartado.

Existe algo que pode ser feito com o iptables no GW1 para evitar isso? Basicamente, uma versão amigável do iptables de "Se o pacote vem do GW2, mas se originou do H1, solte-o"

  • Nota1: É preferível não alterar nada no GW2.
  • Nota2: O H1 precisa ser capaz de falar tanto com o GW1 quanto com o GW2, e vice-versa, mas somente o GW2 deve levar à internet

TLDR; H1 só deve ter permissão de acesso à internet via GW2, mas ainda precisa ser capaz de falar com o GW1 e com o GW2.

EDIT: As interfaces para o GW1 são br0.105 para a rede '99' e br0.111 para a rede '111'. O sollution pode ou não ser obnoxiously simples, mas eu não fui capaz de produzir a sintaxe adequada do iptables, então a ajuda seria muito apreciada.

PS: Esta é uma pergunta de acompanhamento da pergunta

    
por Jarmund 12.10.2012 / 18:34

2 respostas

3

Você realmente deve corrigir seu roteiro em GW2 , se for possível. Se não estiver, você pode configurar uma solução alternativa.

Deixa:

br0.105 = interface at GW1 in the 99.0/24 network facing GW2
<mac-gw2> = the MAC address of GW2's interface in the 99.0/24 network facing GW1
<ip-h1> = IP address of H1 from the 111.0/24 network

Em seguida, adicione a regra

iptables -A FORWARD -i br0.105 -s <ip-h1> -m mac --mac-source <mac-gw2> -j REJECT

resultaria em uma mensagem de destino inacessível do ICMP enviada para <ip-h1> no caso de o pacote de <ip-h1> ser retornado de GW2 para GW1 . A ideia aqui é filtrar pelo endereço MAC, já que você parece ter várias rotas para diferentes roteadores através dessa interface e precisa diferenciar entre os roteadores de origem.

Você pode obter o endereço MAC de GW2 observando sua configuração de interface ou, se não tiver acesso a ele, observando a tabela de cache ARP de GW1 - basta executar arp -n para ver as entradas atuais no cache.

Observe que se GW1 estiver fazendo NAT para o tráfego que sai de <int2> , então <ip-h1> precisaria ser o endereço IP de <int2> , não o de H1 .

Como você pediu uma maneira de curingar o endereço MAC - não há nenhum, o módulo mac do iptables requer uma correspondência exata. Mas, obviamente, você pode roteirizar isso (rápido e sujo, adicionar cheques atendendo ao seu nível de paranóia antes de colocar em produção):

#!/bin/bash

# variables
# the IP address of GW2
IP_GW2=192.168.99.1
# the IP address of H1
IP_H1=192.168.111.47
# the configuration file containing GW2's MAC address
CONFIG_MAC_GW2="/etc/default/iptables-mac-gw2"
# the "arping" utility (used to resolve an IP address to a MAC address)
ARPING=/usr/sbin/arping

# include $CONFIG_MAC_GW2, if exists
test -f $CONFIG_MAC_GW2 && source $CONFIG_MAC_GW2
# test if $MAC_GW2 is empty or undefined
if [ ! -n "$MAC_GW2" ]; then
  MAC_GW2='$ARPING $IP_GW2 -c 1 -r'
  if [ $? == 1 ]; then
     echo \$MAC_GW2 has not been configured and could not be detected using "$ARPING $IP_GW2 -c 1 -r"
     exit 1
  fi
  # write the discovered MAC address into $CONFIG-MAC-GW2 so we don't have 
  # to resolve it on succeeding runs
  echo MAC_GW2=${MAC_GW2} > $CONFIG_MAC_GW2
fi
# [...]
iptables -A FORWARD -i br0.105 -s $IP_H1 -m mac --mac-source $MAC_GW2 -j REJECT
    
por 12.10.2012 / 19:46
0

Como o G1 é uma caixa linux, por que não apenas testar a interface externa do G2 com um teste de ping e alterar a rota padrão quando ela não está respondendo? E, se você fizer isso corretamente, você poderá cancelar automaticamente o backup quando os pings começarem a funcionar novamente.

    
por 12.10.2012 / 20:42