O serviço arranca, o registo queixa-se de que não consegue abrir o dispositivo tun, e as rotas nunca aparecem. Execute capsh --print na sua shell e cap_net_admin está mesmo ali, o que faz a falha parecer impossível. O que difere entre a sua shell e a unidade é a transição de privilégios, não a vontade do núcleo de conceder a capacidade. Percorra as quatro verificações abaixo por ordem e pare na primeira que explique a diferença.

Separe uma capacidade ausente de um dispositivo oculto

Duas falhas parecem iguais na linha de registo. Um processo sem CAP_NET_ADMIN não consegue criar ou configurar a interface do túnel, e um processo cujo sandbox esconde /dev/net/tun não consegue abri-la de todo. Acrescentar capacidades não corrige o segundo caso.

Verifique se o dispositivo existe dentro do espaço de nomes do serviço antes de editar seja o que for. PrivateDevices=yes é uma linha de endurecimento comum que remove o nó tun por completo, e um ProtectSystem restritivo pode tornar o caminho de configuração só de leitura de uma forma que se lê como um erro de permissões. Ambos produzem linhas de registo que mencionam o túnel, e é por isso que as capacidades levam a culpa. Confirme primeiro que o nó está presente e é abrível, e só depois avance.

Saiba que conjunto de capacidades está a observar

O Linux mantém os conjuntos permitido, efetivo, herdável, limite e ambiente, e o conjunto ambiente é o que sobrevive a um exec de um utilizador que não é root. As capacidades de ficheiro no binário podem transferir direitos permitidos e efetivos no exec, mas apenas enquanto nada na cadeia bloquear essa transferência.

É aqui que sudo engana as pessoas. Um comando executado através de sudo -u inicia uma nova transição de privilégios e o conjunto ambiente desaparece, pelo que a mesma verificação que tem sucesso como root falha ali. O gestor de serviços é ainda outra transição, e não concede nada ambiente a menos que a unidade o diga.

Conceda a capacidade na unidade, não num wrapper

Uma secção de serviço mínima para um túnel que tem de criar um dispositivo e instalar rotas lê-se assim.

[Unit]
Description=OpenVPN client, office profile
After=network-online.target

[Service]
Type=notify
User=openvpn
Group=openvpn
NoNewPrivileges=yes
AmbientCapabilities=CAP_NET_ADMIN
CapabilityBoundingSet=CAP_NET_ADMIN
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/office.conf

AmbientCapabilities coloca o direito no conjunto ambiente antes de o processo arrancar, e CapabilityBoundingSet impede o processo de deter algo fora dessa lista. NoNewPrivileges=yes bloqueia a obtenção de privilégios através de setuid ou capacidades de ficheiro, enquanto a capacidade que a unidade concede explicitamente continua a aplicar-se. Acrescente CAP_NET_BIND_SERVICE apenas quando o serviço tiver de ligar uma porta baixa, e nunca acrescente CAP_SYS_ADMIN só porque um tópico de fórum o fez.

Se a unidade envolve o binário em sudo, remova o wrapper. O systemd já aplica User=, e essa camada extra é a razão mais provável para o conjunto ambiente estar vazio.

Verifique contra o processo vivo, não contra o ficheiro da unidade

Leia o que o gestor aplicou realmente e depois leia o processo que gerou.

unit=openvpn-client@office
systemctl show -p User -p AmbientCapabilities "$unit"
systemctl show -p MainPID --value "$unit" | xargs -r getpcaps
grep -E '^Cap(Eff|Amb)' /proc/$(systemctl show -p MainPID --value "$unit")/status

Se a unidade lista a capacidade e CapEff continua sem ela, algum drop-in está a sobrepor a definição ou um passo ExecStartPre está a mudar o ambiente. Procure o nome da unidade nos diretórios drop-in antes de assumir que o ficheiro principal é a autoridade, porque um ficheiro posterior ganha em silêncio. Se tanto a unidade como o processo mostram a capacidade e o túnel continua a falhar, volte às verificações de dispositivo e de caminho em vez de alargar o conjunto limite. Alargá-lo esconde a causa real e deixa o serviço mais privilegiado do que estava.

Prefira largar os privilégios depois do arranque

OpenVPN pode arrancar com privilégios e depois descer para uma conta sem privilégios através das suas próprias opções user e group, com persist-key e persist-tun a manter o túnel utilizável depois. Essa disposição estreita a janela em que o processo detém direitos, e muitas vezes encaixa melhor do que arrancar todo o daemon sem privilégios com capacidades permanentes.

Seja qual for o modelo escolhido, reinicie a unidade e repita as verificações após um reinício, porque um serviço que funciona a partir de uma shell root interativa e falha no arranque é normalmente uma diferença de capacidade, dispositivo ou permissões de ficheiro. Anote as definições da unidade ao lado da saída de capacidades do processo, para que o próximo revisor veja se uma atualização de pacote ou um drop-in deslocou o limite.

Artigos relacionados