LXD-containern öppnar inte /dev/net/tun? Kontrollera unix-char-posten
LXD måste skicka värdens TUN-enhet till containern innan en VPN-klient kan använda den. Se vad unix-char lägger till, vad den inte gör, och hur du verifierar det.
LXD exponerar en teckenenhet från värden för en container genom att lägga till en enhetsnod, inte genom att lära gästen skapa en. Om containern saknar /dev/net/tun kan värden ha enheten och gästen ändå inte kunna öppna den. unix-char-posten är administratörshalvan av den vägen, och den är medvetet snävare än en privilegierad container. Därför förtjänar värdnoden och containernoden varsin kontroll.
Mekanismen är kort nog att hålla i sikte: LXD löser en värdssökväg, skapar en motsvarande nod inne i instansen och lägger till enheten i containerns enhets-cgroup. Därefter behöver gästprocessen sin egen behörighet och förmåga för att använda noden till något.
Vad unix-char-posten faktiskt ändrar
En unix-char-enhet säger åt LXD att exponera en teckenenhet från värden på en vald sökväg inne i containern. Posten har tre delar som spelar roll: enhetsetiketten administratören använder, sökvägen source på värden och path som gästen ser. Bara de två sista beskriver själva enheten. Ett skrivfel i någon av dem ger en nod på en plats som klienten aldrig öppnar.
På värden är enheten vanligtvis /dev/net/tun. Inne i containern kan du behålla samma sökväg eller välja en annan, men sökvägen måste matcha det VPN-klienten förväntar sig. Att behålla /dev/net/tun undviker ett andra konfigurationsproblem, eftersom de flesta klienter öppnar den sökvägen utan att fråga.
Administratören tillämpar posten när instansen startar eller när enheten ansluts varmt. Den kopierar ingen drivrutin till gästen och skapar inget tunnelgränssnitt. Den gör noden synlig och tillåter åtkomst genom containerns enhetskontrollgrupp.
Deklarera enheten på instansen, inte inne i gästen
Lägg till posten från LXD-administrationskontexten, och namnge instansen och en etikett du känner igen senare. För en container som heter vpnbox är kommandot:
lxc config device add vpnbox tun unix-char source=/dev/net/tun path=/dev/net/tun
lxc config device show vpnbox
Etiketten tun är lokal för instansens konfiguration. Den är inte ett gränssnittsnamn och behöver inte matcha något i gästen. Om en profil redan tillhandahåller samma enhet skapar en andra post en konflikt i stället för redundans, så granska den effektiva konfigurationen först.
Att redigera filer inne i containern är fel lager. En mknod i ett startskript kan se ut att fungera på en privilegierad container och sedan försvinna vid återskapande eller misslyckas på en mindre privilegierad. Administratören äger instansens enhetsuppsättning; låt den också äga noden.
Anpassa ägarskap och läge till gästprocessen
unix-char-posten kan sätta uid, gid och mode för noden inne i containern. Använd dem för att matcha kontot som kör VPN-klienten, i stället för att öppna enheten för alla användare eller växla containern till privilegierat läge.
Synlighet är inte samma sak som behörighet. En nod som ägs av root med läge 600 är synlig för tjänsten som körs som opriviligierad användare och kan ändå inte öppnas av den. Kontrollera gästkontot först, sätt sedan ägarskapet till det kontot och håll läget inte bredare än klienten behöver.
Processen behöver också förmågan att konfigurera ett tunnelgränssnitt, vanligtvis CAP_NET_ADMIN i containerns nätverksnamnrymd. Att skicka enheten ger inte den förmågan, och att ge förmågan tillhandahåller inte enheten; det är oberoende krav.
Vet vad posten inte ger
En synlig nod är inte en fungerande VPN. Klientpaketet måste fortfarande installeras, profilen måste fortfarande vara giltig och tjänsten måste fortfarande starta. Autentisering, rutter och DNS är fortfarande klientens arbete, och ett fel där är inte bevis för att enhetsposten är fel.
systemd kan lägga till en annan begränsning. En unit med DeviceAllow eller en härdad enhetspolicy kan neka åtkomst till en nod som containeradministratören har tillhandahållit. Kontrollera unitens enhetspolicy när noden finns men tjänsten rapporterar ett behörighetsfel, och ändra den policyn i stället för att bredda containern.
Varm anslutning är valfri och explicit. En post med required=false kräver en källsökväg och kan dyka upp eller försvinna när värdens enhet ändras. Den livscykeln passar hårdvara som kommer och går; för en TUN-enhet som VPN:en behöver vid start kan en valfri post låta tjänsten starta innan dess förutsättning finns.
Verifiera synlighet, öppning och gränssnitt i den ordningen
Bekräfta först noden inne i den avsedda containern. Sökvägen, huvud- och minornumren och ägarskapet bör matcha värdens enhet och posten du lade till. En saknad nod betyder att administratören inte tillämpade posten, eller tillämpade den på en annan instans.
lxc exec vpnbox -- ls -l /dev/net/tun
lxc exec vpnbox -- sh -c 'test -c /dev/net/tun && echo char-device-ok'
Bekräfta sedan att tjänstekontot kan öppna den. Ett kort test som det kontot skiljer ett ägarproblem från ett tjänsteproblem. Starta till sist klienten och bekräfta att ett tunnelgränssnitt visas; bara det tredje steget bevisar hela vägen, eftersom de två första kan passera medan klientprofilen eller förmågan fortfarande är fel.
Notera instansen, enhetsetiketten, värdkällan, gästsökvägen och det ägande kontot när ändringen godkänns. De fem värdena är vad en senare återskapning, migrering eller profiländring måste bevara, och de är mycket lättare att jämföra än ett behörighetsfel utan sammanhang.