samba – unix extensions bug?

Vor kurzem habe ich ca. 2 Stunden damit verbracht, mich mit einem vermutlichen Fehler in der Samba-Server-Version 3.2.7 unter Kernel 2.6.27 herumzuschlagen. (Die Kernelversion galt sowohl für den betroffenen Server wie auch die Linux-Clients).

Der Fehler bestand darin, dass “force create mode” und “force directory mode” Einstellungen des Samba-Servers ignoriert wurden, wenn User von unseren Linux-Clients aus Dateien/Verzeichnisse im Share anlegen wollten. Das hatte bei uns in der Praxis insofern Folgen, als die reibungslose Arbeit in der Gruppe u.a. von den Rechten der erzeugten Dateien abhing.

Die “force…”-Einstellungen waren gerade deshalb gesetzt worden, damit weder Windows- noch Linux-User der Samba-Shares über die Rechte-Einstellungen nachdenken mussten.

Das Problem im Detail und die Bedeutung der “unix extensions”

Ich habe für einen Share auf einem Samba-Server folgende Einstellungen vorgegeben:

[aux]

comment = aux
inherit acls = Yes
path = /samba/ann_aux
read only = No
create mask = 0664
force create mode = 0664
force user = myuser

Dieser Share wird in unserem Netz – wie gesagt – nicht nur von Win-XP Clients (natürlich in einer virtuellen Umgebung unter Linux) aus benutzt, sondern auch von Anwendern auf reinen Linux-Systemen. Dabei stellten wir dann fest, dass für einen berechtigten Linux-User zwar die “force user”-Vorgabe ausgeführt wurde, die Dateirechte jedoch immer auf “rw-,r–,r–“ gesetzt wurden, statt wie erwartet (“OR” – Kombination der Berechtigungs-Bits!) auf “rw-,rw-,r–“.

Der Rechtekamm “rw-,r–,r–“ entsprach nicht den “force create mode”-Einstellungen des Servers, sondern vielmehr den umask-Einstellungen für den betreffenden User auf dem Linux-Client.

Dagegen funktionierten die obigen Einstellungen auf einem deutlich älteren Samba-Server für ein anderes Share. Was also war der Unterschied zwischen den Servern? Nach einigem Suchen im Internet und Vergleichen kam ich dann dahinter, dass die Option “unix extensions” auf dem neueren Server gesetzt ist – defaultmäßig auf “yes”.

Dieser Parameter steuert für CIFS Shares die Anzeige und Nutzung von Linux-Rechten im Zusammenspiel zwischen Samba-Servern und Linux/Unix-Clients. Ich zitiere von “http://wiki.ubuntuusers.de/Samba_Server/smb.conf” :

CIFS Unix Extensionsunix extensions = yes

Dieser Parameter ermöglicht durch z.B. Samba Client/cifs auch auf dem Client die Original Dateirechte und Zeitstempel zu sehen und zu verwenden. Standardmäßig ist diese Option aktiviert; sie sollte nur bei Problemen mit diesen Extensions deaktiviert werden.
Die Einstellung kann nur für den gesamten Server geändert werden; unterschiedliche Einstellungen für einzelne Freigaben sind vom Server aus nicht möglich.

Dieser Parameter ermöglicht durch z.B. Samba Client/cifs auch auf dem Client die Original Dateirechte und Zeitstempel zu sehen und zu verwenden. Standardmäßig ist diese Option aktiviert; sie sollte nur bei Problemen mit diesen Extensions deaktiviert werden.
Die Einstellung kann nur für den gesamten Server geändert werden; unterschiedliche Einstellungen für einzelne Freigaben sind vom Server aus nicht möglich.

Weiter findet man unter “http://wiki.ubuntuusers.de/Samba_Client_cifs” folgende Ausführungen

Sind die CIFS-UNIX-Erweiterungen aktiv (auf dem Samba-Server: unix extensions = yes, Standard), so werden die echten Besitz- und
Zugriffsrechte zwischen Server und Client übertragen. Ändert man auf dem Client mittels chmod oder chown oder über den Eigenschaften-Dialog der GUI die Rechte, ist die Änderung ebenso auch auf dem Server und auf allen anderen Clients wirksam, die auf die Freigabe zugreifen.
Die Angaben in der Datei /etc/samba/smb.conf auf dem Server legen dabei den Rahmen fest, in dem Zugriffsrechte auf dem Client Gültigkeit haben. Ist z.B. eine Freigabe in smb.conf nur zum Lesen freigegeben, können für sie von keinem Client aus Schreibrechte festgelegt werden. Ist sie aber in smb.conf auch für Schreibzugriffe freigegeben, kann sie von jedem Client aus mittels chmod für “nur lesen” eingeschränkt werden. Ebenso können Freigaben, die auf dem Server den Status “nur lesen” haben, aber in smb.conf mit Schreibrechten eingetragen sind, vom Client aus mit Schreibrechten versehen werden.
Die UNIX-Erweiterungen haben Vorrang vor anderen Angaben für Besitz- und Zugriffsrechte. Sollten in der Mount-Befehlszeile oder im Eintrag in /etc/fstab solche Angaben vorhanden sein, so werden diese bei aktiven UNIX-Erweiterungen ignoriert.

Unter “http://us1.samba.org/samba/docs/man/manpages-3/smb.conf.5.html” liest man

