Kategorien

Dovecot, Exim, OpenLDAP und getmail unter Ubuntu – (1) OpenLDAP

In diesem Blog-Eintrag geht es um die Einrichtung eines Mailservers, der dovecot, Exim, OpenLDAP und getmail verwendet. Folgendes wird mit der Konfiguration erreicht:

  • Mails können von  Benutzern, die in OpenLDAP eingetragen sind per IMAP abgerufen und per SMTP versendet werden (auch mit TLS-Verschlüsselung).
  • Benutzer können Mails von externen POP3/IMAP-Accounts direkt in ihr IMAP Postfach legen lassen
  • Benutzer können Mails mit einer externen Absenderaddresse via lokalem Mailserver verschicken, der sie über den entsprechenden externen Mailserver verschickt

Am Beispiel sollte es klarer werden. Paul ist mit der Userid paul in OpenLDAP eingetragen und hat auf dem lokalen Rechner mit der Domain myserver die Mailaddresse paul@myserver. Paul kann per IMAP Mails abrufen (Login: paul@paul Server: myserver) und ebenfalls per SMTP Mails verschicken. Außerdem hat Paul eine weitere E-Mailadresse aus der Zeit als er sich noch keine eigene Domain leisten konnte. Diese lautet paulpanzer@gmx.de. Paul möchte seine E-Mails zukünftig auf seinem lokalen Server speichern und nicht mehr bei GMX. Er bzw. der Administrator trägt dazu die POP3-Zugangsdaten von GMX in OpenLDAP ein. Danach werden alle E-Mails automatisch heruntergeladen und Paul kann über den Login paul@paulpanzer@gmx.de auf dem Server myserver seine GMX-Mails per IMAP abrufen. Trägt Paul bzw. der Administrator auch die SMTP-Daten für die E-Mailaddresse paulpanzer@gmx.de in OpenLDAP ein, so kann Paul außerdem Mails indirekt via GMX- Mailserver verschicken, indem er als SMTP-Login paul@paulpanzer@gmx.de auf seinem lokalen Server wählt. So sieht das fertige Schema mit der verwendeten Software aus:

General Software Setup - Dovecot, Exim & Co.Der Zugriff per Webinterface auf Mails und der Abruf der Mails vom externen Server bzw. das Empfangen von Mails ist hier dargestellt:

General software setup - Getmail, Roundcube & Co.

Einrichtung

Bevor man überhaupt daran denkt, ein E-Mail-Serversystem aufzusetzen, müssen zwei Bedingungen erfüllt sein. Die erste betrifft eine genaue Systemzeit, der zweite den Hostnamen. Obwohl fast alles im Blog detailliert beschrieben ist, empfehle ich, die Konfigurationsdateien für das Mailsystem herunterzuladen.

Genaue Systemzeit mit Ubuntu

Leider installiert Ubuntu standardmäßig das Paket ntpdate. Durch dieses Paket wird jedes Mal, wenn man mit dem Internet verbunden ist (genauer gesagt beim ifup), die Zeit mit einem NTP-Server im Internet abgeglichen und ggfs. die Systemzeit entsprechend geändert. An sich ja keine schlechte Sache, aber dovecot reagiert auf Zeitänderungen sehr verstimmt und quittiert den Dienst. Deshalb setze ich stets ntpd ein. Dies ist ein NTP-Server, der systematisch die Differenz zwischen Systemzeitgeber und dem Internetserver beobachtet und so systematisches zu schell bzw. zu langsam gehen des Systemzeitgebers korrigieren kann. Man erhält damit eine genauere Systemzeit und damit auch ein stabiles dovecot. Deshalb installiere ich ntpd und entferne ntpdate:

sudo apt-get autoremove --purge ntpdate && sudo apt-get install ntp

Um für den Ausfall des Ubuntu NTP-Servers gewappnet zu sein, habe ich die Server-Einträge in /etc/ntp.conf noch um Server aus dem öffentlichen NTP-Pool ergänzt:

# You do need to talk to an NTP server or two (or three).
server 0.pool.ntp.org
server 1.pool.ntp.org
server 2.pool.ntp.org
server ntp.ubuntu.com

Nach einem Speichern der Konfigurationsdatei und einem Neustart des NTP-Servers mit

sudo /etc/init.d/ntp restart

haben wir den ersten Punkt erledigt. Christoph Langner beschreibt die Installation von ntpd noch etwas ausführlicher.

Hostname für den Mailserver

Der zweite wichtige Punkt ist der Hostname. Der fully qualified domain name (FQDN) des Rechners muss bekannt sein. Nachprüfen lässt sich das über

hostname --fqdn

Bekommt man keine Ausgabe wie host.domain.de, dann muss man die /etc/hosts anpassen, so dass die Reihenfolge der Servernamen stimmt:

127.0.0.1	myserver	localhost

Bitte unbedingt beachten, dass das beispielhaft aufgeführte myserver kein FQDN ist. Ein FQDN besteht immer auch aus einer Top-Level-Domain.

Erzeugen von SSL-Zertifikaten

Damit wir mit imaps, dem durch Verschlüsselung abgesicherten IMAP, auf unseren Server zugreifen können, und auch den SMTP- und LDAP-Zugriff verschlüsseln können, benötigen wir entsprechende SSL-Zertifikate. Am einfachsten lassen sich solche Zertifikate mit easy-rsa aus dem Paktet openvpn erzeugen. Übrigens gibt es gibt es dazu gute Anleitungen von linux.neoberserker.de oder im OpenVPN-Wiki. Das Paket openvpn müssen wir jedoch nicht installieren. Es genügt, wenn wir mit

mkdir openvpn && cd openvpn && apt-get source openvpn

den Quelltext herunterladen. Wir führen alle folgenden Befehle zur Zertifikatserstellung als root aus (wichtig, damit später nicht jeder Benutzer die geheimen Dateien lesen kann). Zunächst kopieren wir das entsprechende Unterverzeichnis in /etc/ssl und löschen anschließend die nicht mehr benötigten Verzeichnisse mit

sudo -s
cp -R openvpn-2.1~rc11/easy-rsa/2.0 /etc/ssl/easy-rsa
cd .. && rm -rf openvpn
cd /etc/ssl/easy-rsa

Nun editieren wir die Datei vars und passen Sie entsprechend an. Bei mir habe ich folgende Zeilen am Ende angepasst:

export KEY_COUNTRY="DE"
export KEY_PROVINCE="RP"
export KEY_CITY="Ludwigshafen"
export KEY_ORG="Effinger"
export KEY_EMAIL="nospam@effinger.org"

Anschließend führen wir folgende Schritte durch, um die CA-Dateien zur Ausstellung eigener Zertifikate zu erzeugen. Beim Schritt ./build-ca kann man alle Punkte mit Enter bestätigen bis auf common name. Hier sollte man einen einfachen Namen, z.B. MyCA, angeben (am Besten nur Buchstaben und Zahlen verwenden – keine Leerzeichen oder sonstige Sonderzeichen).

. ./vars
./clean-all
./build-ca
./build-dh

Im nächsten Schritt erstellen wir für unseren Mailserver ein Server-Schlüsselpaar mit dem Befehl

./build-key-server myserver

myserver sollte dabei durch den DNS-Eintrag des Servers ersetzt werden (Thunderbird fragt ansonsten jedes Mal sicherheitshalber nach, ob das Zertifikat akzeptiert werden soll, weil der Zertifikatsname nicht mit dem Hostnamen übereinstimmt). Auch hier bestätigen wir wieder alles mit Enter bis auf den Punkt Sign the certificate? Hier antworten wir mit ja (y) und bestätigen die darauf erfolgende Rückfrage ebenfalls mit y. Ein Client-Zertifikat kann man mit

