Como usar diferentes interfaces de rede para diferentes processos?

59

Eu tenho duas interfaces de rede em um PC Linux e preciso definir manualmente a interface que um determinado processo usará.

O programa (Twinkle softphone) não tem uma opção semelhante, por isso acredito que deve ser definido externamente.

Como eu posso fazer isso?

Editar: Não estou tentando vincular um processo do servidor a uma interface específica, mas fazer com que um programa cliente entre em contato com um servidor usando uma interface específica.

Andrea Spadaccini
fonte
os clientes também usam o bind / connect, consulte a documentação do bind.c.txt de como forçar o ircII (um programa irc-client) para um determinado ip: 'Exemplo no bash para usar seu IP virtual como seu endereço de origem de saída para o ircII: BIND_ADDR = "seu-virt-ip" LD_PRELOAD =. / Bind.so ircII '
akira
Encontrei uma abordagem diferente aqui, espero que seja útil (espero que o roteamento da política do kernel descrito esteja ativado por padrão hoje em dia): kindlund.wordpress.com/2007/11/19/…
Savvas Radevic

Respostas:

48

você pode substituir o código em tempo de execução pelo uso de LD_PRELOAD (@windows você pode usar uma técnica semelhante chamado desvios , muito fantasia). o que isso faz é informar o vinculador dinâmico para carregar primeiro todas as bibliotecas no processo que você deseja executar e, em seguida, adicionar um pouco mais sobre ele. você normalmente usa assim:

% LD_PRELOAD=./mylib.so ls

e com isso você muda o que lsfaz.

para o seu problema, eu tentaria http://www.ryde.net/code/bind.c.txt , que você pode usar como:

% BIND_ADDR="ip_of_ethX" LD_PRELOAD=./bind.so twinkle

aqui está como você constrói:

% wget http://www.ryde.net/code/bind.c.txt -O bind.c
% gcc -nostartfiles -fpic -shared bind.c -o bind.so -ldl -D_GNU_SOURCE

um tutorial mais longo é http://daniel-lange.com/archives/53-Binding-applications-to-a-specific-IP.html

hacks e ferramentas semelhantes:

akira
fonte
7
Uau, que diabos. 1
sinni800
11
Oi, isso parece um truque muito bom, mas não funciona para mim. Eu tenho dois modems 3G que, quando conectados, abrem duas interfaces (ppp0 e ppp1). Se eu tentar forçar um dos dois IPs, sempre acabo saindo com a mesma interface (vejo isso porque tenho duas instâncias do wireshark, uma para cada interface). Também removi as impressões de depuração do bind.c e, de fato, vejo que a biblioteca "sobrecarregada" está carregada, portanto não sei por que ela não funciona.
Andrea Spadaccini
3
LD_PRELOAD será ignorado se o seu UID efetivo não for o mesmo que o seu UID real.
Matthias krull 24/03/11
O force_bindprojeto por Catalin M. Boie suporta IPv6
BurnsBA
Funciona muito bem, mas foi necessário adicionar #include <arpa / inet.h> para que a compilação tenha êxito.
anno
31

netns ip podem fazer isso.

TL; DR: crie namespaces de rede, associe interfaces a eles e execute "ip netns exec NAME cmd ..."

Apenas verifique se sua distribuição suporta redes IP ... (o Backtrack 5r3 não, enquanto o Kali suporta;))

EM MAIS DETALHES:

#create netns
ip netns add myNamespace
#link iface to netns
ip link set eth0 netns myNamespace
#set ip address in namespace
ip netns exec myNamespace ifconfig eth0 192.168.0.10/24 up
#set loopback (may be needed by process run in this namespace)
ip netns exec myNamespace ifconfig lo 127.0.0.1/8 up
#set route in namespace
ip netns exec myNamespace route add default gw 192.168.0.1
#force firefox to run inside namespace (using eth0 as outgoing interface and the route)
ip netns exec myNamespace firefox

Por que isso é melhor do que ligar o ip via LD_PRELOAD? Porque LD_PRELOAD não controla a rota que os processos usam. Ele usará a primeira rota.

E como sempre usa a mesma rota, será padronizada a interface registrada na rota. (Que não é o que queremos)

olivervbk
fonte
2
Por favor, tente adicionar mais detalhes à sua resposta.
Renju Chandran chingath
4
não faça isso no servidor remoto se eth0 for a interface de rede pública ..
ygrek
11
a última linha deve serip netns exec myNamespace firefox
meuh 20/06/2015
11
Use "sudo ip netns del <namespace-name>" para remover o namespace quando necessário!
Eduardo Lucio
11
@EduardoLucio deve ser possível para executá-lo gosto: sudo ip netns exec myNamespace su -u someUser -c firefox
olivervbk
2

Eu não acho que é possível forçar um processo a usar uma certa interface.

No entanto, acho que você pode jogar com o ipchain / iptables e forçar que uma determinada porta em que seu processo esteja ouvindo obtenha apenas pacotes provenientes de uma interface específica.

COMO FAZER: http://tldp.org/HOWTO/IPCHAINS-HOWTO.html

thetarro
fonte
2
Os dois cargos mais votados provam o contrário.
Paul Gear
2

Baseado na resposta @olivervbk abaixo é o meu!

Execute todos os comandos como "root".

Use o comando ...

ip a

... para descobrir o nome da interface de rede que você deseja usar.

Execute os comandos abaixo como o modelo ...

