NET_ADMIN num contentor VPN: o que pode mudar e onde
A capacidade permite alterações de interface, rota e firewall dentro de um único espaço de nomes de rede. Com a rede do anfitrião, esse espaço é a própria pilha do anfitrião.
NET_ADMIN é a capacidade do Linux que permite a um processo realizar administração de rede, e num contentor faz exatamente isso dentro do espaço de nomes de rede em que o processo é executado. Não é uma licença para abrir um socket nem um substituto de um dispositivo ou de uma rota. A pergunta interessante nunca é se a capacidade foi concedida, mas que espaço de nomes recebe a alteração.
O que a capacidade abrange
Dentro do seu espaço de nomes, um processo com NET_ADMIN pode subir e descer interfaces, atribuir endereços, adicionar e remover rotas e escrever regras de firewall, que é o grupo de operações que capabilities(7) reúne sob esta capacidade. Também pode ajustar definições ao nível da interface que controlam a forma como o núcleo enfileira e filtra o tráfego. Um cliente VPN normalmente precisa de algumas delas no arranque e de mais nada depois. Por isso a maioria das imagens pede mais alcance do que utiliza.
As operações fora desse espaço de nomes não estão abrangidas, e os privilégios adjacentes são separados. Ler e escrever pacotes em bruto pertence a NET_RAW, e criar um dispositivo tun exige tanto a capacidade como acesso ao nó do dispositivo. Um processo sem o dispositivo recebe um erro de permissão que parece um problema de rede e não é.
O espaço de nomes decide o raio de dano
Um contentor na sua própria rede de ponte alcança o seu próprio loopback, as suas próprias interfaces e a sua própria tabela de encaminhamento. Conceder NET_ADMIN aí permite ao cliente VPN construir um túnel sem tocar nas decisões de encaminhamento do anfitrião, que é a disposição que a maioria das imagens de contentor assume.
Mude esse contentor para a rede do anfitrião e a mesma concessão passa a editar as rotas do anfitrião e a firewall do anfitrião, porque não resta nenhum espaço de nomes separado. O cliente que devia gerir um único túnel pode então redirecionar o tráfego de toda a máquina, e um erro no seu script de desmontagem deixa ao anfitrião regras que ninguém escreveu. Nada na capacidade mudou; o contexto mudou. É por isso que o mesmo ficheiro compose se comporta de forma diferente em dois anfitriões.
Três pré-requisitos fundidos num só
As falhas de arranque em contentores VPN envolvem geralmente uma de três coisas separadas: a capacidade, o dispositivo de túnel e o suporte do núcleo para o protocolo. Conceder as três ao mesmo tempo funciona, e também torna a falha seguinte impossível de atribuir. Um fragmento compose mínimo concede a capacidade e passa o nó do dispositivo explicitamente:
services:
vpn:
image: example/vpn-client:latest
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
sysctls:
- net.ipv4.conf.all.src_valid_mark=1Leia a documentação da própria imagem para saber que sysctls precisa, porque um sysctl dentro de um contentor pode exigir um privilégio adicional ou uma definição ao nível do anfitrião. Onde a imagem só suporta o modo de espaço de utilizador, não é necessário qualquer dispositivo e a lista de capacidades reduz-se em conformidade.
Conceda a operação estreita, não o modo
O modo privilegiado entrega todas as capacidades e alarga o acesso a dispositivos ao mesmo tempo, pelo que esconde qual dos três pré-requisitos faltava. Também torna os modos de falha do contentor indistinguíveis das alterações do anfitrião. Prefira uma lista explícita mesmo quando é mais longa de escrever.
Implementações rootless e em espaços de nomes de utilizador alteram o que uma capacidade significa na prática, uma vez que o processo só a pode deter dentro de um espaço de nomes mapeado. Copiar uma lista de capacidades de um exemplo rootful para um runtime rootless e esperar o mesmo alcance é uma forma comum de perder uma tarde.
Os segredos pertencem a uma decisão separada. Deter NET_ADMIN não diz nada sobre que identidade de par o cliente apresenta, que credenciais carrega ou como são rodadas. A administração de rede não fornece confiança.
Verifique a alteração e registe por que existe a concessão
Confirme o que o contentor recebeu realmente antes de depurar o túnel. A inspeção abaixo indica as capacidades adicionadas e o modo de rede e, em seguida, mostra como é a lista de interfaces a partir de dentro:
docker inspect --format '{{.HostConfig.CapAdd}} {{.HostConfig.NetworkMode}} {{.HostConfig.Privileged}}' vpn
docker exec vpn sh -c 'grep CapEff /proc/self/status'
docker exec vpn ip -br addr
docker exec vpn ip routeSe a capacidade estiver presente e a lista de interfaces continuar vazia, o cliente falhou antes de poder criar alguma coisa, e os registos do contentor são o local seguinte a observar. Se o túnel existir mas o tráfego não fluir, a tabela de encaminhamento dentro do contentor responde à pergunta seguinte.
Teste também o caminho de desmontagem, porque um cliente que escreve regras de firewall pode deixá-las para trás. Pare o contentor e verifique novamente o conjunto de regras do anfitrião se for usada a rede do anfitrião. Uma concessão necessária apenas durante dois segundos no arranque não deve ser descrita no ficheiro compose como um requisito permanente sem uma nota que o explique.
Escreva o motivo ao lado de cada capacidade: que operação precisava dela e o que falha sem ela. Essa nota sobrevive às atualizações da imagem, e é a diferença entre uma lista de privilégios revista e uma que cresceu a copiar e colar.