./build-key myclient

analog erzeugen. Dieses benötigt man jedoch nur, wenn man ausschließlich Clients mit gültigem Zertifikat auf den Mailserver zugreifen lassen möchte. Bei dovecot ist das der Fall, wenn der Parameter ssl_require_client_cert=yes gesetzt ist. Da dovecot sich mit dem LDAP-Server verbindet, können wir dazu ebenfalls ein Client-Zertifikat verwenden. Wir erzeugen es mit

./build-key dovecot-client

Im Unterverzeichnis keys sind nun einige Dateien, die wir noch in das richtige Verzeichnis kopieren müssen. Wichtig ist, dass niemand unbefugt auf die geheimzuhaltenden Dateien zugreifen kann, die allesamt mit der Erweiterung .key enden. Am Besten ist es, vor dem Kopieren die Berechtigungen zu prüfen. Die öffentlichen Zertifikate werden in das Verzeichnis /etc/ssl/certs und die geheimen Zertifikate in /etc/ssl/private kopiert mit

cp /etc/ssl/easy-rsa/keys/myserver.crt /etc/ssl/easy-rsa/keys/ca.crt /etc/ssl/certs/
cp /etc/ssl/easy-rsa/keys/myserver.key /etc/ssl/private/
chown root.ssl-cert /etc/ssl/private/myserver.key
chmod 640 /etc/ssl/private/myserver.key

Die letzten beiden Zeilen dienen dazu, Exim, Dovecot und LDAP den Zugriff auf die geheime Key-Datei zu gewähren. Die entsprechendenBenutzer müssen dazu in der Gruppe ssl-cert sein (Anleitung erfolgt bei der Installation des jeweiligen Programms). Falls man später doch noch OpenVPN nutzen möchte, kann man den Diffie-Hellman Parameter ebenfalls kopieren

cp /etc/ssl/easy-rsa/keys/dh1024.pem /etc/ssl/

Die Client-Zertifikate muss man nun natürlich dem E-Mail-Programm bekannt machen. Bei Thunderbird fügt man über Extras>Einstellungen>Erweitert>Zertifikate>Zertifikate>Zertifizierungsstellen>Importieren die Datei ca.crt hinzu, wechselt anschließend auf den Reiter Ihre Zertifikate, um dort dann die Dateien myclient.p12 importieren. Letzere Datei erzeugt man durch ein

openssl pkcs12 -export -name "myclient" -in myclient.crt -inkey myclient.key -out myclient.p12

OpenLDAP installieren