ip netns add [INTERFACE_NAME]_ns
ip link set dev [INTERFACE_NAME] netns [INTERFACE_NAME]_ns
ip netns exec [INTERFACE_NAME]_ns ifconfig [INTERFACE_NAME] 10.1.1.10/24 up
ip netns exec [INTERFACE_NAME]_ns ifconfig lo 127.0.0.1/8 up
ip netns exec [INTERFACE_NAME]_ns route add default gw 10.1.1.1
ip netns exec [INTERFACE_NAME]_ns dhcpcd [INTERFACE_NAME]
ip netns exec [INTERFACE_NAME]_ns sudo -b -u [YOUR_USER] [APP_NAME] 2> /dev/null 1> /dev/null &
  • [INTERFACE_NAME] - substitua pelo nome da interface de rede escolhida.
  • [YOUR_USER] - Substitua pelo seu nome de usuário.
  • [APP_NAME] - Nome do aplicativo que será executado no espaço para nome "[INTERFACE_NAME] _ns". Ex .: "firefox".

NOTA I: Os sinalizadores "-b -u" no comando "sudo" permitem que o aplicativo seja executado usando seu usuário (não "root") e liberando o terminal em segundo plano. O 2> /dev/null 1> /dev/null &trecho é para impedir que as saídas de "[APP_NAME]" sejam impressas no terminal.
NOTA II: Os valores de ip "10.1.1.10" e "10.1.1.1" são arbitrários.
NOTA III: Para trabalhar para mim, tive que executar o dhcpcd [INTERFACE_NAME]comando.

Para remover o espaço para nome, use ...

ip netns del [INTERFACE_NAME]_ns

... ou ...

ip -all netns delete

... para remover qualquer um que exista.

Eduardo Lucio
fonte
1

Geralmente, se um programa não tem opção para configurar a interface de escuta, ele está escutando em TODAS as interfaces. (Você pode verificar isso com lsof -i).

Criar regras de firewall do iptables que descartam o tráfego de entrada direcionado para suas portas nas interfaces nas quais você não deseja que seja visível é a coisa mais fácil de fazer.

LawrenceC
fonte
1

Alternativa I:

Usando ld_preload para forçar o gateway da interface https://github.com/Intika-Linux-Network/App-Route-Jail

Forçar um aplicativo a usar uma interface de rede específica

Precisamos encontrar qual gateway a interface de rede está usando e forçar esse gateway para nosso aplicativo preso e, assim, forçar o aplicativo a se vincular a uma interface de rede específica

  • Como encontrar o gateway da interface (existem muitas soluções para encontrar o gateway, aqui estão alguns comandos que permitem encontrar o gateway usado)
$ route
$ route -n
$ ip rule list
$ ip route show
$ netstat -rn
$ cat /etc/network/interfaces
$ cat /etc/sysconfig/network-scripts/ifcfg-eth0
$ traceroute www.google.com
$ ip route show 0.0.0.0/0 dev eth0

Por gateway de aplicativo

  • Compilar App-Route-Jail
git clone https://github.com/Intika-Linux-Network/App-Route-Jail.git
cd Approute-Utils
chown 755 make.sh
./make.sh
  • Adicionar uma rota para os futuros pacotes marcados (para o aplicativo preso) neste exemplo 192.168.1.1é usado como gateway forçado; essa regra de rota não afeta outros aplicativos; essa manipulação deve ser feita apenas uma vez na inicialização do sistema, por exemplo, se você desejar use esta solução diariamente
ip rule add fwmark 10 table 100
ip route add default via 192.168.1.1 table 100
  • Inicie o aplicativo que você deseja prender
MARK=10 LD_PRELOAD=./mark.so firefox
  • Testando o endereço IP da WAN
MARK=10 LD_PRELOAD=./mark.so wget -qO- ifconfig.me

Alternativa II:

O Firejail https://firejail.wordpress.com/ pode forçar um aplicativo a usar uma rede específica, mas a compatibilidade é limitada.

firejail --dns=8.8.8.8 --net=eth0 --ip=192.168.1.1
intika
fonte
Observe que a marca não é possível para usuários normais, você deve executar como root.
jornane 9/08
-2

Por que você deseja que um programa use uma interface diferente daquela conectada ao servidor para conversar com esse servidor? E se o sistema não estiver usando a interface conectada a um servidor para conversar com esse servidor, é um problema no nível do sistema (tabela de roteamento) e não tem nada a ver com o processo que deseja conversar com esse servidor.

Servidores diferentes em redes IP têm endereços IP diferentes. O kernel deve saber qual interface usar para alcançar um endereço IP específico com base na tabela de roteamento. Se você estiver tentando conversar com dois servidores diferentes com o mesmo endereço IP, o sistema ficará confuso (porque, entre outras coisas, apenas indexa as conexões internamente pelo endereço de destino). Você pode fazer isso funcionar, mas é uma correção no nível do sistema que envolve a colocação de um servidor em uma rede lógica separada, conectada apenas à máquina por meio do software NAT.

Portanto, se eles tiverem endereços IP diferentes, use rotas para selecionar a interface correta. Se eles tiverem o mesmo endereço IP, você precisará usar o NAT para que eles pareçam ter endereços IP diferentes para o sistema.

David Schwartz
fonte
3
Em primeiro lugar, pode haver várias rotas válidas entre o cliente e o servidor, mas com diferentes características adequadas para diferentes tipos de tráfego; por exemplo, UMTS (dados celulares) pode custar dinheiro, mas tem um alcance maior que o WiFi, mas ambos são mais lentos que uma conexão de fibra. Se os provedores upstream fizerem a filtragem de origem (ou NAT), você não terá outra opção a não ser enviar a interface 'certa'. Em segundo lugar, influenciar o roteamento não é o único motivo para selecionar um endereço de origem. Mesmo quando ambos os endereços estão na mesma interface pode ser útil para controlar quais é obrigado a, ao iniciar ligações, como o servidor
Um caso é se você possui IPs públicos diferentes e deseja iniciar um novo processo em cada um para conexões de saída.
Rfraile 15/02