Comando para executar um processo filho “offline” (sem rede externa) no Linux

14

Eu tenho um programa que gostaria de testar no modo offline sem derrubar minha rede real. Este programa ainda precisa se conectar a sockets locais, incluindo sockets de domínio unix e loopback. Ele também precisa escutar no loopback e ficar visível para outros aplicativos.

Mas as tentativas de se conectar a uma máquina remota devem falhar.

Eu gostaria de ter um utilitário que funcionasse como strace / unshare / sudo e simplesmente executasse um comando com a Internet (e LAN) oculta e tudo o mais ainda funcionando:

$ offline my-program-to-test

Esta pergunta tem sugestões para a resposta: Bloquear o acesso à rede de um processo?

Há algumas sugestões, como executar outro usuário e manipular iptables, ou unshare -n . Mas em ambos os casos eu não conheço o encantamento para obter soquetes de domínio unix e loopback para serem compartilhados com o sistema principal - as respostas para essa pergunta só me dizem como descompartilhar a rede inteira . p>

O programa que estou testando ainda precisa se conectar ao meu servidor X e dbus e até mesmo ser capaz de escutar em loopback para conexões de outros aplicativos no sistema.

Idealmente, eu gostaria de evitar a criação de chroots ou usuários ou VMs ou algo semelhante, já que se torna tão irritante quanto desconectar o cabo de rede. ou seja, o ponto da questão é como posso tornar isso tão simples quanto um sudo .

Eu adoraria que o processo funcionasse 100% normalmente, exceto que as chamadas de rede especificando um endereço não local falhariam. O ideal é manter o mesmo uid, mesmo homedir, mesmo pwd, tudo mesmo, exceto ... offline.

Estou usando o Fedora 18, por isso as respostas não suportáveis do Linux estão bem (esperadas, até mesmo).

Estou feliz em resolver isso escrevendo um programa em C, se é isso que está envolvido, então as respostas que envolvem a escrita C estão bem. Eu simplesmente não sei o que o programa C precisaria fazer para revogar o acesso à rede externa, mantendo a rede local.

Qualquer desenvolvedor que tente suportar o "modo offline" provavelmente apreciará esse utilitário!

    
por Havoc P 16.10.2013 / 21:30

2 respostas

8

A resposta tradicional é executar o programa como outro usuário e usar iptables -m owner . Dessa forma, a configuração da rede é compartilhada. No entanto, com o advento dos namespaces, há uma maneira mais fácil.

Com namespaces, você não compartilha a rede e cria um link de rede virtual se precisar de acesso limitado à rede.

Para compartilhar soquetes de domínio unix, tudo que você precisa é ter um kernel recente o suficiente, após este patch de 2010 , então 2.6.36 ou superior (que é o caso em todas as distribuições atuais no momento da escrita, exceto RHEL / CentOS).

Execute o programa em seu próprio namespace IP. Antes de iniciar o programa, estabeleça uma interface de ethernet virtual. Não parece haver muita documentação; Eu encontrei o encantamento certo em alguns blogs:

No snippet abaixo, eu uso o ns_exec é o este wrapper em torno de setns listado em a man page para mostrar o lado do host do link de rede a partir do processo em execução no namespace restrito. Você realmente não precisa disso: você pode configurar o lado do host do link de fora do namespace restrito. Fazê-lo a partir de dentro apenas facilitar o controle de fluxo, caso contrário, você precisa de alguma sincronização para configurar o link depois de ter sido estabelecido, mas antes de iniciar o seu programa.

unshare -n -- sh -c '
  # Create a virtual ethernet interface called "confined",
  # with the other end called "global" in the namespace of PID 1
  ip link add confined type veth peer name global netns 1

  # Bring up the confined end of the network link
  ip addr add 172.16.0.2/30 dev confined
  ip link set confined up

  # Bring up the global end of the network link
  ns_exec /proc/1/ns/net ifconfig global 172.16.0.1 netmask 255.255.255.252 up

  # Execute the test program
  exec sudo -E -u "$TARGET_USER" "$0" "$@"
' /path/to/program --argument

Você precisa fazer tudo isso como root. A introdução de namespaces de usuário no kernel 3.8 pode tornar isso possível sem permissões especiais, exceto a configuração da extremidade global do link de rede .

Eu não sei como compartilhar localhost entre os dois namespaces. Interfaces ethernet virtuais criam uma ponte ponto-a-ponto. Você pode usar as regras de encaminhamento iptables para redirecionar o tráfego de / para lo , se desejado.

    
por 16.10.2013 / 23:56
0

/!!\ This is probably not a valid answer as this will take all of your traffic down with you, not just a single pid's traffic.

Eu não usei isso, mas acho que você poderia usar o Comcast:

link

definido para 100% de perda de pacotes

Mais uma vez, eu não testei isso, mas, teoricamente, modificado de seu readme você pode fazer:

Linux

No Linux, você pode usar iptables para descartar pacotes de entrada e saída.

$ iptables -A INPUT -m statistic --mode random --probability 1 -j DROP $ iptables -A OUTPUT -m statistic --mode random --probability 1 -j DROP

Como alternativa, você pode usar tc , que suporta algumas opções adicionais.

$ tc qdisc change dev eth0 root netem reorder 0 duplicate 0 corrupt 1

Para redefinir:

$ tc qdisc del dev eth0 root netem

    
por 17.06.2015 / 23:55