Eu tenho uma configuração multihomed com dois provedores de upstream. E eu quero limitar algumas conexões para usar apenas um provedor - conexões de saída locais que é. Então, criei uma tabela de roteamento personalizada, que tem uma rota de rede conectada diretamente e uma rota padrão:
$ ip route show table 2
default via 5.1.0.1 dev upstream_b
5.1.0.0/16 dev upstream_b scope link src 5.1.0.2
Em seguida, estou usando um seletor no iptables para adicionar fwmark a algumas conexões e regras de ip para substituir a seleção da tabela de roteamento:
# for output traffic
# restore packet mark from connection mark
iptables --table mangle --append OUTPUT -j CONNMARK --restore-mark
# for !0 packet marks bail out
iptables --table mangle --append OUTPUT -m mark ! --mark 0 -j ACCEPT
# set packet mark
iptables --table mangle --append OUTPUT -m cgroup --cgroup 0x00010002 -j MARK --set-mark 0x2
# save packet mark to connection mark
iptables --table mangle --append OUTPUT -j CONNMARK --save-mark
# for input traffic restoring mark from connmark
iptables --table mangle --append PREROUTING -j CONNMARK --restore-mark
# adding policy forwarding
ip rule add from all fwmark 2 table 2
Portanto, para algum processo [no net_cls
cgroup] especificado, suas conexões de saída atingirão a regra de marca de conexão e, em seguida, deverão ser roteadas via upstream_b
interface.
Mas isso não está funcionando (para um shell bash, que foi colocado no cgroup net_cls):
$ curl --resolve ifconfig.co:80:188.113.88.193 -v http://ifconfig.co
* Added ifconfig.co:80:188.113.88.193 to DNS cache
* Rebuilt URL to: http://ifconfig.co/
* Hostname ifconfig.co was found in DNS cache
* Trying 188.113.88.193...
* Immediate connect fail for 188.113.88.193: Network is unreachable
* Closing connection 0
curl: (7) Couldn't connect to server
O resultado anterior ocorreu enquanto a tabela de roteamento main
não tem rota padrão (ou seja, nenhuma rota para ifconfig.co).
Mas esta não é toda a história. Desde que eu tenho a configuração multihomed, geralmente há uma rota ECMP para equilibrar o tráfego através de ambos os provedores. E para o teste mencionado, obtive um resultado interessante. Os pacotes tcp-syn foram para a interface correta, mas com um endereço de origem incorreto (da outra interface).
Assim, unindo essas observações, em primeiro lugar, uma decisão de roteamento é feita com base na tabela de roteamento main
(assim, a rede é inacessível). Em seguida, enquanto um pacote é processado, ele atinge as regras de marcação e, em seguida, ocorre um reencaminhamento (com base na tabela de roteamento personalizada). Mas o endereço de origem já está definido na primeira decisão de roteamento e não é corrigido aqui.
A minha compreensão das origens do problema está correta?
Eu preciso aplicar uma tabela de roteamento não padrão para alguns processos locais e o método acima não está funcionando. A imposição poderia ser cumprida? Por exemplo, é possível acionar o recálculo do endereço de origem?
EDIT. Considerando o diagrama a seguir (a versão do kernel aqui não é moderna, mas ainda é útil; o diagrama é de link ):
Parece que a primeira decisão de roteamento e a seleção do endereço de origem do pacote são de fato realizadas antes que qualquer regra do iptables possa ser ativada (veja o canto inferior direito).