Como 'não compartilhar -n' sem mudar para root?

0

Gostaria de executar um shell que se comporta exatamente como o pai, mas sem rede. Por que eu tenho que su <login> após unshare ?

    
por sevo 02.08.2018 / 15:41

1 resposta

1

Estou surpreso que você ainda possa su user , afaik depois que o kernel do Linux 3.19 o comando su possa ficar confuso.

O comando unshare não é flexível o suficiente para fazê-lo: permite apenas um mapeamento para root. Você precisa mapear para si mesmo, depois de unshare , mas antes de qualquer garfo / exec escrevendo "<user> <user> 1" para /proc/self/uid_map (e mesmo para /proc/self/gid_map ). Todos os kernels recentes também precisam escrever primeiro deny a /proc/$$/setgroups : todos os grupos suplementares (por exemplo: vídeo) terão que ser perdidos, isso é inevitável, como acontece com unshare -U/-r .

Aqui está um programa muito simples C apenas como prova de conceito, que não faz nenhuma verificação para apenas fazer o que você pediu, mas somente se executado por um usuário com uid / gid 1000/1000 : perder a rede. Sinta-se à vontade para melhorá-lo.

#define _GNU_SOURCE
#include <sched.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <unistd.h>

int main(int argc, char *argv[]) {
    int fd;

    unshare(CLONE_NEWUSER|CLONE_NEWNET);
    fd=open("/proc/self/setgroups",O_WRONLY);
    write(fd,"deny",4);
    close(fd);
    fd=open("/proc/self/uid_map",O_WRONLY);
    write(fd,"1000 1000 1",11);
    close(fd);
    fd=open("/proc/self/gid_map",O_WRONLY);
    write(fd,"1000 1000 1",11);
    close(fd);
    execvp(argv[1],argv+1);
}

Se o arquivo é chamado de removenet.c , compile-o com gcc -o removenet removenet.c .

$ id
uid=1000(user) gid=1000(user) groups=1000(user),44(video)
$ ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128 
eth0@if11        UP             10.0.3.66/24 fe80::216:3eff:fe6a:c1e9/64 
$ ./removenet bash
$ id
uid=1000(user) gid=1000(user) groups=1000(user),65534(nogroup)
$ ip -br a
lo               DOWN           

Note também que o novo namespace de rede tem sua interface lo iniciando, e como você não é root, não é possível configurá-lo.

Você pode executar variantes deste programa para reverter para o seu antigo usuário após tornar-se root com, por exemplo, unshare -r -n -m , alterando novamente para um novo namespace de usuário. Isso permite configurar alguns ambientes primeiro, como /sys de montagem para não ver as interfaces anteriores, trazendo a interface lo para cima, etc. Veja minha resposta para uma pergunta semelhante lá (com o mesmo código, você só precisa adicione novamente |CLONE_NEWNET ):

cancelar o compartilhamento --pasta do usuário root -map para o uid / username original após a configuração

Para ser claro: não conheço nenhum utilitário padrão que possa fazer o que você está pedindo com um simples comando shell. Então você tem que recorrer para usar uma outra linguagem que não shell: C, python, ... há mesmo interface de função estrangeira ctypes.sh para o bash .

Esta outra resposta minha também fornece algumas informações adicionais e uma outra "linguagem", o depurador gdb:

como cancelar a rede de compartilhamento para o processo atual

    
por 02.08.2018 / 21:50