unix extensions (G)
This boolean parameter controls whether Samba implements the CIFS UNIX extensions, as defined by HP. These extensions enable Samba to better serve UNIX CIFS clients by supporting features such as symbolic links, hard links, etc… These extensions require a similarly enabled client, and are of no current use to Windows clients.
Default: unix extensions = yes

Für Interessierte erwähne ich auch noch, dass auf dem Linux-Client beim Mounten eines CIFS-Shares auch ein Kernel-Parameter zur Nutzung der “unix extensions” gesetzt wird (bzw. gesetzt werden kann). Man werfe dazu nach dem Mounten des Samba-Shares einen Blick in das Verzeichnis “/proc/fs/cifs” und dort in die Datei “/proc/fs/cifs/LinuxExtensionsEnabled”. Ein

echo 0 > /proc/fs/cifs/LinuxExtensionsEnabled

schaltet auf dem Client die Nutzung der vom Samba-Server angebotenen Unix-Extensions ab.

Soviel zur Theorie. Tatsächlich funktionieren die “Unix extensions” im Prinzip auch so wie vorgesehen – wenn man mal das “force create mode” außer Acht läßt :

  • Die User- und Gruppenrechte auf dem Samba-Server werden auf dem Linux-Client korrekt angezeigt. (Natürlich müssen auf dem Server und dem Client die gleichen UIDs und GIDs gesetzt sein wie auf dem Linux-Client!).
  • Jede Rechteänderung auf dem Linux-Client wird auf den Server übertragen.
  • Auch von MS Win-Clients aus funktioniert alles so wie vorgesehen – sogar das “force create mode” wird hier richtig ausgeführt.

Mein Problem besteht/bestand also darin, dass bei aktivierten “unix extensions” auf dem Samba-Server das gesetzte “force create mode” ignoriert wird, wenn man Dateien des Shares über einen Linux-Client anlegt. Das hätte ich schon aus Konsistenzgründen zu älteren Versionen des Samba-Servers nicht unbedingt so erwartet.

Die (vorrübergehende) Lösung

Probeweise habe ich den Samba-Server-Parameter “unix extensions” dann auf “no” gesetzt.

Danach wurden die Rechte von Files, die von Linux-Clients neu erzeugt wurden, tatsächlich wieder “korrekt” – d.h. gemäß der “force create mode”-Vorgaben – gesetzt. (Das Gleiche funktioniert natürlich auch, wenn man die entsprechenden Paramter für den Rechtemodus von Verzeichnissen benutzt.)

Blöd ist nur, dass die gewünschten und korrekt gesetzten User- und Gruppen-Rechte der Dateien auf dem Samba-Server nun natürlich nicht mehr auf den Linux-Clients angezeigt werden. Das war ja eigentlich der Sinn der “unix
extensions”. Aber damit kann man leben, wenn einem das Erzwingen von Rechten wirklich wichtig ist.

Eine Philosophie-Frage oder ein Bug ?

Nach diesen Erkenntnissen fragt man sich nun: Ist das eigentlich ein Bug ? Ich habe dazu zumindest einen Hinweis im Internet gefunden:

http://www.mail-archive.com/samba@lists.samba.org/msg99935.html und
http://www.mail-archive.com/samba@lists.samba.org/msg99936.html.

Natürlich könnte man aber auch wie folgt argumentieren: Wenn jemand die “unix extensions” benutzt, dann deshalb, weil man die Rechte auf dem Linux/Unix-Client selbst manipulieren will und soll. Irgendwie ist das ja der Kern der Sache. Also darf der User nicht voraussetzen, dass der Server die Rechtepolitik schon regeln wird. In meinem Fall hatte ich das auf Grund meiner Kenntnis des “force create mode”-Parameters explizit angenommen.

Andererseits:

Welche Chance hat ein Samba-Admin denn, wenn er trotz globalem “unix extensions” für bestimmte Shares auch für die User auf Linux-Clients vorgegebene Rechtekämme erzwingen will oder muss ? Lokal kann er ja für das betroffene Share die “unix extensions” nicht außer Kraft setzen – er muss auf dem Server also “force create mode” verwenden ! Aber das wird dann leider ignoriert !

Letztere Argumentation führt mich zu der Meinung, dass hier tatsächlich ein Bug vorliegt. Deshalb meine Aufforderung an die Samba- und Kernel-Profis: Bitte ändern – falls noch nicht geschehen !

 

Unison – Synchronisation mit GUI

Die gestrige Frage meiner geschätzten Gattin, wie ich es denn eigentlich so schnell schaffen würde, ein für unser Geschäft wichtiges Verzeichnis zwischen einem Linux-PC und einem Linux-Server, einem Windows XP-Laptop und einem anderen Linux-PC abzugleichen, ist vielleicht auch für andere Linux-User interessant.

Mein Freund und Konsolen-Liebhaber Michael würde nun antworten: “rsync”. Ich bin aber ein fauler Mensch. Und gerade im Konfliktfall muss man die Arbeitsweise und die Antworten von Rsync schon recht gut verstehen. Michael würde nun weiter sagen: Na, dann schreib dir halt ein Script. Meine Antwort darauf ist: Das haben andere schon gemacht – plus eine GUI dazu entwickelt.

