Pergunta

Eu estou trabalhando em um sistema de servidor baseado em Linux no qual existem duas interfaces de rede, ambos na mesma sub-rede (por enquanto, vamos apenas dizer que eles são 172.17.32.10 & 172.17.32.11). Quando eu enviar dados para um host na rede, eu gostaria de especificar qual interface no meu servidor os dados são transmitidos por diante. Eu preciso ser capaz de mudar de um interface para o outro (ou talvez até mesmo transmitir em ambos) em software (regras de roteamento estático não irá funcionar para esta aplicação).

Eu achei uma pergunta relacionada em StackOverflow que sugeriu o uso da biblioteca netlink para modificar rotas na mosca. Esta intuitivamente parece que ele deve funcionar, mas eu queria saber se havia outras opções para fazer isso mesmo resultado.

Foi útil?

Solução

Sem querer ofender, mas a resposta sobre o uso bind () é completamente errado. bind () vai controlar o endereço IP de origem colocado dentro do cabeçalho do pacote IP. Ele não controla qual interface será utilizada para enviar o pacote: do kernel tabela de roteamento será consultado para determinar qual interface tem o menor custo para chegar a um determinado destino. (* Ver nota)

Em vez disso, você deve usar um sockopt SO_BINDTODEVICE. Isto faz duas coisas:

  • Os pacotes será sempre de saída a partir da interface especificada, independentemente do que o kernel tabelas de roteamento diz.
  • Somente pacotes que chegam na interface especificada serão entregues à tomada. Pacotes que chegam em outras interfaces não vai.

Se você tiver múltiplas interfaces que você deseja alternar entre, eu sugiro a criação de uma tomada por interface. Porque você também só recebem pacotes para a interface que você obrigado a, você vai precisar adicionar todos esses soquetes para o seu select() / poll() / o que você usa.

#include <net/if.h>

struct ifreq ifr;

memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "eth1", sizeof(ifr.ifr_name));
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
            (void *)&ifr, sizeof(ifr)) < 0) {
    perror("SO_BINDTODEVICE failed");
}

(* nota) Bind() para um endereço IP interface pode levar a confundir, mas ainda assim o comportamento correto. Por exemplo, se você bind() para o endereço IP para eth1, mas a tabela de roteamento envia o pacote para fora eth0, então um pacote aparecerá no fio eth0 mas carregando o endereço IP de origem da interface eth1. Isso é estranho, mas permitiu, apesar de pacotes enviados de volta para o endereço IP eth1 estaria de volta roteado para eth1. Você pode testar isso usando um sistema Linux com duas interfaces IP. Eu tenho um, e fez testá-lo, e bind() não é eficaz na condução do pacote para fora uma interface física.

Apesar de tecnicamente permitido, dependendo da topologia isso não pode, contudo, trabalho. Para atenuar ataques distribuídos de negação de serviço onde os atacantes utilizar falsos endereços IP de origem, muitos roteadores agora realizar encaminhamento caminho inverso (RPF) verifica. Pacotes com um endereço IP de origem no caminho "errado" pode ser descartada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top