Quali capacità Linux richiede il tuo processo VPN?
La configurazione dell’interfaccia, le rotte, l’accesso ai dispositivi e i socket ordinari sono privilegi separati. Nomina l’operazione fallita prima di concedere CAP_NET_ADMIN.
Un demone VPN ha bisogno di operazioni di rete privilegiate anche se le applicazioni ordinarie aprono socket in uscita senza alcun privilegio. È in questo varco che iniziano la maggior parte degli errori di capacità: qualcuno vede un errore di permessi, concede l’intero insieme e il servizio funziona per motivi che poi nessuno sa spiegare. Il percorso qui sotto parte dall’operazione fallita, la associa a una sola autorità e poi controlla il contesto in cui il processo viene realmente eseguito. Eseguire come root senza restrizioni è una risposta valida per alcuni deployment, ma dovrebbe essere una decisione e non un valore predefinito.
Parti dall’operazione fallita
Leggi l’errore prima di leggere un tutorial. «Operazione non permessa» su un cambio di interfaccia, il rifiuto di aprire un nodo di dispositivo e un errore di bind su una porta bassa sono tre problemi diversi con tre concessioni diverse. Se il processo parte e fallisce solo al primo cambio di rotta, questo dice anche che la creazione dell’interfaccia è già riuscita, il che restringe molto la risposta.
Riproduci l’errore con il servizio fermo, poi avvialo in primo piano sotto lo stesso utente se l’implementazione lo consente. Un errore che puoi vedere è meglio di una riga di log che devi indovinare, e rende evidente la differenza tra un problema di capacità e un rifiuto di SELinux o AppArmor.
Associa ogni operazione a una sola autorità
La tabella è una mappa iniziale, non un sostituto della documentazione dell’implementazione:
| Operation | Usual authority | Watch for |
|---|---|---|
| Create or configure tun/tap | CAP_NET_ADMIN in the relevant namespace | Creating the device and opening it are separate steps |
| Add routes, rules, firewall entries | CAP_NET_ADMIN | Same capability, different namespace than you think |
| Open /dev/net/tun | Device permissions, not a capability | Group membership or a udev rule may be enough |
| Raw sockets | CAP_NET_RAW | Needed by some user-space tunnel implementations |
| Bind a port below 1024 | CAP_NET_BIND_SERVICE | Irrelevant for most modern tunnel ports |
Le due righe di quella tabella sono quelle che le persone confondono. Aprire /dev/net/tun è una questione di permessi di file; chiedere al kernel di configurare ciò che hai aperto è una questione di capacità. Concedere CAP_NET_ADMIN non sistema un nodo di dispositivo che il tuo utente di servizio non può leggere, e sistemare il nodo non ti dà autorità sulle rotte. Controlla entrambe le cose prima di cambiarne una.
Anche WireGuard nel kernel e i programmi di tunnel in spazio utente non hanno gli stessi requisiti. La via del modulo del kernel configura un’interfaccia esistente tramite netlink, mentre un’implementazione in spazio utente può aver bisogno anche del dispositivo e, per alcuni trasporti, di socket grezze.
Leggi il contesto: servizio, container o shell
Una capacità nello spazio dei nomi di rete dell’host può avere effetti molto maggiori della stessa operazione dentro uno stack deliberatamente isolato. Un runtime di container parte di solito con un insieme di limiti ridotto; aggiungere NET_ADMIN a un container che condivide la rete dell’host è una concessione molto più ampia che aggiungerla a uno con il proprio spazio dei nomi di rete e senza mount dell’host.
Per le unità systemd leggi ciò che viene realmente applicato e non ciò che il file dell’unità sembra dire: systemctl show -p CapabilityBoundingSet -p AmbientCapabilities riporta i valori effettivi, che possono essere impostati da un drop-in che hai dimenticato. Chiedi il valore effettivo, mai quello previsto. Le capacità ambient contano perché un servizio non root perde capacità attraverso exec senza di esse.
Prendi come base la configurazione supportata del pacchetto o dell’immagine. Non aggiungere permessi di socket grezze o modalità privilegiata perché un altro tutorial li ha elencati per un altro strumento; quel ragionamento non trasferisce nulla e ti costa l’isolamento che hai pagato. In caso di dubbio, non concedere nulla e leggi le note dell’implementazione per l’operazione esatta che ti serve.
Osserva cosa succede dopo la caduta dei privilegi
Molti demoni partono privilegiati, configurano l’interfaccia, poi passano a un utente non privilegiato e mantengono il tunnel. Da quel punto il processo non può più aggiungere una rotta, riscrivere una regola del firewall o aprire un nuovo dispositivo privilegiato, il che va bene finché una riconnessione non ha bisogno esattamente di questo. Le letture di file e l’esecuzione di hook successive possono fallire per lo stesso motivo.
Prova l’intero ciclo di vita e non il primo secondo: avvio, rinnovo o riconnessione e pulizia all’arresto. Un primo successo nella creazione dell’interfaccia non dimostra che ogni operazione privilegiata successiva funzionerà ancora, e il guasto di solito compare ore dopo in produzione.
Le implementazioni che tengono il tunnel aperto durante un cambio di utente di solito lo abbinano a opzioni per conservare il tunnel e le chiavi. Lato systemd, la domanda equivalente è se l’insieme di capacità dell’unità sopravvive al cambio di utente che hai configurato.
Registra la concessione e il suo motivo
Annota la concessione esatta, l’operazione che abilita e l’errore che ha corretto. Una riga nelle note di deployment — «CAP_NET_ADMIN nello spazio dei nomi di rete dell’unità, necessario per i cambi di rotta dopo una riconnessione» — basta a impedire che la persona successiva allarghi di nuovo la concessione.
Poi rileggi l’insieme effettivo dopo ogni aggiornamento. I fornitori aggiungono funzioni, le immagini cambiano i valori predefiniti e una capacità inutile l’anno scorso può diventare portante senza che nessuno se ne accorga.