É possível bloquear o acesso à rede (de saída) de um único processo?
localhost
(na mesma máquina) para realizar seus trabalhos.
É possível bloquear o acesso à rede (de saída) de um único processo?
localhost
(na mesma máquina) para realizar seus trabalhos.
Respostas:
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 unshare
ferramenta.
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 nsenter
para inserir o outro espaço para nome.
O exemplo a seguir é executado ping
com 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
unshare -n
parece jogar "Operação não permitida" sem root
privilégios, alguma coisa que eu sinto falta?
sudo unshare -n
herda 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.
sudo unshare -n sudo -u dude bash -c 'echo Hello, my name is $USER'
@ThorSummoner bbs.archlinux.org/viewtopic.php?id=205240
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 netns
subcomandos 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 iptables
regras etc.)
sudo ip
executar os comandos ip, quando entrei no bash, apenas executei su someuser
para obter um shell não privilegiado para o usuário 'someuser'.
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
/sys/fs/cgroup/net_cls/tasks
(sem 'block' no caminho)
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
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>
--noprofile
desativa a sandbox padrão
--net=none
desativa 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 --help
relaçã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
.
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 owner
mó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.
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
groupadd no-internet
grep no-internet /etc/group
useradd -g no-internet username
usermod -a -G no-internet userName
verifique com:sudo groups userName
nano /home/username/.local/bin/no-internet
chmod 755 /home/username/.local/bin/no-internet
#!/bin/bash
sg no-internet "$@"
iptables -I OUTPUT 1 -m owner --gid-owner no-internet -j DROP
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
sg no-internet
agora.
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.
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 socket
chamada 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.
Você pode usar um programa de linha de comando chamado "proxychains" e tentar uma das seguintes possibilidades:
Configure que ele use ...
Eu mesmo não testei, então não sei se funciona ...