Alexander (HH): Mailserver unter Linux - Rat erwünscht

Beitrag lesen

Moin Moin!

Allerdings hat dnsmasq noch eine Eigenart, die ich mir momentan noch nicht erklären kann: Eine DNS-Anfrage nach dem Namen des Hosts, auf dem dnsmasq selbst läuft, wird nicht beantwortet. Sei "spine" der Name des Rechners, auf dem dnsmasq läuft, und habe er die IP-Adresse 192.168.123.15. In der hosts-Datei auf spine, die dnsmasq ja zur Beantwortung von DNS-Requests mit auswertet, findet sich der Eintrag

192.168.123.15  spine

Ein nslookup von einem Ubuntu-Rechner nach "spine" wird aber mit "kenn ich nicht" beantwortet, auch ein ping auf den Hostnamen spine schlägt logischerweise fehl (direkt auf die IP-Adresse okay), während alle anderen Host/IP-Kombinationen in der hosts-Datei korrekt übermittelt werden. Von einem Windows-Rechner aus ist spine mit Namen ansprechbar, vermutlich weil Windows alternativ die NETBIOS-Namensauflösung verwendet.

Vermutlich.

dnsmasq hat einige Option, mit denen man recht perverse Konstruktionen basteln kann. Unter anderem liest es eine Konfigurationsdatei (/etc/dnsmasq.conf), die aber nicht Bestandteil von dnsmasq ist. Es gibt eine Beispieldatei mit vielen auskommentierten, abenteuerlichen Geschichten. Je nach Distribution wird diese Beispieldatei auch mal als echte Konfigurationsdatei genommen, teilweise mit aktiv geschalteten Optionen.

Prüf mal auf dem Ubuntu-Rechner, was in /etc/resolv.conf steht. Ich würde da folgendes erwarten:

Generated by dhcpcd for interface eth0

search dein.lokales.lan nameserver 192.168.123.15

Wenn der Ubuntu einen anderen Nameserver-Eintrag als den dnsmasq-Server hat, kann das natürlich nicht funktionieren.

Warum es mit anderen Rechnern doch klappt, ist halbwegs erklärbar: Vermutlich hast Du einen kleinen Router mit DNS-Server (oft auch DNSMasq), der die per DHCP(!) angefragten Hostnamen per DNS verteilt. Windows packt in DHCP-Anfragen den eigenen Hostnamen standardmäßig mit rein, Linux-Maschinen machen das normalerweise nicht. dhcpcd kann man mit -h HOSTNAME dazu bringen, andere DHCP-Clients entsprechend.

Gemeines Detail am Rande: Wenn die Maschine mit dnsmasq selbst per DHCP oder PPP konfiguriert wird, liest dnsmasq (normalerweise) die /etc/resolv.conf, um die "höhergelegenen" Nameserver zu finden (typischerweise beim Provider). dhcpcd und andere DHCP- bzw. PPP-Clients erzeugen diese Datei, sobald eine IP-Adresse zugeteilt wurde.

Natürlich lesen auch alle anderen Programme (über die libc) auf dem Rechner die /etc/resolv.conf, und damit fragen sie beim Provider (bzw. beim Router) nach Maschinen, die zwar DNSmasq kennt, aber nicht der Provider oder der Router.

Workaround (siehe dnsmasq-Doku): DHCP-Client bzw. PPP-Daemon in eine andere Datei schreiben lassen (z.B. /etc/ppp/resolv.conf oder /etc/dhcpc/resolv.conf), dnsmasq über die alternative Resolver-Datei informieren (RTFM) und /etc/resolv.conf auf dnsmasq zeigen lassen ("search dein.lokales.lan" und "nameserver 127.0.0.1" oder "nameserver 192.168.123.15").

Außerdem stört mich noch, dass der Rechner permanent, auch wenn "nichts zu tun" ist, alle paar Sekunden kurz, aber hörbar auf die Festplatte zugreift.

Linux hat, wie alle Unixe, einen sehr effektiven Plattencache, der aber auch zu teilweise sehr asynchronen Schreibzugriffen führt. Unter anderem führen auch LESEzugriffe auf Dateien, selbst auf solche, die seit Ewigkeiten im Cache liegen, zu SCHREIBzugriffen auf die Metadaten: Die Last-Access-Time (A-Time) wird aktualisiert. Es sei denn, Du schaltest das über noatime beim expliziten mount-Aufruf oder in /etc/fstab ab.

Außerdem gibt es noch Syslog, der alle 20 Minuten einen Dummy-Eintrag in die Logdateien schreibt, wenn man das nicht explizit abschaltet.

