Bloquear o acesso à rede de um processo?

74

É possível bloquear o acesso à rede (de saída) de um único processo?

Larkee
fonte
6
Como você pretende identificar o processo? PID, nome, caminho?
24413 Marco Marco
11
Que acesso você deseja bloquear? Alguns programas usam o acesso à rede via localhost(na mesma máquina) para realizar seus trabalhos.
vonbrand
Consulte também LD_PRELOAD ou similar para impedir o acesso à rede , se o processo estiver cooperando.
Gilles

Respostas:

78

Com o Linux 2.6.24+ (considerado experimental até 2.6.29), você pode usar namespaces de rede para isso. Você precisa ter os 'namespaces de rede' habilitados no seu kernel ( CONFIG_NET_NS=y) e no util-linux com a unshareferramenta.

Então, iniciar um processo sem acesso à rede é tão simples quanto:

unshare -n program ...

Isso cria um espaço para nome de rede vazio para o processo. Ou seja, é executado sem interfaces de rede, incluindo nenhum loopback . No exemplo abaixo, adicionamos -r para executar o programa somente depois que os IDs de usuário e grupo efetivos atuais foram mapeados para os de superusuário (evite o sudo):

$ unshare -r -n ping 127.0.0.1
connect: Network is unreachable

Se o seu aplicativo precisar de uma interface de rede, você poderá configurar uma nova:

$ unshare -n -- sh -c 'ip link set dev lo up; ping 127.0.0.1'
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=32 time=0.066 ms

Observe que isso criará um novo loopback local . Ou seja, o processo gerado não será capaz de acessar portas abertas do host 127.0.0.1.


Se você precisar obter acesso à rede original dentro do espaço para nome, poderá usar nsenterpara inserir o outro espaço para nome.

O exemplo a seguir é executado pingcom o namespace da rede usado pelo PID 1 (é especificado por meio -t 1):

$ nsenter -n -t 1 -- ping -c4 example.com
PING example.com (93.184.216.119) 56(84) bytes of data.
64 bytes from 93.184.216.119: icmp_seq=1 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=2 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=3 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=4 ttl=50 time=139 ms

--- example.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 134.621/136.028/139.848/2.252 ms
Michał Górny
fonte
4
unshare -nparece jogar "Operação não permitida" sem rootprivilégios, alguma coisa que eu sinto falta?
Baldrs
11
Talvez uma pergunta estúpida ... esse espaço para nome também se aplica a processos filhos / processos chamados do aplicativo não compartilhado?
27515 bonanza
3
Sim. É herdado por todos os filhos gerados após alternar o namespace.
Michał Górny
2
Parece que qualquer programa que eu gostaria de compartilhar, por exemplo, sudo unshare -nherda o direito de root. Como preciso que o sudo chame o compartilhamento, estou pensando em como posso garantir que o programa chamado não tenha direitos de root.
Bonanza #
3
Um revestimento para restringir o processo a um usuário. Apenas sudo duas vezes: sudo unshare -n sudo -u dude bash -c 'echo Hello, my name is $USER'@ThorSummoner bbs.archlinux.org/viewtopic.php?id=205240
Jakub Bochenski
21

O Linux possui um recurso chamado namespaces de rede que permite essencialmente ter várias pilhas de rede na mesma máquina e atribuir uma a um programa ao executá-lo. Esse é um recurso normalmente usado para contêineres, mas você também pode usá-lo para realizar o que deseja.

Os ip netnssubcomandos gerenciam isso. Criar um novo espaço para nome da rede sem acesso a nada é fácil, é o estado padrão de um novo espaço para nome:

root@host:~# ip netns add jail

Agora, se você alternar para esse espaço para nome, poderá configurá-lo com bastante facilidade. Você provavelmente desejará falar sobre isso, e é isso:

root@host:~# ip netns exec jail /bin/bash
root@host:~# ip addr add 127.0.0.1/8 dev lo
root@host:~# ip link set dev lo up
root@host:~# exit

Agora, quando você deseja executar seu comando sem rede, basta executá-lo nessa prisão:

root@host:~# ip netns exec jail su user -c 'ping  8.8.8.8'
connect: Network is unreachable

A rede é, como desejado, inacessível. (Você pode fazer todos os tipos de coisas interessantes, pois uma pilha de rede separada inclui iptablesregras etc.)

