Roteamento para vários uplinks / provedores

5

Eu tenho um PC com duas conexões de internet. O primeiro é uma interface Ethernet para se conectar à minha rede local e acessar a Internet através do meu roteador. O segundo usa um modem GSM para se conectar ao ppp.

Eu gostaria de poder usar cada conexão independentemente ao especificar a interface, por exemplo:

ping -I eth0 www.google.com
ping -I ppp0 www.google.com

E poder usar eth0 por padrão se nenhuma interface for selecionada e a conexão via eth0 funcionar, mas ppp0 se a conexão via eth0 não funcionar.

Eu li o artigo e criei as seguintes regras:

# Main table
ip route add 10.0.0.0/24 dev eth0 src 10.0.0.100
ip route add 10.64.64.64 dev ppp0 src 10.123.122.101
ip route add default via 10.0.0.1

# Specific tables
ip route add 10.0.0.0/24 dev eth0 src 10.0.0.100 table eth0
ip route add default via 10.0.0.1 table eth0
ip route add 10.64.64.64 dev ppp0 src 10.123.122.101 table ppp0
ip route add default via 10.64.64.64 table ppp0

# Rules
ip rule add from 10.0.0.100 table eth0
ip rule add from 10.123.122.101 table ppp0

No começo parece funcionar. No entanto, a tabela eth0 parece nunca ser usada. Eu esperava que o seguinte acontecesse:

ping -I eth0 www.google.ch    # Use default gateway in table eth0
ping -I ppp0 www.google.ch    # Use default gateway in table ppp0
ping www.google.ch            # Use default gateway (main)

No entanto, se eu remover o gateway padrão (principal), a interface eth0 não funcionará. Obviamente, há algo que não entendo. Você pode me explicar como conseguir o que eu quero?

EDIT de acordo com a resposta @derobert:

Eu testei a seguinte configuração, mas ainda recebo o mesmo erro (ok para ppp0 mas não funciona para eth0).

Rotas:

# ip rule list
0:      from all lookup local
1500:   from 10.0.0.100 lookup eth0
1501:   from 10.123.122.101 lookup ppp0
2000:   from all fwmark 0x1 lookup eth0
2001:   from all fwmark 0x2 lookup ppp0
32766:  from all lookup main
32767:  from all lookup default

# ip route list table eth0
10.0.0.0/24 dev eth0  src 10.0.0.100
default via 10.0.0.1 dev eth0

# ip route list table ppp0
10.64.64.64 dev ppp0  src 10.123.122.101
default via 10.64.64.64 dev ppp0

# ip route list table main
10.64.64.64 dev ppp0  src 10.123.122.101
192.168.1.0/24 dev eth1  src 192.168.1.1
10.0.0.0/24 dev eth0  src 10.0.0.100

Firewall:

# iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

# iptables -L -t mangle
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
CONNMARK   all  --  anywhere             anywhere            CONNMARK restore
RETURN     all  --  anywhere             anywhere            mark match !0x0
MARK       all  --  anywhere             anywhere            MARK set 0x1
MARK       all  --  anywhere             anywhere            MARK set 0x2

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MARK       all  --  anywhere             anywhere            MARK set 0x1
MARK       all  --  anywhere             anywhere            MARK set 0x2
CONNMARK   all  --  anywhere             anywhere            CONNMARK save

# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
SNAT       all  --  10.0.0.1             anywhere            to:10.0.0.100
SNAT       all  --  10.64.64.64          anywhere            to:10.123.122.101

Eu removi todas as outras regras de firewall para ter certeza de que elas não interferem. Eu obtenho este resultado:

# ip route get 8.2.1.1 from 10.0.0.100
8.2.1.1 from 10.0.0.100 via 10.0.0.1 dev eth0

# ip route get 8.2.1.1 from 10.123.122.101
8.2.1.1 from 10.123.122.101 via 10.64.64.64 dev ppp0

# ping -I ppp0 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=45 time=350.108 ms
64 bytes from 8.8.8.8: seq=1 ttl=45 time=349.768 ms
64 bytes from 8.8.8.8: seq=2 ttl=45 time=329.671 ms
^C
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 329.671/343.182/350.108 ms

128# ping -I eth0 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
^C
--- 8.8.8.8 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss

As regras parecem estar corretas, mas obviamente há outro problema. Eu realmente não entendo o papel do SNAT aqui. Eu adicionei as regras para refletir a configuração da resposta, pois elas podem estar erradas.

    
por slepasteur 28.03.2013 / 16:59