Weiteres: Ecology-HOWTO, Battery-Powered-HOWTO (schon etwas angestaubt)

Und weil mit checkpassword für BincIMAP ohnehin DJB-Software auf der Maschine landet, kann man auch gleich noch die gepatchten Daemontools dazu packen und denen die Kontrolle über exim und fetchmail überlassen. Das läuft bei mir seit Jahren absolut schmerzfrei.

Was zum Geier ist DJB,

Nicht was, wer.

was macht es,

Vieles. Unter anderem daemontools, qmail, djbdns.

tut das weh,

Ja, gelegentlich. djb tritt offenbar Leuten gerne auf die Füße, aber er liefert sehr hochwertige Software, so frei wie es nur geht: Public Domain.

Und djb hat eine Allergie gegen #include <errno.h>, was sich darin äußert, dass sich seine Software auf Linux nicht ohne weiteres (Patches bzw. Compiler-Optionen) übersetzen läßt.

Kleinere Nerverreien sind sein völlig eigenes Konzept, Software zu verteilen, zu compilieren und zu installieren. Aber es funktioniert.

Leseempfehlung: http://thedjbway.b0llix.net/ (Mirror vom Original thedjbway.org, das von einem Domain-Grabber in Linkfarm für Pornoseiten umgewandelt wurde), dort gibt es auch (Links auf) Patches für Linux und für SIGQUIT/SIGUSR1/SIGUSR2.

wozu braucht man das?

daemontools: Daemons managen und Code sparen. Daemontools kümmern sich um Dinge wie automatischen Neustart, zuverlässiges Logging, etc.

Vor allem aber nutzen die djb-Programme Unix-Features, statt das Rad ewig neu zu erfinden. Wenn man das Prinzip einmal verstanden hat, fragt man sich, warum sich Leute immer noch damit quälen, Programme "in den Hintergrund bringen" zu wollen, PID-Files zu verwalten, oder ein brauchbares Logging auf die Reihe zu bekommen. Das alles ist mit Unix-Derivaten völlig unnötig.

Google und Wikipedia geben mir da auch keine Anhaltspunkte.

Schade eigentlich.

Und was für Daemontools? Ich kenne daemon tools als Windows-Software, die anhand einer ISO-Imagedatei ein virtuelles CD/DVD-Laufwerk generiert.

Ja, auch. Aber die schreibt sich "laut" und mit Bindestrich.

Die "wahren" daemontools schreibt man "leise" und ohne Bindestrich, und vor allem haben sie nichts mit Windows zu tun.

Wenn Du nur ins Internet mailen willst, kann PHP sich auch gleich an den Mailserver des Providers wenden.

Tatsächlich? Das würde mir vollkommen genügen. Denn intern kann ich Protokolle auch einfach in Protokolldateien schreiben, das ist mir lieber. Aus Mails müsste ich sie ja erst wieder rauspopeln.

Du weißt, dass diverse Dienste auf typischen Unixen (und Linux-Distributionen aller Art) an User oder root mailen? Allen voran cron, aber auch mdadm oder smartd, die RAID-Volumes bzw. Festplatten überwachen.

Mein Backup-Script mailt mir auch jede Nacht via cron, ob und wie das Backup gelaufen ist. Und mdadm und smart warnen natürlich auch, wenn Platten sterben. So muß ich eben NICHT regelmäßig in irgendwelchen über die Platte verstreuten Logs wühlen, ob irgendetwas schief gelaufen ist. Ich sehe es quasi sofort in meinen Mails.

Wobei - wenn ich es mir recht überlege, brauche ich gar keinen MTA. Wichtig ist mir nur, dass ich mail() in PHP zum Testen verwenden kann. Ob die so versendeten Mails dann über reguläre e-Mail-Versandwege laufen oder auf dem kurzen Weg direkt ins interne Mail-Processing, ist eigentlich egal.

Wenn Du die mail()-Funktion in PHP benutzen willst, wirst Du um einen MTA kaum herumkommen, es sei denn, Du ersetzt sendmail durch ein eigenes Programm, dass alle Aufrufe inklusive STDIN ausführlich dokumentiert.

