( Editar : A versão anterior só funcionava para pacotes de saída (UDP), esta versão funciona em ambas as direções (TCP e ping).)
Existem várias dicas para uma configuração como a sua: o Linux considera um pacote de entrada com um endereço de origem que corresponde a um endereço de interface de rede como um erro de roteamento (porque em circunstâncias normais indica um loop de roteamento). Além disso, por padrão, a tabela de roteamento local
mantida pelo kernel tem a prioridade mais alta, e isso impedirá que seus pacotes saiam da interface à qual está vinculada.
Pode-se resolver o segundo problema com o roteamento de políticas: Primeiro, exclua as rotas sobrepostas (que só causarão problemas):
ip route list
# overlapping routes should look like:
ip route del 192.168.42.0/24 dev mvl0 proto kernel scope link src 192.168.42.16
ip route del 192.168.42.0/24 dev mvl1 proto kernel scope link src 192.168.42.17
Em seguida, atribua à tabela local
uma prioridade mais baixa (maior valor numérico):
ip rule add pref 1000 lookup local
ip rule del pref 0
Precisamos aceitar pacotes de entrada enviando-os para a tabela local
:
ip rule add pref 100 to 192.168.42.16 iif mvl0 lookup local
ip rule add pref 100 to 192.168.42.17 iif mvl1 lookup local
enquanto todos os outros pacotes (de saída) para o resp. destino usará uma tabela especial que os força a sair na outra interface:
ip rule add pref 200 to 192.168.42.17 lookup 100
ip rule add pref 200 to 192.168.42.16 lookup 101
ip route add default dev mvl0 table 100
ip route add default dev mvl1 table 101
Além disso, temos que cuidar do primeiro problema desabilitando a filtragem de caminho reverso (se já não estiver desabilitada) e permitindo que pacotes que tenham uma fonte local sejam aceitos:
echo "0" | tee /proc/sys/net/ipv4/conf/mvl{0,1}/rp_filter
echo "1" | tee /proc/sys/net/ipv4/conf/mvl{0,1}/accept_local
Agora, ping
funciona mesmo se não estiver vinculado a uma das interfaces mvl
. TCP e UDP também funcionam, testando com socat
:
socat TCP4-LISTEN:9998,so-bindtodevice=mvl0 -
echo foo | socat - TCP4:192.168.42.16:9998,so-bindtodevice=mvl1
socat UDP4-RECV:9900,so-bindtodevice=mvl0 -
echo foo | socat - UDP4-SENDTO:192.168.42.16:9900,so-bindtodevice=mvl1