Als nächstes installieren wir OpenLDAP und die ldap-utils nach meinem OpenLDAP 1×1. Hier die Schritte in Kurzform (falls Schritte unklar sind – im OpenLDAP 1×1 ist alles sehr ausführlich erklärt):

  1. Alle folgenden Befehle als root ausführen mit einem
    sudo bash

    oder

    sudo -s
  2. apt-get install slapd ldap-utils

    Unbedingt das Administrator-Passwort bei der Einrichtung merken.

  3. /etc/init.d/slapd stop
  4. Die automatisch bei der Einrichtung erzeugte Datenbank löschen (Vorsicht, wenn OpenLDAP bereits im Einsatz ist! Dieser Befehl kann die aktive Datenbank löschen)
  5. rm /etc/ldap/slapd.d/cn\=config/olcDatabase\=\{1\}hdb.ldif && rm /var/lib/ldap/*
  6. Die folgende Datei database.ldif passen:
    # Database settings
    dn: olcDatabase=hdb,cn=config
    objectClass: olcDatabaseConfig
    objectClass: olcHdbConfig
    olcDatabase: hdb
    # The base of your directory
    olcSuffix: o=effinger
    # rootdn directive for specifying a superuser on the database. This is needed
    # for syncrepl.
    olcRootDN: cn=admin,o=effinger
    # Superuser Password for the database
    # {SSHA}pEvotN6PmSjx0JV/mZl5BWeSVOKR1Ejt equals "test"
    # CHANGE this for your installation!!!
    olcRootPW: {SSHA}pEvotN6PmSjx0JV/mZl5BWeSVOKR1Ejt
    # Where the database file are physically stored
    olcDbDirectory: /var/lib/ldap
    # The dbconfig settings are used to generate a DB_CONFIG file the first
    # time slapd starts.  They do NOT override existing an existing DB_CONFIG
    # file.  You should therefore change these settings in DB_CONFIG directly
    # or remove DB_CONFIG and restart slapd for changes to take effect.
    # For the Debian package we use 2MB as default but be sure to update this
    # value if you have plenty of RAM
    
    olcDbConfig: set_cachesize 0 2097152 0
    # Sven Hartge reported that he had to set this value incredibly high
    # to get slapd running at all. See http://bugs.debian.org/303057 for more
    # information.
    # Number of objects that can be locked at the same time.
    olcDbConfig: set_lk_max_objects 1500
    # Number of locks (both requested and granted)
    olcDbConfig: set_lk_max_locks 1500
    # Number of lockers
    olcDbConfig: set_lk_max_lockers 1500
    # Indexing options
    olcDbIndex: objectClass eq
    # Save the time that the entry gets modified
    olcLastMod: TRUE
    # Checkpoint the BerkeleyDB database periodically in case of system
    # failure and to speed slapd shutdown.
    olcDbCheckpoint: 512 30
    # The userPassword by default can be changed
    # by the entry owning it if they are authenticated.
    # Others should not be able to see it, except the
    # admin entry below
    # These access lines apply to database #1 only
    olcAccess: to attrs=userPassword,shadowLastChange by dn="cn=admin,o=effinger" write by anonymous auth by self write by * none
    # Ensure read access to the base for things like
    # supportedSASLMechanisms.  Without this you may
    # have problems with SASL not knowing what
    # mechanisms are available and the like.
    # Note that this is covered by the 'access to *'
    # ACL below too but if you change that as people
    # are wont to do you'll still need this if you
    # want SASL (and possible other things) to work
    # happily.
    olcAccess: to dn.base="" by * read
    # The admin dn has full write access, everyone else
    # can read everything.
    olcAccess: to * by dn="cn=admin,o=effinger" write by * read
    # For Netscape Roaming support, each user gets a roaming
    # profile for which they have write access to
    #olcAccess: to dn=".*,ou=Roaming,o=morsnet" by dn="cn=admin,o=effinger" write by dnattr=owner write

    Bitte unbedingt das Passwort (olcRootPW) ändern.
    Falls gewünscht auch die RootDN (hier „o=effinger“) anpassen. Dadurch müssen einige der folgenden Befehle/Dateien angepasst werden.

  7. Eine neue Datenbank mit Hilfe der database.ldif erzeugen (Administratorpasswort aus Schritt 2 wird benötigt)
    /etc/init.d/slapd start
    ldapadd -f database.ldif -x -D "cn=admin,cn=config" -W

Jetzt haben wir eine saubere Datenbank mit der RootDN „o=effinger“ und dem entsprechenden Administrator „cn=admin,o=effinger“, die wir nun weiter konfigurieren können. Bevor wir damit loslegen, muss man sich jedoch Gedanken machen, wie die Daten in OpenLDAP strukturiert werden sollen. Ich habe mich für folgendes Setup entschieden:

  • Benutzer werden im Kontext ou=users,o=effinger gespeichert also z.B. uid=paul,ou=users,o=effinger. Hier wird auch die lokale Mail-Addresse paul abgelegt. Die Domainendung (@myserver) wird hier weggelassen, da teilweise die Domain nicht angegeben ist bzw. oft anders addressiert ist, z.B. paul@localhost
  • Externe Mail-Accounts des Benutzers werden jeweils unter dem zugehörigen Benutzereintrag gespeichert, also z.B. dcSubMailAddress=paulpanzer@gmx.de,uid=paul,ou=users,o=effinger, zusammen mit den Angaben zu Logins für SMTP und den Mailabruf, z.B. mit POP3.
  • Da dovecot jedoch nicht ganz flexibel mit LDAP umgehen kann, müssen wir Parameter wie uid, Angaben zum Speicherort der Mails, die unter uid=paul,ou=users,o=effinger verfügbar sind auch unter dcSubMailAddress=paulpanzer@gmx.de,uid=paul,ou=users,o=effinger verfügbar machen. Das geht mit dem DynList/DynGroup Overlay von OpenLDAP. Eine Alternative wäre das slapo-rwm Overlay gewesen, das allerdings in der aktuellen Ubuntu-Version noch einen Bug aufweist und deshalb außen vor bleibt.

Nach den konzeptionellen Überlegungen machen wir uns nun an die Arbeit. Wir konfigurieren das DynList-Overlay, wobei mir eine Anleitung für Gentoo und die kurze Einführung für Ubuntu sehr geholfen haben und ergänzen OpenLDAP mit einem von mir erstellten Schema (dovecot.schema.ldif).

  1. Folgenden Inhalt unter dem Namen dyngroup.schema.ldif abspeichern:
    dn: cn=dyngroup,cn=schema,cn=config
    objectClass: olcSchemaConfig
    cn: dyngroup
    olcObjectIdentifier: NetscapeRoot 2.16.840.1.113730
    olcObjectIdentifier: NetscapeLDAP NetscapeRoot:3
    olcObjectIdentifier: NetscapeLDAPattributeType NetscapeLDAP:1
    olcObjectIdentifier: NetscapeLDAPobjectClass NetscapeLDAP:2
    olcObjectIdentifier: OpenLDAPExp11 1.3.6.1.4.1.4203.666.11
    olcObjectIdentifier: DynGroupBase OpenLDAPExp11:8
    olcObjectIdentifier: DynGroupAttr DynGroupBase:1
    olcObjectIdentifier: DynGroupOC DynGroupBase:2
    olcAttributeTypes: ( NetscapeLDAPattributeType:198 NAME 'memberURL' DESC 'Identifies an URL associated with each member of a group. Any type of labeled URL can be used.' SUP labeledURI )
    olcAttributeTypes: ( DynGroupAttr:1 NAME 'dgIdentity' DESC 'Identity to use when processing the memberURL' SUP distinguishedName SINGLE-VALUE )
    olcAttributeTypes: ( DynGroupAttr:2 NAME 'dgAuthz' DESC 'Optional authorization rules that determine who is allowed to assume the dgIdentity' EQUALITY authzMatch SYNTAX 1.3.6.1.4.1.4203.666.2.7 X-ORDERED 'VALUES' )
    olcObjectClasses: ( NetscapeLDAPobjectClass:33 NAME 'groupOfURLs' SUP top STRUCTURAL MUST cn MAY ( memberURL $ businessCategory $ description $ o $ ou $ owner $ seeAlso ) )
    olcObjectClasses: ( DynGroupOC:1 NAME 'dgIdentityAux' SUP top AUXILIARY MAY ( dgIdentity $ dgAuthz ) )

    und mit einem

    ldapadd -D "cn=admin,cn=config" -x -W -f dyngroup.schema.ldif

    hinzufügen (Administrator-Passwort wird benötigt).

  2. Als nächstes folgenden Inhalt unter dem Namen dovecot.schema.ldif abspeichern
    dn: cn=dovecot,cn=schema,cn=config
    objectClass: olcSchemaConfig
    cn: dovecot
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.1.1.1 NAME 'dcMailMessageStore' DESC 'Path to the maildir/mbox on the mail system' EQUALITY caseExactIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.1.1.2 NAME 'dcMailAlias' DESC 'Secondary (alias) mailaddresses for a user' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.1 NAME 'dcSubMailAddress' DESC 'A users secondary e-mail address for which mail from on another Mailserver has to be fetched' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.2 NAME 'dcAccountStatus' DESC 'The status of a user account: active, noaccess, disabled, deleted' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.3 NAME 'dcSMTPServer' DESC 'Outgoing mails should be delivered to this Mailserver via SMTP.' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.4 NAME 'dcSMTPLogin' DESC 'Login credential to send Mail with the SMTP server' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.5 NAME 'dcSMTPPassword' DESC 'A separate text that stores the SMTP account password in clear text' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.6 NAME 'dcRetrieveType' DESC 'Tells getmail what mail account to retrieve mail from, and how to access that account, e.g. SimplePOP3Retriever and BrokenUIDLPOP3SSLRetriever' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.7 NAME 'dcRetrieveServer' DESC 'Incoming mails have to be downloaded from this server' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.8 NAME 'dcRetrieveLogin' DESC 'Login credential to receive Mail from the server' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.9 NAME 'dcRetrievePassword' DESC 'Password for mail retrieval in clear text' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.10 NAME 'dcMailQuota' DESC 'The size of space the user can have until further messages get bounced.' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.11 NAME 'dcMailSizeMax' DESC 'The maximum size of a single messages the user accepts.' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.12 NAME 'dcMailAlternateAddress' DESC 'Secondary (alias) mailaddresses for an external Mail Account' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
    olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.3.1.1 NAME 'dcPosixOwnerURL' DESC 'Identifies an URL associated with the posixOwner of the entry. Any type of labeled URL can be used.' SUP labeledURI )
    olcObjectClasses: ( 1.3.6.1.4.1.32589.1.1.2.1 NAME 'dcMailUser' DESC 'Dovecot-LDAP User' SUP top AUXILIARY MUST dcMailMessageStore MAY dcMailAlias )
    olcObjectClasses: ( 1.3.6.1.4.1.32589.1.2.2.1 NAME 'dcExternalMailAccount' DESC 'Dovecot-LDAP external mail account' SUP top STRUCTURAL MUST ( dcSubMailAddress $ dcAccountStatus ) MAY ( dcSMTPServer $ dcSMTPLogin $ dcSMTPPassword $ dcRetrieveType $ dcRetrieveServer $ dcRetrieveLogin $ dcRetrievePassword $ dcMailQuota $ dcMailSizeMax $ dcMailAlternateAddress ) )
    olcObjectClasses: ( 1.3.6.1.4.1.32589.1.3.2.1 NAME 'dcPosixSubAccount' DESC 'LDAP-URL for retrieving the respective posixAccount of an entry' SUP top AUXILIARY MAY dcPosixOwnerURL )

    und ebenfalls in die Konfiguration übernehmen mit

    ldapadd -D "cn=admin,cn=config" -x -W -f dovecot.schema.ldif
  3. Jetzt aktivieren wir das DynList-Modul und speichern dazu Folgendes als dynlist_moduleLoad.ldif
    dn: cn=module{0},cn=config
    changetype: modify
    add: olcModuleLoad
    olcModuleLoad: dynlist.so

    um es anschließend zur OpenLDAP-Konfiguration hinzuzufügen mit einem

    ldapmodify -D "cn=admin,cn=config" -x -W -f dynlist_moduleLoad.ldif
  4. Dem Dynlist-Overlay müssen wir außerdem mitteilen, dass das Attribut dcPosixOwnerURL jeweils auf den zugehörigen Benutzer verweist. Das machen wir, indem wir den folgenden Inhalt als dynlist_activateOnSuffix.ldif abspeichern
    dn: olcOverlay=dynlist,olcDatabase={1}hdb,cn=config
    objectClass: olcOverlayConfig
    objectClass: olcDynamicList
    olcDLattrSet: dcPosixSubAccount dcPosixOwnerURL
    olcOverlay: dynlist

    und dann

    ldapadd -D "cn=admin,cn=config" -x -W -f dynlist_activateOnSuffix.ldif

    ausführen.

  5. Nun müssen wir einen Grundeintrag in LDAP vornehmen, bevor wir starten können. Außerdem benötigen wir einen Benutzer secmail, um Mails von externen Servern in festen Intervallen abzurufen und in das jeweilige lokale IMAP-Postfach abzulegen. Daher legen wir mit der folgenden LDIF-Datei database-content.ldif zunächst den Grundeintrag und den Benutzer secmail an (Passwort wieder unbedingt mit slappasswd anpassen) an
    # effinger
    dn: o=effinger
    objectclass: organization
    objectclass: top
    o: effinger
    
    # users, effinger
    dn: ou=users,o=effinger
    objectClass: organizationalUnit
    objectClass: top
    ou: users
    
    # secmail, users, effinger
    dn: uid=secmail,ou=users,o=effinger
    objectClass: posixAccount
    objectClass: account
    objectClass: top
    cn: secmail
    gidNumber: 134
    homeDirectory: /home/secmail
    uid: secmail
    uidNumber: 121
    # This password equals test
    userPassword: {SSHA}R+pQv9aIQINrPYdgljEJ0B7jzCp2cCzz

    und fügen sie mit einem

    ldapadd -D "cn=admin,o=effinger" -x -W -f database-content.ldif

    zum LDAP-Verzeichnis hinzu (Achtung Passwort verwenden, das für database.ldif erzeugt wurde)

  6. SSL/TLS aktivieren, dazu folgenden Inhalt als ssl-tls_init.ldif abspeichern
    dn: cn=config
    changetype: modify
    add: olcTLSCACertificateFile
    olcTLSCACertificateFile: /etc/ssl/certs/ca.crt
    
    dn: cn=config
    changetype: modify
    add: olcTLSCertificateFile
    olcTLSCertificateFile: /etc/ssl/certs/myserver.crt
    
    dn: cn=config
    changetype: modify
    add: olcTLSCertificateKeyFile
    olcTLSCertificateKeyFile: /etc/ssl/private/myserver.key

    und folgende Befehle ausführen:

    ldapmodify -D "cn=admin,cn=config" -x -W -f ssl-tls_init.ldif
    sudo adduser openldap ssl-cert

    Ein Neustart ist ebenfalls erforderlich, da ich die Erfahrung gemacht habe, dass ohne einen Neustart der Zugriff über TLS nicht funktioniert.

    /etc/init.d/slapd restart
  7. Im nächsten Schritt der LDAP-Konfiguration richten wir Zugriffsrechte ein. Generell soll auf die Login-Daten bei externen Mailservern nur der jeweilige Benutzer selbst und der LDAP-Administrator lesend und schreibend zugreifen können, während der secmail Benutzer nur Leserechte benötigt. Diese Zugriffsrechte werden in der Datei add_acl.ldif mit dem Inhalt
    dn: olcDatabase={1}hdb,cn=config
    changetype: modify
    add: olcAccess
    # The information to send and receive mails from remote servers
    # can only be modified by the user itself and the admin
    # the secmail user which will retrieve mails must have read access
    olcAccess: {1}to dn.regex=".*uid=([^,]+),ou=users,o=effinger" attrs=dcRetrieveType,dcRetrieveLogin,dcRetrievePassword,dcRetrieveServer,dcSMTPLogin,dcSMTPPassword,dcSMTPServer by dn="cn=admin,o=effinger" write by dn.exact,expand="uid=$1,ou=users,o=effinger" write by dn="uid=secmail,ou=users,o=effinger" read by * none
    # Users shall have write access to their attributes
    # admin shall have write access as well
    # all other users have only read access
    olcAccess: {2}to dn.regex=".*uid=([^,]+),ou=users,o=effinger" attrs=dcMailAlternateAddress by dn="cn=admin,o=effinger" write by dn.exact,expand="uid=$1,ou=users,o=effinger" write by * read

    durch den Befehl

    ldapmodify -D "cn=admin,cn=config" -x -W -f add_acl.ldif

    zum LDAP-Verzeichnis hinzugefügt.

  8. Im letzten Schritt indizieren wir wichtige Felder für die Suche im LDAP-Verzeichnis. Das schont Ressourcen und sorgt außerdem dafür,  dass die dezenten Hinweise von OpenLDAP in der Syslog, dass einzelne Attribute indiziert werden sollten, verschwinden. Was die einzelnen Indexoptionen bedeuten ist auf zytrax.com erklärt. Wir legen die Datei add_attribute_indices.ldif mit dem Inhalt
    dn: olcDatabase={1}hdb,cn=config
    changetype: modify
    add: olcDbIndex
    olcDbIndex: cn pres,eq,sub
    olcDbIndex: sn pres,eq,sub
    olcDbIndex: uid pres,eq
    olcDbIndex: mail pres,eq,sub
    olcDbIndex: dcMailAlias pres,eq
    olcDbIndex: givenName pres,eq,sub
    olcDbIndex: dcSubMailAddress pres,eq
    olcDbIndex: dcMailAlternateAddress pres,eq
    olcDbIndex: dcAccountStatus pres,eq

    an und fügen sie mit dem Befehl

    ldapmodify -D "cn=admin,cn=config" -x -W -f add_attribute_indices.ldif

    dem Verzeichnis hinzu.

Zugriff auf OpenLDAP-Server absichern

Durch die Anpassung der Datei ldap.conf können wir festlegen, an welchen LDAP-Server Anfragen standardmäßig gerichtet werden sollen und unter welchen Bedingungen eine Verbindung mit diesem akzeptiert wird. Wir möchten die Konfiguration so anpassen, dass der OpenLDAP-Server ein gültiges Zertifikat vorweisen muss und standardmäßig der gerade eingerichtete LDAP-Server befragt wird. Standardmäßig werden die Anfragen zwar sowieso an den lokalen Rechner gerichtet, aber die Angabe des DNS-Namens ist notwendig, da sonst die Gültigkeitsprüfung für das Serverzertifikat fehlschlagt. In der Datei /etc/ldap/ldap.conf tragen wir folgende Zeilen ein (myserver durch den DNS-Namen ersetzen):

URI             ldap://myserver
TLS_CACERT      /etc/ssl/certs/ca.crt
TLS_REQCERT     demand

Ein anschließender Test mit dem Befehl

ldapsearch -x -b "o=effinger" -ZZ

sollte Einträge des LDAP-Servers zurückgeben. Eigentlich wäre es auch das Beste, wenn der LDAP-Server nur TLS-verschlüsselte Verbindungen akzeptieren würde. Das kann man über ACL mit den Security Strength Factors (SSF) einstellen, allerdings unterstützt Exim bislang keine TLS-verschlüsselten LDAP-Verbindungen, so dass wir hierauf verzichten.

LDAP-Einträge hinzufügen

Jetzt können wir Einträge in OpenLDAP anlegen. Sehr komfortabel kann man dazu JXplorer verwenden (zur Installation siehe Abschnitt Die nächsten Schritt mit LDAP im OpenLDAP 1×1). Wir starten JXplorer und wählen im Menü Datei>Verbinden. Dort tragen wir folgendes ein (localhost bzw. myserver anpassen):
Connection Dialog from JXplorer

Die Daten noch mal im Überblick:

  • Host: myserver Port:389 (myserver anpassen)
  • Base DN: o=effinger (ggfs. anpassen)
  • Benutzer DN: cn=admin,o=effinger (ggfs. anpassen)
  • Kennwort: Das Passwort, das wir für die Datei database.ldif gewählt haben (s.o.).

Nach der erfolgreichen Verbindungsherstellung sehen wir die LDAP-Hierarchie und erweitern den Baum unter o=effinger, so dass wir folgendes sehen:
LDAP Hierarchie nach dem Hinzufügen von users

Im nächsten Schritt fügen wir unseren ersten Benutzer Paul hinzu. Dazu Rechtsklick auf users im LDAP-Baum und Neu auswählen. Im nachfolgenden Dialog ändern wir die RDN auf uid=paul und fügen die Klassen top, person, organizationalPerson, inetOrgPerson, posixAccount und dcMailUser hinzu.
Adding a user to the LDAP directory with JXplorer

Nun sehen wir im nächsten Dialog einige fett gedruckte Attribute – diese sind Pflichtattribute und müssen daher ausgefüllt werden.
Adding necessary user attributes with JXplorer

  • cn steht für common name und ist einfach eine Bezeichnung für den Eintrag, am einfachsten ist es, man wählt hier Vornamen und Nachnamen des Benutzers
  • dcMailMessageStore gibt  das Grundverzeichnis an, in welchem die E-Mails abgelegt werden sollen. Wir werden Dovecot später so konfigurieren, dass wir dieses Verzeichnis (z.B. /home/paul/mail) um die E-Mail-Addresse ergänzen, so dass man z.B. /home/paul/mail/paul/ erhält. Letzeres wird in Dovecot das Home-Verzeichnis sein, in dem u.a. die .dovecot.sieve gespeichert wird. Die Mails werden später als Maildir im Unterverzeichnis maildir abgelegt, also /home/paul/mail/paul/maildir
  • gidNumber gibt die GruppenID des Benutzers Paul an. Paul sollte bereits als Benutzer auf dem Rechner angelegt sein, so dass man über ein
    id paul

    die gid herausfinden kann.

  • homeDirectory das Heimverzeichnis des Benutzers Paul. Den korrekten Wert kann man herausfinden durch ein
    cat /etc/passwd | grep paul | cut -d: -f6
  • sn steht für surname, also den Nachnamen des Benutzers
  • givenName steht für den Vornamen des Benutzers, ist allerdings ein optionales Attribut
  • uidNumber die BenutzerID von Paul. Der korrekte Wert ist analog zur gidNumber herauszufinden – statt gid dann den Wert von uid verwenden.
  • userPassword Damit Paul sich einloggen kann, legen wir ein Passwort für ihn fest. Das Passwort sollte keinen Slash „/“ enthalten, da in der Exim-Konfiguration dieses Zeichen zur Trennung einer zusammengesetzten Zeichenfolge aus Login und Passwort verwendet wird.
  • mail Dieses Attribut steht für die lokale E-Mail-Addresse von Paul. Die lokale E-Mail-Addresse wird dabei ohne die Domain angegeben. In diesem Fall genügt also der Eintrag „paul“ für die Addresse paul@myserver

Danach klicken wir auf den Button Abschicken und Paul ist als Benutzer in LDAP verfügbar.

Jetzt richten wir noch den externen MailAccount von Paul ein, damit er auch seine Mails von GMX abrufen bzw. über GMX schicken kann. Dazu erweitern wir die Ansicht der LDAP-Hierarchie, so dass wir mit einem Rechtsklick auf paul erneut den Eintrag Neu wählen können.
LDAP tree after adding paul as a user
Im erscheinenden Dialogfeld wählen wir die Klassen dcExternalMailAccount und dcPosixSubAccount aus. RDN setzen wir auf dcSubMailAddress=paulpanzer@gmx.de. Folgende Attribute können bzw. müssen wir eintragen:

  • dcSubMailAddress steht für die Mail-Addresse des externen Accounts. Lokale Mails an diese Addresse werden ohne den Umweg über den externen Mailprovider zugestellt.
  • dcAccountStatus kann die Werte active, noaccess, disabled und deleted annehmen. Wir wählen active.
  • dcMailQuota ist ein Attribut, das  wir nicht verwenden werden, allerdings könnte man hier zukünftig eine Größenbeschränkung für die paulpanzer@gmx.de-Mailbox  einrichten.
  • dcMailSizeMax verwenden wir ebenfalls nicht, allerdings könnte man hier zukünftig eine Beschränkung der Größe der zu versendenden E-Mails festlegen.
  • dcRetrieveType gibt den Protokoll/Typ an, mit dem die Mails abgerufen werden sollen. Beispielhafte Werte sind SimplePOP3Retriever, BrokenUIDLPOP3Retriever oder SimpleIMAPSSLRetriever. Eine detaillierte Auflistung findet sich in der Dokumentation von getmail.
  • dcRetrieveLogin der Benutzername für den Mailabruf, bei GMX üblicherweise die E-Mail-Addresse
  • dcRetrievePassword das zugehörige Passwort, um Mails abzurufen.
  • dcRetrieveServer der Name/IP des Servers für das Abrufen von Mails. Bei GMX mit POP3 ist es pop.gmx.net.
  • dcSMTPLogin der Benutzername für den SMTP-Server, bei GMX üblicherweise die E-Mail-Addresse.
  • dcSMTPPassword das zugehörige Passwort, um Mails zu versenden.
  • dcSMTPServer der Name/IP des SMTP-Servers. Bei GMX ist es mail.gmx.net.
  • dcMailAlternateAddress steht für eventuelle Alias-Addressen der bei dcSubMailAddress angegebenen E-Mail-Addresse.  Besitzt Paul Panzer also für die Addresse paulpanzer@gmx.de noch den Alias p.panzer@gmx.de kann er die Mail hier eintragen und Mails über den lokalen Server werden direkt ohne Umwege über GMX zugestellt.
  • dcPosixOwnerURL dient dazu, dass dovecot wichtige Parameter, wie uid, uidNumber,gidNumber und dcMailMessageStore vom übergeordneten Benutzereintrag von Paul bekommt. Hier tragen wir folgende LDAP-URL ein:
    ldap:///uid=paul,ou=users,o=effinger?uid,uidNumber,gidNumber,dcMailMessageStore?base?(&(objectClass=posixAccount)(objectClass=dcMailUser))

Und so sieht das bei mir aus:
Adding an external mail account to the LDAP directory
Nun wieder auf Abschicken klicken und der Eintrag sollte vorhanden sein. Wichtig ist, jetzt nochmal zu prüfen, ob auch das Dynlist-Overlay funktioniert. Das machen wir mit einem

ldapsearch -b "dcSubMailAddress=paulpanzer@gmx.de,uid=paul,ou=users,o=effinger" -x

Dieser Befehl sollte unter anderem die Zeilen mit den Attributen uid, uidNumber,gidNumber und dcMailMessageStore augeben:

dcMailMessageStore: /home/paul
gidNumber: 1000
uidNumber: 1000
uid: paul

Testen und Mitschneiden von Anfragen an OpenLDAP

Zum Testen und Debuggen ist es oft hilfreich, zu überprüfen, welche LDAP Anfragen an den OpenLDAP-Server gestellt wurden. Dazu kann man unter cn=config (mit cn=admin,cn=config einloggen) den Parameter olcLogLevel von none auf einen numerischen Wert ändern. 256 hat sich für mich als gut bewährt, bei Terrence Miao findet man aber eine detaillierte Auflistung der einzelnen Loglevels. Die LDAP-Anfragen werden dann in die syslog geschrieben.

Da der Artikel nun schon ziemlich lang ist, folgt die Konfiguration von dovecot in einem zweiten Teil.

Tips für Ubuntu Server unter Virtualbox

In diesem Beitrag beschreibe ich, wie die Maus im Terminalmodus aktiviert werden kann, wie man mit VirtualBox >= 2.1.0 trotz nichtverbundenem Netzwerkkabel auf sein Gastsystem unter Windows XP zugreifen kann und wie man die Gasterweiterungen installiert.

Maus im Terminalmodus aktivieren

Betreibt man als Gastsystem Ubuntu in der Server Version, so möchte man normalerweise keine grafische Oberfläche installieren. Dennoch wäre es manchmal sehr hilfreich, man könnte zumindest die Maus nutzen. Das geht und zwar mit gdm, dem General Purpose Mouse Interface. Dieses lässt sich ganz einfach installieren mit einem

sudo apt-get install gpm

Permanent auf Gastsystem über Netzwerk zugreifen

In VirtualBox Versionen ab 2.1.0 wurde das Netzwerksetup komplett überarbeitet. Als Folge werden Hostinterfaces nicht mehr als eigener Netzwerkadapter auf dem Hostsystem erzeugt, sondern unmittelbar einem dort existierenden Netzwerkadapter zugeordnet. Das macht aus meiner Sicht durchaus Sinn, hat aber bei mir einen unerwünschten Nebeneffekt gehabt. Sobald das Netzwerkkabel meines Netzwerkadapters auf dem Hostsystem entfernt wurde, konnte ich auch nicht mehr auf das Gastsystem zugreifen, dessen Hostinterface diesem Netzwerkadapter zugeordnet war. Allerdings möchte ich ja auch unterwegs, wenn ich keine Netzwerverbindung habe, mit meinem Gastsystem arbeiten. Eine Lösung habe ich in der VirtualBox FAQ gefunden. Man installiert ein Loopback Netzwerkadapter entsprechend der Anleitung von Microsoft für Windows XP (sollte unter Vista analog funktionieren). Nun hat man zwei Möglichkeiten, um das Gastsystem daran anzubinden. Man kann eine Netzwerkbrücke zwischen dem bisherigen Netzwerkadapter, dem das VirtualBox Hostinterface zugeordnet ist, und dem neuen Loopback Netzwerkadapter bilden. Dazu unter Start > Systemsteuerung > Netzwerkverbindungen beide Netzwerkvebindungen markieren, nach einem Rechtsklick den Menüpunkt Verbindungen überbrücken auswählen. Alternativ kann man unter VirtualBox dem Gastsystem eine weitere Netzwerkverbindung vom Typ Hostinterface hinzufügen und wählt dort als Netzwerkkarte des Hosts die entsprechende Loopback Netzwerkverbindung aus. Ich habe mich für letzteres entschieden. Man muss in diesem Fall noch entsprechende IP-Addressen vergeben, damit Host- und Gastsystem miteinander kommunizieren können. Dem Host- bzw. Gastsystem habe ich die folgenden Werte zugewiesen:

Hostsystem (hier: Windows XP) Gastsystem (hier: Ubuntu)
IP-Addresse 192.168.254.1 192.168.254.2
Netzwerkmaske 255.255.255.252 255.255.255.252

Die Windows-Konfiguration erfolgt grafisch (analog zu der Anleitung der Uni Köln, Gateway und DNS-Server frei lassen). Bei Ubuntu editiert man dazu die Datei /etc/network/interfaces und fügt folgenden Eintrag hinzu (ggfs. Interface anpassen – hier eth1):

auto eth1
iface eth1 inet static
address 192.168.254.2
netmask 255.255.255.252

Nach einem

sudo /etc/init.d/networking restart

sollte die Verbindung zwischen Host- und Gastsystem möglich sein (testen mit ping).

Gasterweiterungen unter Ubuntu Server installieren

Um die Gasterweiterung, die beispielsweise das gemeinsame Nutzen von Ordnern des Host- und Gastsystems zulässt, zu installieren, müssen zunächst die entsprechenden Pakete installiert sein. Unter anderem werden die Kernel-Header Dateien benötigt. Dies habe ich zum Anlass genommen  gleich auf die neueste Kernelversion von Ubuntu 8.04 Server umzusteigen (wohl gemerkt: das dist-upgrade führt hier nicht zu einem Upgrade der Distributionsversion also z.B. 8.04 auf 8.10, da man hierfür die entsprechenden Einträge in /etc/apt/sources.list ändern müsste).

sudo apt-get update && sudo apt-get dist-upgrade

Im nächsten Schritt müssen wir die benötigten Pakete für die Gasterweiterungen installieren.

sudo apt-get install linux-headers-server make gcc

Anschließend müssen die Gasterweiterungen als CD-ROM über den Menübefehl Geräte > Gasterweiterungen installieren zur Verfügung gestellt werden. Durch das Mounten der CD-ROM mit

sudo mount /media/cdrom

und den anschließenden Aufruf des Installationsprogramms mit

sudo /media/cdrom/VBoxLinuxAdditions-x86.run

(ggfs. für 64-bit System anpassen) und anschließendem Neustart des Gastsystems werden alle erforderlichen Schritte erledigt.

LDIF-Dateien zur Konfiguration von OpenLDAP bequem erzeugen

In einem vorherigen Artikel habe ich beschrieben, wie man ein eigenes LDAP-Schemas erstellen kann. Im letzten Schritt muss dabei die von slaptest erzeugte LDIF-Datei von Hand angepasst werden. Diesen Vorgang habe ich mittlerweile durch ein sed Skript autmatisiert. Geholfen hat mir dabei die Vorlage von Vishal Goenka. Neben dem Einfügen von Kommentaren wurde das Skript noch ergänzt, damit alle von OpenLDAP eingefügten Nummerierungen und unnötigen Zeilen am Schluss entfernt werden. Als sed-Neuling haben mit dabei folgende Webseiten weitergeholfen:

Nach Aufrufen des Skriptes von der Shell mit

unldif.sed original_cn_config_file.ldif > modified_cn_config_file.ldif

muss man lediglich noch wie gehabt die erste Zeile mit dn anpassen, die sich von Fall zu Fall unterscheiden kann. Zum Schluss nun das Skript:

#!/bin/sed -nf
# Disclaimer and Terms: You may use these scripts for commercial or
# non-commercial use at your own risk, as long as you retain the
# copyright statements in the source code. These scripts are provided
# "AS IS" with no warranty whatsoever and are FREE for as long as you
# want to use them. You can edit and adapt them to your requirements
# without seeking permission from me. I only ask that you retain the
# credits where they are due.
#
# Adapted by Markus Effinger <blog[at-nospam]effinger.org>
#
# Original Author: Vishal Goenka <vgoenka@hotmail.com>
#
# Unfold LDIF (LDAP Data Interchange Format) lines for scheme files
# Version 1.0
#
# Usage: unldif.sed <ldif file>
#              or
#        cat <ldif file> | unldif.sed
# and if /usr/bin/sed is not available,
#        sed -nf unldif.sed <ldif file>
#
# Most LDIF generators will fold a long field on multiple lines by
# inserting a line separator (either a linefeed or carriage
# return/linefeed pair) followed by a space. Processing such ldif
# files through another script becomes much easier if such lines were
# unfolded. That is exactly what this script does. It unfolds ldif
# entries that are folded (broken) across lines and writes them on a
# single line.
#
# This Line
# Replace any "{2}" numbering that was added by slaptest
s/\(^[^:]*: \){[^}]*}\(.*\)$/\1\2/;
{
	# Append first line to hold space and
	# put the next line into the pattern space
	1{
		h;
		n;
	};
	# Delete anything after structuralObjectClass
	/^structuralObjectClass/,$ {
		# These commands get run for each line after
		# structuralObjectClass - Therefore we have to make
		# sure, that the hold buffer gets only printed once
		# Get content from hold buffer to pattern buffer
		g;
		# Remove a newline followed by a space
		s/\n //;
		# Print the pattern buffer if not empty
		/^$/!p;
		# Make pattern buffer empty and save in hold buffer
		s/^.*$//;
		h;
		# Continue with next line
		d;
	};
	# If line starts not with space
	/^ /!{
		# Append a newline to the hold space and add the current line
		H;
		# Replace the content of the pattern space with the hold space
		g;
		# Print the first line of the pattern space
		# Delete everything after the first line in the pattern space
		# and print the rest (first line)
		s/\n.*//p;
		# Fill the pattern space again with the hold space
		g;
		# Delete the first line which has just been printed
		s/.*\n//;
		# Put the result in the hold space
		h;
	};
	/^ /{
		# Append a newline to the hold space and add the current line
		H;
		# Replace the content of the pattern space with the hold space
		g;
		# Remove a newline followed by a space
		s/\n //;
		# Write the result to hold space
		h;
	};
	${
		# Replace the content of the pattern space with the hold space
		g;
		# Remove a newline followed by a space
		s/\n //;
		# Print the result
		p;
	};
};

