OpenVPN s'atura amb una queixa errno 2 sobre /dev/net/tun mentre que lsmod llista sense problemes el mòdul tun. Els dos fets són certs alhora. El mòdul proporciona un controlador, i el camí que obre el client és un node de dispositiu que alguna altra cosa ha de crear. Tractar-los com un sol objecte és la raó per la qual la reparació òbvia de recarregar el mòdul no canvia absolutament res.

Dos objectes, dos propietaris diferents

Un mòdul del nucli i un node de dispositiu són objectes independents amb cicles de vida independents. Carregar el mòdul registra un controlador, i en un sistema amb devtmpfs el nucli demana que es creï el node corresponent. En un sistema sense devtmpfs res no crea res, i el controlador es queda allà sense cap camí que hi apunti. El mòdul pot estar carregat, sa i completament inabastable a través del sistema de fitxers en el mateix moment.

Per això el text de l'error i la llista de mòduls no es contradiuen. El client obre un camí, el camí no existeix, i el nucli retorna ENOENT abans que el controlador tun sigui consultat mai. Recarregar el mòdul no pot reparar un camí absent, i crear el camí no pot reparar un controlador absent.

lsmod | grep -w tun
stat -c "%F %t:%T" /dev/net/tun
grep " /dev " /proc/mounts

devtmpfs enfront d'un mknod explícit

Normalment dos mecanismes creen aquest node, i saber quin se suposa que n'és el responsable us diu què cal reparar. devtmpfs fa que el nucli creï nodes de dispositiu en una instància muntada, i udev hi aplica propietat i permisos a sobre. Un mknod explícit és el camí manual per a imatges i espais de noms on cap dels dos s'executa en arrencar.

Compareu resultats en lloc d'intencions. Si devtmpfs està muntat a /dev i el node encara falta, el controlador no és el que suposeu, o alguna cosa va eliminar el node després de l'arrencada. Si /dev és un directori normal dins d'un rootfs desempaquetat, no hi ha cap mecanisme automàtic i qui construeix la imatge ha de crear el node.

stat -c "%F major=%t minor=%T" /dev/net/tun
# expect: character special file major=a minor=c8

On no s'executa cap dels dos mecanismes, el node s'ha de fer a mà, i l'ordre importa. Creeu primer el directori pare, perquè mknod no pot inventar-se'l, després el dispositiu de caràcters, i després un mode que el deixi escrivible només per a root. Recarregueu el mòdul abans de crear el node, i traieu un camí existent només després que ls hagi mostrat que és un directori i no un dispositiu.

sudo modprobe tun
sudo mkdir -p /dev/net
sudo mknod /dev/net/tun c 10 200
sudo chmod 600 /dev/net/tun
ls -l /dev/net/tun

El tipus que informa stat és el discriminant més ràpid, i un directori en aquest camí és la sorpresa més habitual en imatges mínimes. Un mkdir benintencionat en un Dockerfile deixa exactament això, i cap quantitat de càrrega de mòduls substitueix un directori per un dispositiu de caràcters. Major 10 amb minor 200 és la parella registrada per a tun, expressada en hexadecimal com a a i c8.

Quatre rastres, quatre causes

Quatre causes expliquen gairebé tots els casos, i cadascuna deixa un rastre diferent als registres. Comenceu per l'entorn d'arrencada. Les imatges sense disc, les plaques incrustades i les etapes d'initramfs sovint no munten ni devtmpfs ni un /devgestionat per udev, així que cap procés escriu mai el node. Després llegiu les opcions de muntatge d'allò que allotja /dev, perquè nodev permet que el camí existeixi mentre es nega a obrir-lo, i un muntatge bind pres d'un amfitrió endurit porta la bandera sense anunciar-se. Un muntatge només de lectura falla abans i més fort: mknod hi retorna EROFS, mentre que EPERM vol dir que al procés li falta la capacitat i no que el sistema de fitxers es protegeixi. Finalment, un runtime de contenidors amb el seu propi /dev tmpfs necessita que el node s'injecti al seu propi espai de noms, i el seu cgroup de dispositius ha de permetre la parella major i minor.

Comproveu la capa de política abans de tornar a canviar permisos. SELinux i AppArmor poden refusar una obertura que tots els atributs del fitxer permeten, i aquest refús apareix al registre d'auditoria i no a la sortida del client. Un canvi de permisos que no apareix mai en una denegació és temps gastat en la capa completament equivocada.

sudo journalctl -k -n 20 --no-pager
sudo ausearch -m AVC -ts recent | tail -5

Demostreu-ho amb una interfície, no amb un llistat

Un llistat correcte demostra que un camí existeix i res més. Obriu un node tun sa per llegir-lo i la crida torna amb un error, perquè el dispositiu no té semàntica de lectura i no és un fitxer normal. Aquest error és aquí el senyal d'èxit, i reconèixer-lo us estalvia perseguir-lo com si fos una fallada.

head -c 1 /dev/net/tun
head: error reading '/dev/net/tun': File descriptor in bad state

La prova decisiva crea una interfície, perquè exercita el controlador, el node i els vostres privilegis en un sol pas. Si l'addició té èxit i l'enllaç apareix, els tres funcionen. Quan falla, l'errno separa les causes: ENOENT vol dir que no hi ha cap node utilitzable, EPERM apunta a la capacitat, les banderes de muntatge o la política, i EBUSY vol dir que un altre procés ja posseeix la interfície.

sudo ip tuntap add dev tun7 mode tun
ip -brief link show tun7
sudo ip tuntap del dev tun7 mode tun

Executeu aquesta prova en el context que realment falla, perquè una unitat de servei, un contenidor o una tasca programada poden portar un conjunt de capacitats diferent del vostre intèrpret d'ordres d'inici de sessió. Una prova que passa en el context equivocat no demostra res sobre el que falla.

Quan el dispositiu no és el problema

Si la prova d'interfície té èxit i el client encara falla, el problema restant és el perfil, el context del servei o la ruta, i el dispositiu està bé. Aquest és el moment de deixar d'editar nodes de dispositiu, perquè més canvis només afegeixen distància respecte a un sistema que funciona.

Executeu les mateixes cinc comprovacions cada vegada en lloc d'inventar-ne una de nova: està el mòdul carregat sense cap mòdul rival, és el camí un dispositiu de caràcters amb el major i el minor correctes, estan netes les opcions de muntatge, porta el context del procés la capacitat, i hi ha una denegació de política a la marca de temps de la fallada. Una fallada que sobreviu a les cinc no és un problema de dispositiu, digui el que digui el missatge.

Articles relacionats