2 respostas

3

Eu tenho uma configuração um pouco mais complicada, que também inclui NAT e roteamento dinâmico (interno) na máquina.

Existem várias partes para isso. Vamos começar com as regras:

Maginot:~# ip rule ls
0:      from all lookup local 
1000:   from all lookup main 
1500:   from 173.167.51.136/29 lookup comcast 
1501:   from 76.160.165.106/29 lookup cavtel 
1502:   from 151.200.251.90/31 lookup vzdsl 
1502:   from 151.200.251.92/31 lookup vzdsl 
1502:   from 151.200.251.94 lookup vzdsl 
2000:   from all fwmark 0x1 lookup comcast 
2001:   from all fwmark 0x2 lookup cavtel 
2002:   from all fwmark 0x3 lookup vzdsl 
2500:   from all lookup comcast 
2501:   from all lookup cavtel 
2502:   from all lookup vzdsl 
32767:  from all lookup default 

(As tabelas recebem nomes em /etc/iproute2/rt_tables )

Como você pode ver, temos três ISPs no momento e temos dois endereços IP estáticos em cada um deles. As regras 1500-1502 enviam o tráfego desses endereços IP de origem para a interface apropriada. As regras 2000-2002 enviam o tráfego com uma determinada marca de firewall (chegaremos a isso) na interface apropriada. Regras 2500-2502 dão a ordem de preferência de nossos ISPs, para o tráfego que não foi atribuído a um ISP já. Se um deles cair, você remove a regra para ele e o próximo da lista é usado.

Cada tabela de roteamento é bastante trivial:

Maginot:~# ip route ls table comcast
default via 173.167.51.142 dev comcast 

(Local e main têm muito mais coisas, mas isso é diretamente conectado e rotas internas, respectivamente. O padrão da tabela é vazio).

Em seguida, é importante que uma vez que uma conexão seja atribuída a um ISP, ela permaneça ali (incluindo conexões de entrada). Tentar movê-lo é impossível, já que temos endereços IP diferentes em cada interface, e nossos provedores realmente têm filtragem de caminho inverso. Nós os mantemos no mesmo ISP com regras de firewall.

Lembre-se que o SNAT é feito após o roteamento, portanto, as políticas ip rule não ajudarão. Você tem que usar outra coisa (talvez este seja o seu problema?)

iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j RETURN # if already set, we're done
iptables -t mangle -A PREROUTING -i wan                                       -j MARK --set-mark $MARK_CAVTEL
iptables -t mangle -A PREROUTING -i comcast                                   -j MARK --set-mark $MARK_COMCAST
iptables -t mangle -A PREROUTING -i vz-dsl                                    -j MARK --set-mark $MARK_VZDSL

iptables -t mangle -A POSTROUTING -o wan     -j MARK --set-mark $MARK_CAVTEL
iptables -t mangle -A POSTROUTING -o comcast -j MARK --set-mark $MARK_COMCAST
iptables -t mangle -A POSTROUTING -o vz-dsl  -j MARK --set-mark $MARK_VZDSL
iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark

Isto é do script de shell que o configura; as variáveis $MARK_… correspondem às marcas que você vê nas regras acima. Bastante simples: restaure a marca de conexão (lembre-se, as marcas são por pacote); se houver uma marca agora (da marca de conexão), terminamos. Caso contrário, defina a marca para aquela baseada na interface envolvida.

Note que restaura a marcação antes do roteamento, e só salva depois. E a marca é definida para a interface de saída, independentemente (o que é discutível).

Finalmente, existem as regras reais do NAT. Temos vários prefixos locais, esse código é executado em um loop for com $local definido para cada:

iptables -t nat -A POSTROUTING -s $local -o wan     -j SNAT --to-source 76.160.165.106
iptables -t nat -A POSTROUTING -s $local -o comcast -j SNAT --to-source 173.167.51.137
iptables -t nat -A POSTROUTING -s $local -o vz-dsl  -j SNAT --to-source 151.200.251.90

(Nota: Existem muito mais regras, incluindo alguns DNAT para servidores DMZ, etc ... Acho que copiei todos os relevantes.)

    
por 09.04.2013 / 19:02
0

Você vai querer configurar o peso do dispositivo eth0 para ter uma prioridade maior que o dispositivo ppp0.

exemplo:

ip route append default scope global nexthop via 10.0.0.1 dev eth0 weight 2 nexthop via 10.64.64.65 dev ppp0 weight 3
    
por 28.03.2013 / 18:12