ufw – Firewall in Ubuntu

ufw (uncomplicated firewall) ist zwar die Standard-Firewall von Ubuntu, aber im Auslieferungszustand bei der Desktop-Version nicht aktiviert. Nach einem

sudo ufw enable
sudo ufw default deny

ist sie aktiv und befolgt folgende Regeln (siehe Ubuntu-Wiki) in Intrepid Ibex:

  1. Alle loopback-Verbindungen akzeptieren, d.h. vom lokalen Rechner aus kann man auf jeden beliebigen Port zugreifen.
  2. Alle ausgehenden Verbindungen zulassen.
  3. Alle eingehenden Verbindungen ablehnen.
  4. Alle abgelehnten Pakete in die Syslog schreiben (–limit 3/min), also maximal drei Einträge pro Minute.

Ich habe gleich mal den SSH-Zugang freigeschaltet durch ein

sudo ufw allow OpenSSH

Um einzelne Anwendungen/Ports frei zu schalten, habe ich mir noch ein paar zusätzliche Profile im Verzeichnis /etc/ufw/applications.d/ erstellt:

$ cat deluge
[Deluge]
title=Deluge Bittorrent Client
description=Deluge is an open source bittorrent client.
ports=5050,5051/tcp
$ cat vino-server
[vino-server]
title=Vino VNC Server
description=Vino is an open source VNC server
ports=5900/tcp
$ cat exim
[Exim SMTP]
title=Exim Message Transfer Agent
description=Exim is an open source mail transfer agent (MTA) providing services such as SMTP to send e-mails.
ports=25/tcp
$ cat openldap
[OpenLDAP]
title=Server for the Lightweight Directory Access Protocol (LDAP)
description=OpenLDAP is an open source implementation of a Lightweight Directory Access Protocol Server
ports=389/tcp