Vermutlich kann PHP auch unter Linux so konfiguriert werden, dass es sich mit einem SMTP-Server zum Versand verbindet wie unter Windows So weit ich weiß nein. Warum denn das nicht? Das wäre eine extrem dämliche Einschränkung. (Im Zweifel mal in die Doku schauen -- http://de2.php.net/manual/en/mail.configuration.php sagt tatsächlich, dass PHP nur unter Windoof SMTP kann -- D'oh!) In ein Programm namens sendmail zu pipen ist auf Unix-Systemen zwar üblich, aber SMTP zu localhost oder dem MX der lokalen Domain ist auch möglich.

Aus rein akademischen Interesse: Wie? Hinweis, Fingerzeig?

Was meinst Du? SMTP zu localhost?

telnet localhost 25 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 220 meine.kiste ESMTP Exim 4.60 Tue, 29 Jun 2010 16:58:25 +0200 HELO localhost 250 meine.kiste Hello localhost [127.0.0.1] MAIL FROM: alex@localhost 250 OK RCPT TO: alex@localhost 250 Accepted DATA 354 Enter message, ending with "." on a line by itself Hallo Welt . 250 OK id=1OTcH2-0004Ay-It QUIT 221 meine.kiste closing connection Connection closed by foreign host.

Das war's, extrem kurz. Länger:

Es gibt keinen verbindlichen Weg herauszufinden, wie man als Programm seine Mails los wird.

Man kann es "stumpf und dumm" damit versuchen, ein anderes Programm namens sendmail zu finden, typischerweise in $PATH, /usr/lib oder /usr/sbin. Das ruft man dann mit ein paar "magischen" Parametern auf, die das Originale sendmail seit Urzeiten verträgt, und hofft, dass das Programm wirklich die per STDIN angelieferte Mail verschickt.

Man kann versuchen herauszufinden, welcher Mailserver für den Rechner des Empfängers bzw. der Empfänger zuständig ist, und und mit diesen direkt kommunizieren. Dazu befragt man das DNS nach MX-Records für die jeweiligen Hosts bzw. Domains. Das scheitert immer öfter an Blacklists, weil die etablierten Mailserver der Provider etwas "gleicher" als die Server auf Dial-Up-IP-Adressen sind.

Man kann versuchen herauszufinden, welcher Mailserver für die lokale Maschine (bzw. das lokale Netz) zuständig ist (ebenfalls über DNS / MX-Records), und hoffen, dass der MX erstens richtig konfiguriert ist, zweitens Relaying (weiterleiten an beliebige andere Mail-Adressen) erlaubt, und drittens überhaupt Mails annimmt.

Man kann stumpf voraussetzen, dass auf der lokalen Maschine ein Mailserver (MTA) läuft.

Mein Standard-Ansatz ist, in der jeweiligen Programmkonfiguration SMTP-Server, SMTP-Port, User-Name und Passwort einstellbar zu machen, und den Rest einer SMTP-Library (in Perl typischerweise MIME::Lite) zu überlassen.

Wenn auf einer Maschine sendmail funktioniert, arbeitet sendmail meistens auch als MTA, d.h. ich kann per SMTP über Port 25 oder 587 meine Mails loswerden.

Ohne sendmail oder bei "besonderen Umständen" (dämliche DNS-Admins, paranoide Mail-Admins, Microsoft-only-Laden)  gibt es im LAN oder spätestens beim Provider einen Server, der mitspielt. Das kann auch mal Exchange, Groupwise oder Notes sein, ggf. mit einem entsprechenden "Adapter".

SMTP zu sprechen ist nicht sonderlich schwer, siehe oben. Der Teufel steckt im Detail, weil SMTP eben eines der ältesten Protokolle im Netz ist, aus Zeiten, als Datenverbindungen oft nur 7 Bit übertragen konnten und Hacker noch ein rein positiver Begriff war. Du öffnest einen TCP-Socket zu Port 25 oder 587 des Mailservers, wartest auf die Begrüßung des Servers, wertest den Statuscode am Zeilenanfang aus, und arbeitest Dich dann weiter durch die Kette HELO name.des.client.rechners, ggf. Login, MAIL FROM: absender@example.com, RCPT TO: empfaenger1@example.com, RCPT TO: empfaenger2@example.com, DATA, Mailtext, ".", QUIT, mit einer Auswertung des Statuscodes nach jedem gesendeten Kommando. In der Praxis überläßt Du SMTP besser einer Library, die sich um die ganzen Details kümmert, und auch das Konstruieren einer Mail mit allem Firlefanz (insbesondere MIME) überläßt Du besser einer Library.

Weiteres: Mail-Format ist in RFC2822 definiert, SMTP in RFC2821, IMAP4rev1 in RFC3501, POP3 in RFC1939 und RFC2449, DNS in rund 20 RFCs

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".