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:
- Namespaces do Linux na Arista
- Algumas notas sobre as interfaces veth de waldner
- Introduzindo namespaces de rede Linux por Scott Lowe
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.