[OpenLDAP Secure]
title=Secure Server for the Lightweight Directory Access Protocol (LDAPS)
description=OpenLDAP is an open source implementation of a Lightweight Directory Access Protocol Server
ports=636/tcp
$ cat dovecot-managesieve
[Dovecot Managesieve]
title=Dovecot Managesieve Protocol
description=Dovecot Managesieve allows to remotely administer sieve filters
ports=2000/tcp

Danach habe ich VNC, deluge, exim, dovecot imap und imaps, CUPS, Samba, LDAP (wegen Adressbuch) für das lokale Netz freigeschalten mit

sudo ufw allow from 192.168.0.0/16 to any app CUPS
sudo ufw allow from 192.168.0.0/16 to any app Samba
sudo ufw allow from 192.168.0.0/16 to any app "Dovecot IMAP"
sudo ufw allow "Dovecot Secure IMAP"
sudo ufw allow from 192.168.0.0/16 to any app "Dovecot Managesieve"
sudo ufw allow from 192.168.0.0/16 to any app vino-server
sudo ufw allow Deluge
sudo ufw allow from 192.168.0.0/16 to any app "OpenLDAP"
sudo ufw allow from 192.168.0.0/16 to any app "OpenLDAP Secure"
sudo ufw allow from 192.168.0.0/16 to any app "Exim SMTP"