derobert
fonte
Embora eu precisasse sudo ipexecutar os comandos ip, quando entrei no bash, apenas executei su someuserpara obter um shell não privilegiado para o usuário 'someuser'.
sage
11

Você pode usar o iptables e mover esse processo para um cgroup:

mkdir /sys/fs/cgroup/net_cls/block
echo 42 > /sys/fs/cgroup/net_cls/block/net_cls.classid

iptables -A OUTPUT -m cgroup --cgroup 42 -j DROP

echo [pid] > /sys/fs/cgroup/net_cls/block/tasks
Jan Mueller
fonte
11
como remover o pid de que as tarefas apresentar sua dando erro quando im tentando remover ou excluir dados a partir desse ficheiro embora im com usuário root
pkm
@pkm para permitir rede de volta, você só precisa ecoar [pid] para /sys/fs/cgroup/net_cls/tasks(sem 'block' no caminho)
Grief
10

Sim, com perfil de aparato personalizado, ou seja,

/usr/bin/curl {
    ...

    # block ipv4 acces
    deny network inet,
    # ipv6 
    deny network inet6,
    # raw socket
    deny network raw,

}

Mas, dessa forma, você precisará gerar uma lista de arquivos permitidos para acessar também, todo o procedimento pode ser um pouco complicado. E veja o documento de ajuda aqui

margarida
fonte
7

Você pode usar a sandbox firejail (deve funcionar nos kernels com o recurso seccomp).

Para usá-lo basta fazer

firejail --noprofile --net=none <path to executable>

--noprofiledesativa a sandbox padrão --net=nonedesativa a rede

Eu acredito que a maioria das distros já fornece pacotes, mas mesmo que não façam o firejail, praticamente não há dependências além de construir a cadeia de ferramentas e o kernel habilitado para namespace / seccomp.

Existem alguns outros recursos interessantes do firejail que podem ser mostrados com firejail --helprelação à rede (como fornecer apenas interface de loopback ou bloquear ip / dns etc.), mas isso deve fazer o trabalho. Além disso doesn't require root.

pruzinat
fonte
5

Você não pode fazer isso apenas com o iptables. Esse recurso existiu brevemente , mas não pôde ser feito para funcionar de maneira confiável e foi abandonado.

Se você pode executar o processo como um ID de usuário dedicado, o iptables pode fazê-lo com o ownermódulo:

iptables -A OUTPUT -m owner --uid-owner 1234 -j DROP

Veja exemplos em Iptables: correspondência do tráfego de saída com o conntrack e o proprietário. Funciona com quedas estranhas , regra iptables / pf para permitir apenas o aplicativo / usuário XY?

Se você puder executar o processo em seu próprio contêiner, poderá fazer firewall desse contêiner de forma independente (até torná-lo completamente desconectado da rede).

Um módulo de segurança pode filtrar o acesso de um processo aos recursos de rede. A resposta de warl0ck dá um exemplo com o AppArmor.

Gilles
fonte
3

Solução 1: Firewall:

Poderíamos usar firewalls como Douane ou Opensnitch, mas esses aplicativos não são 100% eficientes ou estão em um estágio inicial de desenvolvimento (tem muitos bugs etc. a partir de 2019)

Solução 2: Kernel MAC:

Os MACs do kernel podem ser usados ​​como um firewall mais conhecido: Tomoyo , Selinux e Apparmor. Essa solução é a melhor quando se trata de estabilidade e eficiência (solução de firewall), mas na maioria das vezes a configuração é algo complicado.

Solução 3: Firejail:

O Firejail pode ser usado para bloquear o acesso à rede de um aplicativo, o que não requer raiz, pois qualquer usuário pode se beneficiar

firejail --noprofile --net=none command-application

Solução 4: cancelar o compartilhamento

O Unshare pode iniciar um aplicativo em um namesapece diferente sem rede, mas isso requer que a solução root firejail faça quase exatamente a mesma coisa, mas não requer root

unshare -r -n application-comand

Solução 5: Proxify:

Uma solução é proxy do aplicativo para um proxy nulo / falso . Podemos usar tsocks ou proxybound . Aqui estão alguns detalhes sobre a configuração

Solução 6: Iptables:

Uma outra solução fácil é o iptables, que pode ser configurado para bloquear um aplicativo

  1. Criar, validar novo grupo ; adicione usuários necessários a este grupo:
    • Crio: groupadd no-internet
    • Validar: grep no-internet /etc/group
    • Adicionar usuário: useradd -g no-internet username

      Nota: Se você estiver modificando um usuário já existente, execute: usermod -a -G no-internet userName verifique com:sudo groups userName

  2. Crie um script no seu caminho e torne-o executável:
    • Crio: nano /home/username/.local/bin/no-internet
    • Executável: chmod 755 /home/username/.local/bin/no-internet
    • Conteúdo: #!/bin/bash
                    sg no-internet "$@"

  3. Adicione a regra iptables para descartar a atividade de rede para o grupo no-internet :


   4. Verifique, por exemplo no Firefox, executando:

  • no-internet "firefox"

   5. Caso deseje fazer uma exceção e permitir que um programa acesse a rede local :

  • iptables -A OUTPUT -m owner --gid-owner no-internet -d 192.168.1.0/24 -j ACCEPT
  • iptables -A OUTPUT -m owner --gid-owner no-internet -d 127.0.0.0/8 -j ACCEPT
  • iptables -A OUTPUT -m owner --gid-owner no-internet -j DROP

   6. Torne permanente

   Uma maneira de aplicar a regra iptables na inicialização é adicionar a regra como um serviço com systemd

cat /usr/lib/systemd/system/nonet.service
[Unit]
Description=Nonet group iptable update
After=network.target
After=xsession.target
After=iptables.service
After=shorewall.service

[Service]
Type=oneshot
RemainAfterExit=true
StandardOutput=journal
ExecStart=/bin/bash /home/user/Scripts/Nonet.iptables.sh
intika
fonte
11
Este é um guia seriamente excelente. Obrigado. Embora, para mim, meu comando no-internet nunca pareça passar o parâmetro, estou usando sg no-internetagora.
Zach Bloomquist
@Zach eu atualizei minha resposta, você pode estar interessado em firejail;)
intika 28/04
2

Depende da distro que você está usando, mas esse é um recurso geralmente incluído no sistema MAC do sistema operacional. Como afirmado anteriormente, o Ubuntu ou o AppArmor do SuSE podem fazer isso. Se você estiver usando o RHEL, poderá configurar o SELinux para permitir ou negar o acesso a um número de porta específico com base no rótulo do processo em execução. Isso é tudo o que pude encontrar depois de pesquisar rapidamente no Google, mas provavelmente existem mais recursos on-line, se você olhar mais e isso lhe der uma idéia geral.

Bratchley
fonte
2

Você pode usar o seccomp-bpf para bloquear algumas chamadas do sistema. Por exemplo, talvez você queira bloquear asocket chamada do sistema para impedir que o processo crie soquetes FD.

Eu escrevi um exemplo dessa abordagem que impede a socketchamada do sistema para trabalhar usando o libseccomp. O resumo é (sem verificação de erros):

scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
seccomp_arch_add(ctx, SCMP_ARCH_NATIVE);
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(socket), 1, SCMP_CMP(0, SCMP_CMP_EQ, pf));
seccomp_load(ctx);
execvp(argv[1], argv+1);

Isso não precisa de privilégios de root.

Uma sandbox completa é muito mais complexa, portanto, você não deve usar esta ordem un para bloquear programas não-cooperativos / maliciosos.

ysdx
fonte
Você poderia dar um exemplo de como usar isso? Requer privilégios de root para funcionar?
22917 bonanza
-4

Você pode usar um programa de linha de comando chamado "proxychains" e tentar uma das seguintes possibilidades:

Configure que ele use ...

  • ... um proxy que não existe? (Não sei se o executará com um proxy "inválido")
  • ... um proxy local (como "tinyproxy", "squid", "privoxy", ...) que limita o acesso à internet? (Basta usar ACLs)

Eu mesmo não testei, então não sei se funciona ...

drkhsh
fonte
A publicação de soluções não testadas geralmente não é uma boa ideia.
Twirrim 16/08/16
proxychains com um proxy inexistente (como localhost: 1234 ou similar) pode realmente ser uma abordagem sólida, no entanto
phil294