Imagens de contêiner podem carregar todos os binários e arquivos de configuração do OpenVPN de que precisam e ainda assim falhar na primeira chamada de rede. O erro menciona /dev/net/tun porque a aplicação pediu ao kernel uma interface TUN e o contêiner não tinha nem o nó de dispositivo nem a capacidade de criar um. São duas permissões separadas, e corrigir uma deixa a outra exatamente onde estava.

Separá-las custa um comando para cada. A mensagem de erro seguinte diz em qual fronteira você realmente estava.

O nó de dispositivo e a capacidade são duas portas

O nó de dispositivo é um objeto do sistema de arquivos, então um contêiner precisa vê-lo no seu próprio espaço de nomes de montagem. A capacidade é uma permissão, então o processo precisa de CAP_NET_ADMIN no espaço de nomes onde a interface será criada. Passar o dispositivo sem a capacidade dá um nó que abre e um ioctl que falha. Conceder a capacidade sem o dispositivo deixa a aplicação incapaz de abrir qualquer coisa, e é por isso que as duas costumam aparecer juntas nos exemplos.

A configuração devices do Docker mapeia o dispositivo do host para dentro do contêiner, enquanto o cap_add ajusta o conjunto de capacidades. Um bind mount do mesmo caminho coloca o arquivo à vista sem aplicar a semântica de acesso ao dispositivo.

Reproduza fora do arquivo Compose

Antes de editar o serviço, verifique se o host tem o dispositivo e se um contêiner nu consegue criar uma interface. O comando abaixo é deliberadamente mínimo, e seu único propósito é separar um problema do host de um problema de compose. Se ele falhar, nenhuma alteração no compose ajudará.

ls -l /dev/net/tun
docker run --rm --cap-add NET_ADMIN --device /dev/net/tun:/dev/net/tun alpine sh -c 'apk add -q iproute2 && ip tuntap add dev tun9 mode tun && ip link show tun9'

Um nó ausente no host significa que o módulo tun não está disponível, o que é uma correção do lado do host e não do contêiner. Um nó que existe mas não abre dentro do contêiner aponta para o acesso ao dispositivo, e a mensagem dirá permission denied em vez de no such file. A ordem dessas duas falhas é todo o diagnóstico. Anote qual você viu antes de mudar uma opção.

Os erros depois do TUN são problemas diferentes

Assim que a interface aparece, a próxima falha tem outro dono. Erros de autenticação significam que o túnel chegou ao servidor e as credenciais foram rejeitadas, então mudanças de capacidade não ajudarão. Um túnel que se estabelece enquanto as aplicações ainda falham aponta para rotas, encaminhamento, resolução de DNS dentro do contêiner ou a própria disposição de rede do contêiner. Cada uma dessas é uma pergunta comum de rede que a permissão TUN não pode responder. Repetir o teste original após cada mudança impede que as falhas se fundam numa única impressão.

Copiar cada configuração de um exemplo que funciona é como uma correção mínima se torna uma definição de serviço ilegível. Traga apenas as que esta implantação precisa e anote por que cada uma está ali.

Verifique a interface dentro do contêiner

Verifique a interface e o conjunto de capacidades de dentro do contêiner em execução e não do host. Os comandos abaixo mostram o nó de dispositivo, a lista de capacidades e se uma interface pode ser criada. Execute-os no mesmo contêiner que executa o cliente, e instale as ferramentas se a imagem for mínima.

ls -l /dev/net/tun
capsh --print | grep -i net_admin
ip link add dev tun9 type tun && ip link show tun9

Uma capacidade presente no bounding set mas ausente do effective set comporta-se de forma diferente de uma que nunca foi concedida, e o capsh mostra as duas. Se o nó existe e a capacidade está lá enquanto a criação ainda falha, o ambiente de execução está impondo outra coisa, como um perfil seccomp ou uma política AppArmor que restringe a operação. Essa é uma terceira fronteira, documentada pelo ambiente de execução e não pela aplicação.

Anote as flags do contêiner, a imagem e o erro exato de cada tentativa. A próxima pessoa que ler essa nota poderá saber qual porta estava fechada sem repetir toda a investigação.

Artigos relacionados