bzw. falls man nicht Exim sondern Postfix einsetzt, welches standardmäßig installiert ist, die letzte Zeile ersetzen mit

sudo ufw allow from 192.168.0.0/16 to any app "Postfix"
sudo ufw allow from 192.168.0.0/16 to any app "Postfix Submission"

Die Regeln werden übrigens in /var/lib/ufw/user.rules gespeichert. Eine Anleitung zur Erstelltung eigener ufw-Regeln, findet sich in der Hilfe der Ubuntu Server Edition. Im Ubuntu-Forum sind außerdem einige Beispiele zu ufw.

Wenn man wie ich VirtualBox über Proxy ARP auf das Netzwerk zugreifen lässt, sollte man in der Datei /etc/default/ufw in folgender Zeile das DROP auf ACCEPT ändern, da ansonsten die virtuellen Maschinen nur noch Verbindungen zum Host aufbauen können.

# set the default forward policy to ACCEPT or DROP.  Please note that if you
# change this you will most likely want to adjust your rules
# Default was DROP
DEFAULT_FORWARD_POLICY="ACCEPT"

Normalerweise sollte nach einem

sudo ufw enable

die Firewall bei jedem Neustart auch aktiviert werden. Falls dies nicht der Fall ist, muss man ggfs. in der Datei /etc/ufw/ufw.conf ENABLED auf yes setzen:

# /etc/ufw/ufw.conf
#
# set to yes to start on boot
ENABLED=yes

Das Einzige, was mir an ufw noch fehlt, ist, dass keine Regeln für Interfaces unterstützt werden (siehe Feature Request), aber vielleicht kommt das ja noch..

Nach der Aktivierung hatte ich außerdem einige unschöne Einträge in meiner Logdatei, die einen Zugriff von meinem Router auf den Port registrierten:

Jan 19 05:36:14 abraxas kernel: [51524.306320] [UFW BLOCK INPUT]: IN=eth1 OUT= MAC=00:11:d8:59:8a:18:00:15:0c:d5:1f:02:08:00 SRC=192.168.178.1 DST=192.168.178.200 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=29386 DF PROTO=TCP SPT=4981 DPT=14013 WINDOW=5840 RES=0x00 SYN URGP=0

Nachforschungen im Internet ergaben, dass es sich um die Kindersicherung der Fritz-Box handelt. Diese lässt sich über das Webinterface deaktivieren, allerdings hören die Portzugriffe erst nach einem Neustart auf.

Das Fazit zu ufw: Wirklich unkompliziert („uncomplicated“) ist ufw nicht – man muss schon wissen, was man macht. Im Vergleich zu iptables ist es aber doch deutlich einfacher zu bedienen und kommt der Regelerstellung auf gängigen Heimnetzerwerkroutern (abgesehen vom command-line syntax) relativ nahe.