Ein Beispiel für eine nette Applikation in diesem Umfeld stellt meiner Meinung nach “Unison” dar. Ich liste mal kurz die für mich wichtigen Eigenschaften auf:

  • Unison benutzt rsync, ist damit relativ schnell und vermittelt zwischen den Welten Linux, Unix, Mac OX und Windows.
  • Unison hat eine leicht zu überblickende und leicht zu bedienende graphische Oberfläche.
  • Unison erlaubt die Organisation der Abgleichvorgänge über Profile.
  • Unison gleicht Verzeichnisse natürlich auf Wunsch rekursiv ab.
  • Unison zeigt vor dem Abgleich an, was sich geändert hat.
  • Unison stellt Abgleichkonflikte in verständlicher Weise dar und gibt die Möglichkeit diese Konflikte pro Datei zu lösen.
  • Unison kann zusammen mit ssh benutzt werden.
  • Unison funktioniert auch über das Internet.
  • Unison funktioniert auch lokal – die abzugleichenden Verzeichnisse können auf ein und demselben Rechner liegen.

Letzteres ist besonders in Kombination mit NFS, Samba und smb4k interessant. Wenn keine größeren Sicherheitsanforderungen im lokalen Netz vorliegen und man die entsprechenden Rechte hat, hängt man die Laufwerke/Directories des Fremdrechners, auf dem sich das abzugleichende Verzeichnis befindet, einfach in das eigene Filesystem ein und führt dann den Abgleich durch. Das geht rasch und bequem.

Unison hat aber auch einen großen Nachteil – es funktioniert nicht, wenn der UTF8-Zeichensatz für Verzeichnis- oder Dateinamen ausgenutzt wird. Leider ! Wenn man aber im abzugleichenden Bereich diszipliniert mit konventionellen Dateinamen (ASCII 7) arbeitet, steht dem Einsatz von Unison als Synchronisationstool nichts im Wege – auch nicht für Arbeitsgruppen im Firmenumfeld.

Ein weiterer “Nachteil” ist ggf. der, dass man einen Abgleich zwischen mehreren Systemen durch sukzessive paarweise Abgleichvorgänge herbeiführen muss.

Dennoch: Einen Blick und einen Testlauf ist das einfach zu installierende Tool auf jeden Fall wert !

Virtuelle Domainen

Beim Web-Entwickeln stößt man ab und zu auf das Problem, dass man zum Testen auf seinem Apache2-Webserver schnell mal zwei separate Domainen benötigt, um typische Situation bei Web-Providern nachzustellen:

Auf den gehosteten Servern findet man regelmäßig Verhältnisse vor, bei denen einem in einer abgekapselten “chroot”-Umgebung zwei oder mehr Verzeichnisse bereitgestellt werden, denen dann unterschiedliche Domainen zugeordnet sid oder zugeordnet werden können. Und als Entwickler möchte man gerne domainenübergreifende PHP-Klassenbibliotheken in Verzeichnissen außerhalb der eigentlichen Domainen installieren und testen, ob die Klassen auch ordentlich in allen Domainen gezogen werden …. oder man hat mit ähnlichen domainübergreifenden Problemstellungen zu tun …..(Dass man Bibliotheken in domainunabhängigen, übergeordneten Verzeichnissen des Webservers installiert, hat seinen Grund übrigens nicht nur in der Vermeidung von Doppelpflege, sondern es dient u.U. auch der Sicherheit.)

Möchte man ähnliche Situationen auf einem eigenen Apache-Server nachstellen, greift man am besten – wie der Webprovider auch – zu namensbasierten virtuellen Domainen.
Das folgende einfache Beispiel zeigt, wie man zwei solcher zusätzlicher Domainen auf einem Opensuse-System einrichten kann und wie man dafür sorgt, dass der ursprüngliche Zugriff auf den Server erhalten bleibt. Wir gehen von folgendem Szenario aus: Es laufe ein Webserver unter der beispielhaften Adresse “server.mydomain.de”. Ihm sei die IP-Adresse “192.168.0.10” zugeordnet. Die DNS-Einstellungen im Netzwerk seien so, dass man den Webserver unter “http://server.mydomain.de” oder “http.//server” erreicht. Der Web-Server selbst sei im Moment so eingerichtet, dass in der Haupt-Konfigurations-Datei

/etc/apache2/http.conf

über eine inkludierte Datei die erforderlichen Port- und SSL-Einstellungen des Webservers vorgegeben werden. Das entsprechende Include-Statement in der httpd.conf findet sich meist an deren Anfang

Include /etc/apache2/listen.conf

Später werde auch die Default-Konfiguration des Servers über eine weitere Konfigurationsdatei (globale Einstellungen für den Defaultserver) in die “httpd.conf” geladen. Dies geschieht z.B. über den Eintrag

Include /etc/apache2/default-server.conf

Ein nachfolgender Eintrag in der httpd.conf sorge dafür, dass Definitionen für virtuelle Domainen aus dem Verzeichnis “/etc/apache2/vhosts.d” geladen werden, sobald wir (s.u.) solche Definitionen angelegt haben:

Include /etc/apache2/vhosts.d/*.conf

Auf andere Einträge in der Datei “httpd.conf” gehen wir im Moment nicht ein, da sie hier nicht von direkter Bedeutung sind.
Folgende Einträge in der “default-server.conf” sorgen vor der Umstellung auf virtuelle Domainen für den reibungslosen Betrieb.

DocumentRoot “/srv/www/htdocs”
<Directory “/srv/www/htdocs”>
     AllowOverride None
     Order allow,deny
     Allow from all
</Directory>

Alias /icons/ “/usr/share/apache2/icons/”

<Directory “/usr/share/apache2/icons”>
     Options Indexes MultiViews
     AllowOverride None
     Order allow,deny
     Allow from all
</Directory>
ScriptAlias /cgi-bin/ “/srv/www/cgi-bin/”
<Directory “/srv/www/cgi-bin”>
     AllowOverride None
     Options +ExecCGI -Includes
     Order allow,deny
     Allow from all
</Directory>
<IfModule mod_userdir.c>
     UserDir public_html
     Include /etc/apache2/mod_userdir.conf
</IfModule>
Include /etc/apache2/conf.d/*.conf
Include /etc/apache2/conf.d/apache2-manual?conf

Diese Einstellungen können
später pro virtueller Domaine überschrieben werden. Das Apache2-Konzept ist hier sehr modular.

Einrichtung der virtuellen Domainen
Nun richten wir uns 3 virtuelle Domainen ein. Zwei davon werden zwei speziellen Verzeichnissen zugeordnet; die dritte ersetzt den bisherigen “Default-Server”. Die dritte virtuelle Default-Domaine ist deshalb wichtig und notwendig,

  • weil bei einem “namebased virtual server” zunächst keine Default-Domaine existiert und der Standard-Default-Server keine Wirkung mehr hat und
  • weil man die bisherigen User des Servers nicht dazu zwingen will, ihre Lesezeichen in Ihren Browsern grundlegend zu ändern.

Diese dritte Domaine darf in einer professionell genutzten Umgebung bei der Umstellung nicht vergessen werden.

Für die Umstellung ist zunächst ein Eintrag in der Datei “/etc/apache2/listen.conf” essentiell:

NameVirtualHost 192.168.0.10:80

Nachdem wir das erledigt haben, erstellen wir im Verzeichnis “/etc/apache2/vhosts.d” eine Datei “virtu.conf” für eine virtuelle Domaine “virtu.mydomain.de” mit folgendem Inhalt :

<VirtualHost 192.168.0.10:80>
     ServerAdmin your_admin_name@mydomain.de
     ServerName virtu.mydomain.de
     ServerAlias virtu
     DocumentRoot /srv/www/vitualdomains/virtu
     HostnameLookups Off
     UseCanonicalName Off
     ServerSignature On
     DirectoryIndex index.html index.html.var index.htm index.php index.php5
     <Directory “/srv/www/virtualdomains/virtu”>
         Options Indexes FollowSymLinks
         AllowOverride None
         Order allow,deny
         Allow from all
     </Directory>
</VirtualHost>

Beachten Sie den Eintrag zum “DirectoryIndex” und “ServerAlias”. Letzterer macht die neue Domaine auch über eine Abkürzung (http://virtu) anstelle des voll qualifizierten Domainnamens ansprechbar. Der “DirectoryIndex” spezifiziert, welche Dateien aufgerufen werden sollen, wenn als Http-Adresse nur die Domaine (also das Verzeichnis) angesprochen wird. Diese Vorgabe gilt aber auch für Subverzeichnisse. Einträge aus der Datei “default-server.conf” bleiben weiterhin gültig, soweit sie nicht überschrieben wurden. Eine weitere Domaine kann etwas so aussehen:

<VirtualHost 192.168.0.10:80>
     ServerAdmin your_admin_name@mydomain.de
     ServerName virtual.mydomain.de
     ServerAlias virtual
     DocumentRoot /srv/www/vitualdomains/virtual
     HostnameLookups Off
     UseCanonicalName Off
     ServerSignature On
     DirectoryIndex index.html index.html.var index.htm index.php index.php5
     <Directory “/srv/www/virtualdomains/virtual”>
         Options Indexes FollowSymLinks
         AllowOverride None
         Order allow,deny
         Allow from all
     </Directory>
</VirtualHost>

Abschließend möchten wir noch den Server mit einer Default-Domaine ausstatten, die für alle sonstigen Zwecke aufgerufen wird, und die der ursprünglichen Serverkonfiguration entspricht:

<VirtualHost 192.168.0.10:80>
     DocumentRoot /srv/www/htdocs
  &
nbsp;  DirectoryIndex index.html index.html.var index.htm index.php index.php5
     <Directory “/srv/www/htdocs”>
         Options Indexes FollowSymLinks
         AllowOverride None
         Order allow,deny
         Allow from all
     </Directory>
</VirtualHost>

Man erkennt, dass hier der “ServerName”-Eintrag fehlt !
Bleibt nur noch, auf unserem DNS-Server (oder auf dem Client-Rechner in der “/etc/hosts”-Datei) dafür zu sorgen, dass “virtu.mydomain.de” und “virtual.mydomain.de” im Netzwerk auch unter der Adresse “192.168.0.10” gefunden werden. Danach können wir den Webserver neu starten und erreichen in einem Browser über “http://virtu.mydomain.de” bzw. “http://virtual.mydomain.de” die neuen Domainen. Rufen wir nur “server.mydomain.de” oder “http://192.168.0.10” auf, so erhalten wir diejenigen Seiten, die auch auf dem urssprünglichen Server schon angezeigt wurden.
Viel Spaß mit den neuen Domainen!
Wenn es funktioniert, dann ist es an der Zeit, sich mit weiteren Varianten und Möglichkeiten von virtuellen Domainen auf einem Apache-Server auseinanderzusetzen. Das obige Beispiel war nur eine sehr einfache Lösung zu fester IP-Adresse und einheitlichem Port.

Debian – Leere resolv.conf nach Neustart

Gerade hatte ich ein denkwürdiges Erlebnis zusammen mit meinem Freund Michael, das uns beide etliche Nerven gekostet hat. Es ging dabei um eine WLAN-Konfiguration auf einem Laptop. Interessanterweise scheiterten wir dabei nicht an der WLAN-Karte, sondern an elementaren Schwierigkeiten mit der lokalen Konfiguration der “/etc/resolv.conf” – also etwas sehr Trivialem.

Michaels Begeisterung für Debian hat bei dem nachfolgend geschilderten Erlebnis doch einen kleinen Knacks bekommen. (Ich persönlich stehe ja eh’ mehr auf SuSE – eine Vergleichsinstallation auf einem Laptop mit einer Intel 3945 WLAN Karte lief auf Anhieb. Für Debian muss man halt doch immer deutlich mehr Zeit haben und strapazierfähige Nerven mitbringen …. )

WLAN-Karte erfordert Firmware

Michael wollte Debian Lenny auf einem etwas älteren Laptop für seine Tochter installieren – in der begründeten Hoffnung, dass dann auch Debian mit der Hardware zurechtkommen würde … ) Alles verlief denn auch ganz gut, bis es an die Netzwerkkonfiguration seiner WLAN-Karte ging. Es handelte sich um einen schon betagten Intel-Chip, der vom Modul “ipw2200” unterstützt wird. Obwohl das Modul anstandslos geladen wurde, lief dann aber erstmal gar nichts. Vom System wurde kein entsprechendes Netzwerkinterface für die IP-Konfiguration angeboten. Nach einigem Forschen im Internet stellte sich dann heraus, dass man unter Debian auch noch Firmware von der Adresse

http://ipw2200.sourceforge.net/firmware.php

herunterladen muss – ohne diese Firmware läuft die Karte nicht (vergl. mit “http://faq.pathfinderteam.org/index.php/Ipw2200”).

Wichtig ist hierbei übrigens auch, dass zum Einspielen der Firmware ein voller Restart des Systems erforderlich ist. Erst danach wird die Firmware geladen und dass WLAN-Device umfassend über das Kernelmodul angesprochen. Im Anschluss war die Karte denn auch mit “iwconfig” konfigurierbar. Wir kamen nach den üblichen Netzwerkeinstellungen und mit einer manuell konfigurierten “/etc/resolv.conf” schließlich auch anstandslos ins Internet. So weit , so gut …..

Dauerhafte Netzwerkkonfiguration mit “network-admin”

Nun möchte man aber auch unter Debian alle Netzwerkeinstellungen persistent machen. Damit die Netzwerkkonfiguration einen System-Neustart überlebt, müssen natürlich Vorgaben für Startup-Skripte gesetzt und gespeichert werden. Ein zugehöriges graphisches Programm für diese Aufgabe stellt unter Debian “network-admin” dar (siehe etwa http://www.debianadmin.com/debian-networking-for-basic-and-advanced-users.html).

Wohlgemut gingen wir an die Arbeit. Die Default-Einträge für den Rechner und die zugehörigen Domaine muss man natürlich an seine Bedürfnisse anpassen. Gleiches gilt für die Default-Gateway-Adresse. Wir wiesen dem Netzwerk-Interface anfänglich eine statische Adresse zu, die mit dem WLAN-Router kompatibel war. Abschließend legten wir über “network-admin” die Adressen der DNS-Server fest. Ein kurzer Test der Internetverbindung nach einem “/etc/init.d/networking restart” verlief denn auch erfolgreich.

Leere /etc/resolv.conf nach Neustart des Debian-Systems

Dann tauchte aber ein Problem auf, dass wir nur nach stundenlangem Rätseln und herumprobieren lösen konnten: Ein Restart des Systems führte jedesmal zu einer leeren Datei “/etc/resolv.conf” ! Und wer hat schon Lust, nach einem Systemstart immer wieder die DNS-Adressen manuell zu setzen ……

Dass das Netzwerk wegen einer evtl. falschen Runlevel-Konfiguration nicht richtig gestartet wurde, konnten wir nach kurzer Zeit ausschließen. Alles war OK und keine (andere) netzwerkrelevante Konfigurationsdatei wurde beim Systemstart geändert – außer eben der “resolv.conf”. (Die “/etc/network/interfaces” etwa enthält genau die gewünschten Einträge.) Nun
ging das Rätseln los:

  • Lief etwa ungewollt “bind9/named” und überschrieb aus dieser Ecke irgendwas die resolv.conf? Antwort: Nein.
  • Lief “dhcp” und überschrieb evtl. ein DHCP-Server die Einträge? Antwort auch hier wieder: Nein. Der einzige DHCP-Serve im Netz wurde deaktiviert und das dhcp-client-Paket haben wir schließlich explizit vom Laptop deinstalliert. Einen Eintrag “iface ethX …. dhcp” gab es in der Datei “/etc/network/interfaces” auch nicht – sondern korrekterweise “iface ethX inet static”.
  • Wurde etwa beim Starten der der graphischen Oberfläche ein Programm gestartet, dass sich an der resolv.conf zu schaffen machte? Auch das konnten wir ausschließen.

 

Bösewicht “resolvconf”

Später fiel uns dann bei einem Suchlauf auf, dass es auch ein Programm “/etc/resolvconf” und ein zugehöriges Package gab. Bei genauem Hinsehen erkannten wir zusätzlich, dass die Datei “/etc/resolv.conf” eigentlich einen Link zu einer Datei “/etc/resolvconf/run/resolv.conf” darstellte. Das machte uns dann doch sehr misstrauisch. Testhalber haben wir dann das zugrundeliegende Package komplett entfernt:

“apt-get –purge remove resolvconf”.

Und man glaubt es kaum: Danach blieb bei einem Systemneustart die /etc/resolv.conf erhalten !!!!
Resolvconf überschrieb uns beim Systemstart immer unsere DNS-Server-Adressen mit Leereinträgen!

Das muss man erstmal wissen ! Auf meinen SUSE-Systemen gibt es keine Spur eines resolvconf-Paketes. Das Programm “resolvconf” dient unter Debian wohl zur Anpassung von DNS-Einträgen durch verschiedene Programme zur Laufzeit. Die Standard-Datei “/etc/resolv.conf” wird dabei in den angebenen Link verwandelt. Die Zieldatei ist dabei nicht für manuelle Einträge gedacht.

Lösungsmöglichkeiten

Für einfach Systeme, die keinen dynamischen Update der Nameserver-Konfiguration während der Laufzeit benötigen, kann man auf das optionale “resolvconf”-Paket anscheinend verzichten. Wir sind diesen Weg gegangen. Erste Hinweise, was man bei Problemen mit einem laufenden “resolvconf” tun kann, liefert übrigens der Abschnitt zu “resolvconf” unter folgender Adresse:

http://wiki.debian.org/NetworkConfiguration

In unserem Fall hätten wir das Problem wohl auch durch einen zusätzlichen Eintrag in der “/etc/network/interfaces” folgender Art

dns-nameservers ip-adr1 ip-adr2

lösen können. Diesen Eintrag muss man eingerückt hinter dem Gateway-Eintrag platzieren.
(Weitere Hinweise gibt die Datei “/usr/share/doc/resolvconf/README”)

Fazit
Wie gesagt: Das muss man alles erstmal wissen. Ist halt Debian …. nix für einfach gestrickte Gemüter, die an schnelle Lösungen mit Linux glauben wollen …. (sorry, Michael!)

Links:
http://wiki.debian.org/NetworkConfiguration
http://www.debianadmin.com/debian-networking-for-basic-and-advanced-users.html”
http://www.debian.org/doc/manuals/reference/ch-gateway.de.html
http://www.technovelty.de/debian-nameserver-mit-resolvconf-eintragen/

“NIC-Names” unter SuSE

Bei der Vorbereitung auf ein LPI-Zertifikat lernt man den Umgang mit den Befehlen “ifconfig”, “ip” und “iwconfig” in umfassender Weise. Dabei beziehen sich die Befehle allerdings auf vorhandene Interface-Namen, die dem System bereits bekannt sind. Ifconfig kann u.a. die Zuordnung einer IP-Adresse zu einem definierten und benannten Netzwerk-Interface vornehmen. Diese Zuordnung überdauert aber einen Neustart des Systems jedoch nicht.

Trotz Yast kann ein SuSE-Anwender öfter als ihm lieb ist, in eine Situation geraten, in der die Beherrschung von ifconfig nicht mehr genügt und er gerne auch die Antwort auf folgende Fragen wissen möchte:

Wo wird eigentlich unter SuSE der Name eines Netzwerk-Interfaces dauerhaft hinterlegt? Wie wird eine erkannte NIC eigentlich dem jeweiligen Interface-Namen zugeordnet? Wo steht das? Wo und wie hinterlegt SuSE die Netzwerkkonfigurationsdaten dauerhaft zu einem Interface-Namen? Woher erhält das System z.B. beim Startup die Information, dass es zwei Interfaces eth0 und eth1 gibt, de konfiguriert werden müssen? Genau diese Fragen wurden mir heute gestellt – und LPI-Bücher helfen hier nicht wirklich weiter.

Ich versuche nachfolgend zu zeigen, wie man die zugehörigen Konfigurationsdateien und Informationen in einem SuSE-System durch ein wenig Nachdenken und systematisches Stöbern im System finden kann. Bei aktuellen SuSE-Systemen gelangt man dabei unweigerlich zum Verzeichnis “/sys”. Wir gehen daher kurz auch auf seine grundlegende Bedeutung für Kernel 2.6-Systeme ein.

Die Suche nach der Nadel im Heuhaufen

Angesichts der Vielzahl von Konfigurationsdateien, Startup-Skripts und SuSE- bzw. Yast-spezifischen Konfigurationsdateien kann man auch als erfahrener Linux-Anwender bei der Suche nach spezifischen Informationen zu Netzwerkkarten und deren Interface-Namen fast verzweifeln, wenn einem das Internet mal nicht als zusätzliche Informationsquelle zur Verfügung steht.

Um einen Startpunkt zu bekommen, könnte man als erstes geneigt sein, einmal unter “/proc/sys/ipv4/” und genauer unter “/proc/sys/ipv4/conf” nachzusehen. Der Kernel muss ja zumindest wissen, welche Interfaces er im Griff hat. Das ist insofern ein guter Ansatz, als man dort schnell einen Überblick über die aktiven Karten erhält. Übrigens auch über die (virtuellen) Host-Interfaces eines gestarteten VMware-Prozesses, wobei das Linux-Systems als VMware-Host dient:

Netzinterfaces_2

Also irgendwie sind auch dem Kernel die für die Netzwerkkarten vergebenen Namen bekannt. Als SUSE-Anwender weiß man aber auch, dass man die Bezeichnung “eth0” eines Interfaces bereits bei der Einrichtung der Netzwerkkarte über Yast vergeben hat – oftmals schon während der Installation. Zudem bleiben die diesem Namen zugeordnete Konfigurationsvorgaben (z.B. zu DHCP oder einer statischen IP-Adresse) dauerhaft im System erhalten.

Wie gesagt: Der Befehl “ifconfig” kann den Netzwerkinterfaces Konfigurationswerte nur momentan, nicht aber über einen Reboot hinaus zuordnen. Mit ifconfig vergebene Werte überleben einen Neustart des Systems oder des Netzwerkes nicht. (Das kann man leicht ausprobieren!).

Also hegt man die Vermutung, dass es wohl Dateien geben wird, in denen Yast die benötigten Informationen persistent hinterlegt. Diese Informationen müssen dann zwangsläufig bei jedem Systemstart ausgewertet werden und auch dem Kernel verfügbar sein. Um herauszubekommen, woher das System beim Startup Informationen zur Netzwerkkonfiguration und zu Interfaces bezieht, werfen wir deshalb einen Blick in das entsprechende Startup-Skript von SuSE für das Netzwerk.

Dieses Skript finden wir – wie erwartet – unter “/etc/init.d/” als Datei “/etc/init.d/network”. Nach etwas Suchen im Skript stößt man recht bald auf eine Zeile in der das
Verzeichnis

/etc/sysconfig/network

aufgesucht wird.

Das Verzeichnis /etc/sysconfig/net

Bei SuSE werden grundlegende Einstellungen zum System im Verzeichnis “/etc/sysconfig” verankert. Tatsächlich gibt es dort denn auch ein Unterverzeichnis “/etc/sysconfig/network” sowie eine Konfigurations-Datei “/etc/sysconfig/network/config”. Unter SuSE’s Yast gibt es zudem ein Werkzeug – den “/etc/sysconfig”-Editor – mit dem man sich die Einträge unter /etc/sysconfig” ansehen und ggf. auch editieren kann. Die Parameter der Datei “/etc/sysconfig/network/config” erhält man im “/etc/sysconfig”-Editor z.B. unter dem Punkt “Network->General”.

Klickt man sich im “Sysconfig-Editor” weiter durch die Hauptpunkte durch, so gelangt man unter “Hardware->Network” auch zu Unterpunkten für die verschiedenen, namentlich definierten Netzwerk-Interfaces (z.B. eth0, eth1,…). U.a. sind hier die zuzuordnenden IP-Adressen hinterlegt. Weitere im “Sysconfig-Editor” definierte bzw. definierbare Parameter sind z.B.:

BOOTPROTO, BROADCAST, ETHTOOL_OPTIONS, IPADDR, MTU, NAME, NETWORK, REMOTE_IPADDR, STARTMODE, USERCONTROL.

Woher nimmt der “Sysconfig-Editor” diese Informationen? Ein kontrollierender Blick in das Verzeichnis “/etc/sysconfig/network” zeigt dann, dass die Vorgaben für das Interface eth0 (bei der Einrichtung der Netzwerkkarte mit Yast2->Netzwerkgeräte->Netzwerkkarte) in die Datei

/etc/sysconfig/network/ifcfg_eth0

geschrieben wurden. Entsprechende Konfigurationsdateien gibt es unter “/etc/sysconfig/network/” natürlich auch für andere NIC-Interfaces.

Aha, über diese Dateien oder über den “Sysconfig”-Editor kann man also unter SuSE IP-Adressen und Broadcast-Adressen für ein Interface (dauerhaft) ändern. Wenn man also im laufenden Betrieb nicht zu “ifconfig” greifen will oder aber Änderungen für ein Interface dauerhaft hinterlegen muss und die erneute Kartenkonfiguration mit “Yast->Netzwerkgeräte->Netzwerkkarten” scheut, so führt auch der Umweg über das Editieren der besagten Dateien zum Ziel. Im laufenden Betrieb muss man aber nach den Datei-Änderungen (über den “/etc/sysconfig”-Editor) den Befehl “/etc/init.d/rcnetwork restart” aufrufen, um die Änderungen konkret auf die vorhandenen NICs anzuwenden.

Die Startup-Skripts für das Aufsetzen des Netzwerkes greifen also auf die Interface-spezifischen Dateien vom Typ “/etc/sysconfig/network/ifcfg_ethx” zurück. Natürlich macht auch dieses Startup-Skript sich bei der Konfiguration des jeweilige Interfaces intern die Möglichkeiten von ifconfig(oder ip) zu Nutze. (Dies erkennt man, wenn man die Logik des Startup-Slripts weiter verfolgt.)

Nun führen aber Konfigurationsdateien wie “/etc/sysconfig/network/ifcfg_eth0” die Bezeichnung des Netzwerkinterfaces bereits im Namen! Die Datei wurde bei der Konfiguration der NIC erzeugt. Zu diesem Zeitpunkt war natürlich klar, um welche Hardware es sich handelt. Wie weiß das System aber im Nachhinein, welche Interface-Bezeichnung welcher NIC (welchem physikalischen Gerät) zuzuordnen ist? Wo wird also festgeschrieben, welche Netzwerk-Geräte und -Interfaces es im System gibt und welche Namen diesen Interfaces zugeordnet wurden ?

Wir werfen erneut einen Blick in die Startup-Datei “/etc/init.d/rcnetwork restart”. Nach weiterem Scrollen werden wir fündig (Opensuse 10.X):

Zum Durcharbeiten aller Netzwerkinterfaces wird (falls der “Networkmanager” nicht benutzt wird), die Variable “AVAILABLE_IFACES” herangezogen. Ein wenig weitere Forschungsarbeit zeigt schließlich, dass die Variable “AVAILABLE_IFACES” nach Durchlaufen eines Analyse-Loops über den Inhalt des Verzeichnisses

/sys/class/net/

festgelegt wird.

Von /sys/class/net zum sysFS

Tatsächlich zeigt ein Blick in das Verzeichnis “/sys/class/net/” auf einem meiner Systeme auszugsweise Folgendes:

Netz_interfaces_3

Also: Unsere ursprüngliche Frage, wo im System Informationen zu NIC-Interface-Namen hinterlegt sind, haben wir damit beantwortet: Unter “sys/class/net”.

Wir lernen bei der Gelegenheit jedoch noch ein wenig mehr:

Bei genauerem Hinsehen stellen wir fest, dass es sich bei den Dateien unter “/sys/class/net” um Links handelt, die wiederum auf Device-Dateien unter “/sys” (hier genauer: /sys/pci0000:00) verweisen. Wir erkennen nach einigem Studium ferner, dass sich auch Links aus dem Verzeichnis “/sys/bus/pci” auf die Device-Dateien beziehen. Aha, so langsam wird uns klar, dass das “/sys”-Verzeichnis offenbar essentielle und strukturierte Informationen zu Devices – und nicht nur zu Netzwerkdevices – enthält. Es scheint so, als würden Interface-Klassen separat von den Geräten aufgeführt, aber doch einander zugeordnet.

Ein Blick in “/etc/fstab” zeigt übrigens, dass “sysfs” auf “/sys” gemountet wird. Es handelt sich also um ein regelrechtes Filesystem. Wem nützt sowas? Natürlich u.a. dem Kernel (ab Version 2.6). Es handelt sich um das sog. “sysFS”-System, mit dem Geräte und deren Interfaces organisiert werden. Die sysFS-Organisation wird in den Startup-Skripts von SUSE (ab Vers. 9.1) explizit verwendet.

Generell sind die Unterverzeichnisse im sysFS die Verzeichnisse “/sys/devices/”, “/sys/bus”, “/sys/class” und “/sys/block” wesentlich. Die Verzeichnisse “/sys/devices” und “/sys/bus” entsprechen zwei verschiedenen Sichten auf die im System vorhandene Hardwaregeräte.

“/sys/class” und “/sys/block” enthalten alle “Schnittstellen” (Interfaces) zu konkreten Geräten. Nur diese definierten Interfaces können die Anwendungen des jeweiligen Systems ansprechen. es mag befremdlich wirken, aber “/dev/sdb” ist in diesem Sinne z.B. ein Interface zu einem Speichergerät. Von einem Eintrag in den Schnittstellenunterverzeichnissen “/sys/class” oder “/sys/block” führt ein eindeutiger Verweis auf ein entsprechendes Geräteunterverzeichnis in “/sys/devices” und dort zu einem speziellen Gerät.

Unter “/sys/block” findet man (wie der Name andeutet) Interfaces zu Blockgeräten, “/sys/class” enthält dagegen Interfaces zu zeichenorientierten Geräten. Die Major- und Minor-Nummern der Devices sind jeweils in einer zugehörigen Pseudodatei namens »dev« enthalten.

Aha, durch diese Verweise kann das System also wissen, welche Schnittstelle sich auf welches Gerät bezieht. Wie sieht es nun mit den Bezeichnungen der Netzwerk-Interfaces aus?

Durch die persistente Namensvergabe zu Geräte-Schnittstellen unter “/sys/class/net/*” und die entsprechende Bezeichnung der zugehörigen Datei “/etc/sysconfig/network/ifcfg_*” mit den Konfigurationsvorgaben ermöglicht es SUSE, die Netzwerk-Interface-Konfiguration über die sysFS-Struktur mit einem ganz bestimmten Gerät zu verbinden. Im Kern gilt folgende Zuordnungskette:

Gerät unter /sys/devices/Unterverzeichnis/…/Gerätedatei <<>> Bezeichnetes Interface unter /sys/class/net/*

Bezeichnetes Interface unter /sys/class/net/* <<>> (Netz-) Interfacekonfiguration unter /etc/sysconfig/network/ifcfg_*

Hiermit rundet sich unser Bild zur Netzwerkkonfiguration unter SUSE ab. Neben SUSE-spezifischen Konfigurationsdateien und Startup-Skripts spielt der Einsatz der “sysFS”-Struktur eine essentielle Rolle. Die persistente Namensgebung für die Netzwerkinterfaces spiegelt sich im Verzeichnis “/sys/class/net” wieder. Auf dieses nehmen auch die Startup-Skripts Bezug. Die unter “/sys/class/net” definierten Interfaces
sind dagegen mit konkreten Geräten unter “/sys/devices/….” verbunden.

Links

Wer nun immer noch neugierig ist, der möge sich mit tiefergehenden Geheimnissen des “sysFS”-Filesystems und weiterführend ggf. auch mit “udev” befassen.

Einen ersten Einstieg bieten folgende Adressen:

http://de.opensuse.org/SDB:SUSE_Linux_Geräte-_und_Schnittstellenkonfiguration

http://www.linux-magazin.de/heft_abo/ausgaben/2005/04/knoten_knuepfen/(offset)/2