/dev/net/tun yok ama tun yüklü: aygıt düğümünü onarın
Yüklü bir tun modülü, aygıt düğümünün var olduğunu kanıtlamaz. Sürücüyü düğümden ayırın, sırasıyla yeniden oluşturun ve bir arayüzle doğrulayın.
OpenVPN hakkında bir errno 2 şikâyetiyle dururken /dev/net/tun ise lsmod tun modülünü rahatça listeler. İki olgu aynı anda doğrudur. Modül bir sürücü sağlar ve istemcinin açtığı yol, başka bir şeyin oluşturması gereken bir aygıt düğümüdür. İkisini tek bir nesne saymak, modülü yeniden yükleme gibi apaçık onarımın neden hiçbir şeyi değiştirmediğinin sebebidir.
İki nesne, iki farklı sahip
Bir çekirdek modülü ile bir aygıt düğümü, bağımsız yaşam döngülerine sahip bağımsız nesnelerdir. Modülün yüklenmesi bir sürücü kaydeder ve devtmpfs bulunan bir sistemde çekirdek ilgili düğümün oluşturulmasını ister. devtmpfs olmayan bir sistemde hiçbir şey hiçbir şey oluşturmaz ve sürücü ona işaret eden hiçbir yol olmadan orada oturur. Modül aynı anda yüklü, sağlıklı ve dosya sistemi üzerinden tamamen erişilemez olabilir.
Bu yüzden hata metni ile modül listesi birbirine çelişmez. İstemci bir yol açar, yol yoktur ve çekirdek tun sürücüsüne hiç sorulmadan önce ENOENT döndürür. Modülü yeniden yüklemek eksik bir yolu onaramaz, yolu oluşturmak da eksik bir sürücüyü onaramaz.
lsmod | grep -w tun
stat -c "%F %t:%T" /dev/net/tun
grep " /dev " /proc/mounts
devtmpfs ile açık bir mknod arasındaki fark
Normalde o düğümü iki mekanizma oluşturur ve hangisinin sorumlu olması gerektiğini bilmek neyi onaracağınızı söyler. devtmpfs çekirdeğin bağlı bir örnekte aygıt düğümleri oluşturmasını sağlar ve udev bunların üzerine sahiplik ile izinleri uygular. Açık bir mknod her ikisinin de önyüklemede çalışmadığı imajlar ve ad alanları için elle izlenecek yoldur.
Niyetleri değil sonuçları karşılaştırın. devtmpfs /dev üzerine bağlıysa ve düğüm hâlâ yoksa, sürücü sandığınız değildir ya da bir şey düğümü önyüklemeden sonra kaldırmıştır. /dev açılmış bir rootfs içinde sıradan bir dizinse, otomatik bir mekanizma yoktur ve imajı oluşturan kişi düğümü oluşturmalıdır.
stat -c "%F major=%t minor=%T" /dev/net/tun
# expect: character special file major=a minor=c8
İki mekanizmanın da çalışmadığı yerde düğüm elle yapılmalıdır ve sıra önemlidir. Önce üst dizini oluşturun, çünkü mknod onu uyduramaz, sonra karakter aygıtını, sonra yalnızca root için yazılabilir bırakan bir kip. Düğümü oluşturmadan önce modülü yeniden yükleyin ve var olan bir yolu ancak ls bunun bir aygıt değil dizin olduğunu gösterdikten sonra kaldırın.
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
En hızlı ayırıcı, stat tarafından bildirilen türdür ve o yolda bir dizin bulunması asgari imajlarda en sık rastlanan sürprizdir. İyi niyetle yazılmış bir mkdir Dockerfile içinde tam olarak bunu bırakır ve ne kadar modül yüklenirse yüklensin bir dizinin yerini karakter aygıtı almaz. Major 10 ile minor 200, tun için kayıtlı çifttir ve onaltılık olarak a ve c8 diye ifade edilir.
Dört iz, dört neden
Dört neden neredeyse her durumu açıklar ve her biri günlüklerde farklı bir iz bırakır. Önyükleme ortamından başlayın. Disksiz imajlar, gömülü kartlar ve initramfs aşamaları çoğu zaman ne devtmpfs ne de udev tarafından yönetilen bir /devbağlar, bu yüzden hiçbir süreç düğümü asla yazmaz. Ardından /devneyi barındırıyorsa onun bağlama seçeneklerini okuyun, çünkü nodev yolun var olmasına izin verir ama açmayı reddeder ve sağlamlaştırılmış bir ana makineden alınan bind bağlaması bu bayrağı kendini duyurmadan taşır. Salt okunur bağlama daha erken ve daha yüksek sesle başarısız olur: mknod orada EROFS döndürür, oysa EPERM sürecin yetenekten yoksun olduğunu gösterir, dosya sisteminin kendini koruduğunu değil. Son olarak, kendi /dev tmpfs'sine sahip bir konteyner çalışma zamanı, düğümün kendi ad alanına enjekte edilmesini gerektirir ve aygıt cgroup'u major ile minor çiftine izin vermelidir.
İzinleri yeniden değiştirmeden önce ilke katmanını denetleyin. SELinux ve AppArmor, her dosya özniteliğinin izin verdiği bir açmayı reddedebilir ve bu ret istemci çıktısında değil denetim günlüğünde görünür. Hiçbir rette görünmeyen bir izin değişikliği tamamen yanlış katmana harcanmış zamandır.
sudo journalctl -k -n 20 --no-pager
sudo ausearch -m AVC -ts recent | tail -5
Bunu liste ile değil arayüzle kanıtlayın
Başarılı bir liste yalnızca bir yolun var olduğunu kanıtlar ve daha fazlasını değil. Sağlıklı bir tun düğümünü okumak için açın, çağrı bir hatayla döner, çünkü aygıtın okuma anlamı yoktur ve sıradan bir dosya değildir. Bu hata burada başarı işaretidir ve onu tanımak arıza diye peşine düşmenizi engeller.
head -c 1 /dev/net/tun
head: error reading '/dev/net/tun': File descriptor in bad state
Belirleyici test bir arayüz oluşturur, çünkü sürücüyü, düğümü ve ayrıcalıklarınızı tek adımda sınar. Ekleme başarılı olur ve bağlantı görünürse üçü de çalışıyordur. Başarısız olduğunda errno nedenleri ayırır: ENOENT kullanılabilir düğüm olmadığını, EPERM yeteneğe, bağlama bayraklarına veya ilkeye işaret ettiğini, EBUSY ise arayüzü başka bir sürecin zaten sahiplendiğini gösterir.
sudo ip tuntap add dev tun7 mode tun
ip -brief link show tun7
sudo ip tuntap del dev tun7 mode tun
Bu testi gerçekten başarısız olan bağlamda çalıştırın, çünkü bir hizmet birimi, bir konteyner veya zamanlanmış bir iş oturum açma kabuğunuzdan farklı bir yetenek kümesi taşıyabilir. Yanlış bağlamda geçen bir test, başarısız olan hakkında hiçbir şey kanıtlamaz.
Aygıt sorun olmadığında
Arayüz testi başarılı olur ve istemci hâlâ başarısız olursa, kalan sorun profildir, hizmet bağlamıdır veya rotadır ve aygıt iyidir. Aygıt düğümlerini düzenlemeyi bırakmanın zamanı budur, çünkü daha fazla değişiklik yalnızca çalışan bir sistemden uzaklaşmayı artırır.
Her seferinde yenisini uydurmak yerine aynı beş denetimi çalıştırın: modül rakip bir modül olmadan yüklü mü, yol doğru major ve minor değerlerine sahip bir karakter aygıtı mı, bağlama seçenekleri temiz mi, süreç bağlamı yeteneği taşıyor mu ve arıza zaman damgasında bir ilke reddi var mı. Beşini de atlatan bir arıza, mesaj ne söylerse söylesin aygıt sorunu değildir.