Eigenes PPA-Repository auf Launchpad einrichten

Ein Launchpad-Repository (PPA – personal package archive) mit 1 GB freiem Speicherplatz hilft den eigenen Webserver zu entlasten. Der ersten Schritt zum eigenen Repository ist die Anmeldung bei Launchpad.

Erzeugen eines OpenPGP-Schlüssels

Um ein Repository zu bekommen, benötigt man außerdem einen OpenPGP Schlüssel. Diesen habe ich mit dem Befehl

gpg --gen-key

erzeugt. Dabei habe ich für Art, Gültigkeit und Schlüssellänge stets die vorgegebenen Standardwerte verwendet. Bei den persönlichen Angaben bitte keinen Kommentar eingeben. Zum Schluss erhält man auch eine Zeile mit der Ausgabe

pub   1024D/8E7FE678 2009-01-21

Die öffentliche Schlüssel-ID beträgt hier also 8E7FE678. Diese Ausgabe erhält man im Nachhinein übrigens mit einem

gpg --list-keys

für alle erzeugten Schlüssel bzw. für eine spezielle E-Mail-Addresse mit

gpg --list-keys your@mailaddress.com

Damit die öffentliche Schlüssel-ID allen Programmen zur Verfügung steht, setzen wir die entsprechende Umgebungsvariable durch Ergänzung der .bashrc um folgende Zeile (Schlüssel-ID anpassen):

export GPGKEY=8E7FE678

Außerdem sollte man sicherstellen, dass die Angaben zu den Packages, die aus den zwei Umgebungsvariablen DEBFULLNAME und DEBEMAIL gelesen werden, vorhanden sind. Die Schreibweise muss exakt mit den gemachten Angaben zur Erzeugung des OpenPGP-Schlüssels übereinstimmen:

export DEBFULLNAME='Your Name'
export DEBEMAIL='your@mailaddress.org'

Gibt es Differenzen erhält man nämlich bei der Erstellung von Paketen folgende Fehlermeldung: „geheimer schlüssel ist nicht vorhanden“ bzw. „secret key not available“. Als nächstes Übertragen wir den öffentlichen Schlüssel auf einen öffentlichen Schlüsselserver

gpg --send-keys --keyserver keyserver.ubuntu.com 8E7FE678

Die Schlüssel-ID ist hier natürlich ebenfalls anzupassen.

Aktivieren des Launchpad-Repositories

Zum Aktivieren des Launchpad-Repositories meldet man sich mit seinem Login an und klickt auf seinen Namen (rechts oben), so dass man zum eigenen Profil komt. Anschließend wählt dann den Punkt Change Details. Im Menü wählt man OpenPGP Keys und gibt dort die Finger-Print des Schlüssels ein, den man über ein

gpg --fingerprint 8E7FE678

erhält (wiederum für eigene Schlüssel-ID anpassen). Nach dem Importieren erhält man eine E-Mail, deren Inhalt einen verschlüsselten Link enthält, den man zum Aktivieren aufrufen muss. Zum Entschlüsseln wird der entsprechende Inhalt (ab einschließlich —–BEGIN PGP MESSAGE—– bis —–END PGP MESSAGE—–) in der Datei temp.txt gespeichert, die man dann durch ein

gpg --decrypt temp.txt

in den Klartext verwandelt. Durch Aufrufen des enthaltenen Links bestätigt man den Schlüssel nochmals und kann dann unter seinem Profil das PPA aktivieren. Im nächsten Schritt muss man Ubuntero werden, d.h. den Ubuntu Verhaltenskodex akzeptieren. Ist man dies nicht, werden hochgeladene Pakete mit der Fehlermeldung „PPA uploads must be signed by an ‚ubuntero‘. “ verworfen. Um Ubuntero zu werden ruft man nach dem Einloggen die Seite Ubuntu Code of Conduct auf, geht auf den Punkt Sign it!, lädt den Kodex herunter und signiert ihn mit einem

gpg --clearsign UbuntuCodeofConduct-1.0.1.txt

Den Inhalt der dadurch erzeugten Datei UbuntuCodeofConduct-1.0.1.txt.asc fügt man nun in das entsprechende Feld ein, schickt das Formular ab – und schon ist man Ubuntero.

Pakete erstellen und ins Repository übernehmen

Eigene Pakete muss man fortan beim Erstellen signieren, falls sie in das PPA-Repository aufgenommen werden sollen. Falls man ein bereits im Ubuntu-Repository vorhandenes Paket angepasst hat, also die Datei names xyz.orig.tar.gz von Beginn an vorhanden ist, so erstellt man mit

debuild -S -sd

die entsprechenden Dateien – ansonsten mit

debuild -S -sa

Zum Hochladen installiert man dput mit

sudo apt-get install dput

und erzeugt die Datei ~/.dput.cf mit diesem Inhalt (bitte launchpad-id anpassen):

[my-ppa]
fqdn = ppa.launchpad.net
method = ftp
incoming = ~your-launchpad-id/ubuntu/
login = anonymous
allow_unsigned_uploads = 0

Das erzeugte Source-Paket wird schließlich durch ein

dput my-ppa P_V_source.changes

ins Repository übertragen. P steht dabei für den Paketnamen und V für die Versionsnummer. Die Datei P_V_source.changes sollte sich natürlich im entsprechenden Verzeichnis befinden. Anfangs habe ich mich gefragt, weshalb man zum Hochladen kein Passwort oder dergleichen benötigt, aber da die erzeugten Pakete signiert sind, ist das ja gar nicht notwendig.
Die hochgeladenen Quelltext-Pakete werden dann von Launchpad für die Platformen i386, AMD64 und LPIA kompiliert und  anschließend ins Repository gestellt. Das kann etwas dauern. Natürlich sollte man vorher selbst sicherstellen, dass das Kompilieren auf dem eigenen Rechner fehlerfrei abläuft. Während in der Vergangenheit die Packages auf dem Launchpad PPA nicht signiert wurden, soll dies zukünftig anders sein. Ich bin gespannt, wann meine Pakete signiert sind..

Kleine Tips zum Schluss

GPG-Agent nutzen

Der gpg-agent erlaubt eine etwas bequemere Anwendung von GPG, da bei mehrfacher Verwendung eines Schlüssels innerhalb einer bestimmten Zeitspanne nur beim ersten Mal nach dem Passwort gefragt wird. Installieren lässt sich der gpg-agent mit einem

sudo apt-get install gnupg-agent

Damit der gpg-agent bei jeder Sitzung gestartet wird, habe ich ihn unter System>Einstellungen>Sitzungen als Startprogramm mit dem Befehl

gpg-agent --daemon

hinzugefügt.

Schlüssel zurückziehen

Hat jemand Zugang zum privaten Schlüssel erhalten, so kann man den Schlüssel zurückziehen/als ungültig markieren (revoke). Die sehr gute revoke-Anleitung von Hackdiary hilft dabei. Lediglich den dort angegebenen MIT Server habe ich durch den Ubuntu Server ersetzt, an den ich meinen öffentlichen Schlüssel gesendet hatte. Das sollte eigentlich aber keinen Unterschied machen, da die Schlüsselserver die öffentlichen Schlüssel untereinander austauschen.