Guten Tag, Habr!
Ziel
In meiner Organisation nutzen wir einen Mailserver auf der Kerio Connect-Plattform. In verschiedenen StĂ€dten sind Mailserver installiert, die ihre Benutzer betreuen. Eine verteilte Struktur gab es ursprĂŒnglich nicht, da die DomĂ€nen auf dritter Ebene mit der Angabe der Stadt des Standorts unterschiedlich waren. Alles funktionierte einwandfrei und alle waren zufrieden. An einem schönen Tag stellte die GeschĂ€ftsfĂŒhrung die Aufgabe: einen gemeinsamen GeschĂ€ftskalender fĂŒr alle Standorte!
Hintergrund
Die ursprĂŒngliche Idee war, eine verteilte Mail-DomĂ€ne fĂŒr Kerio einzurichten und dass er die Synchronisation selbst ĂŒbernimmt. Gesagt, getan â die verteilte DomĂ€ne wurde erstellt, aber damit war es nicht getan. Der Server war bereit, Kalender, Ordner, Kontakte zwischen DomĂ€nen auf demselben Server zu synchronisieren, aber war ĂŒberhaupt nicht bereit, Daten zwischen mehreren Servern zu synchronisieren.
Mit einem solchen Betrug hatte ich natĂŒrlich nicht gerechnet und konnte lange nicht glauben, dass die benötigte FunktionalitĂ€t fehlte. SpĂ€ter fand ich dokumentarische Beweise fĂŒr diese Tatsache, was mich sehr verwirrte und enttĂ€uschte.
Die Aufgabe entwickelte sich schnell zu einem Problem.
Welche Optionen gab es?
- Zwei Kunden auf verschiedenen Servern zu erstellen, die mit einer bestimmten externen Software notwendige Daten austauschten. Ich musste diese externe Software finden, die diese FunktionalitĂ€t umsetzt â ich mag solche Umwege nicht, aber es schien die einzige schnelle Lösung zu sein.
- Ein eigenes Skript zur Daten-Synchronisation zwischen den Servern zu schreiben. Das Problem ist, dass Kerio jedes Objekt als separate Datei speichert, sodass ein Skript fĂŒr die Dateibearbeitung entwickelt werden musste. Aufgrund der Vielzahl an Quellen erschien die Aufgabe jedoch komplex, zumal zahlreiche Datenvalidierungen erforderlich waren; andernfalls könnte jemand gleichzeitig eine Aufgabe erstellen und so weiter.
Um es vorweg zu nehmen: Kerio speichert zwar Objekte als separate Dateien, ist jedoch nicht so dumm, bei jedem Zugriff auf ein Objekt nachzufragen â wie steht es um die Dateisysteme.
Nachdem ich viel Zeit mit Ăberlegungen verbracht und zahlreiche PlĂ€ne zur "Eroberung feindlichen Territoriums" skizziert hatte, traf ich um 6 Uhr zwei richtige Entscheidungen:
- Die erste Lösung besteht darin, selbst zu machen und nichts anderes zu suchen.
- Die zweite Lösung ist, schlafen zu gehen.
Am Morgen bin ich mit einem einzigen und klaren Gedanken aufgewacht, der sich auf ein paar Buchstaben reduzierte â DFS.
Lösung
Die Lösung sah folgendermaĂen aus:
- Alle Server, die an der Synchronisierung teilnehmen, mĂŒssen auf Windows OS laufen. (Ein Teil war auf Linux. Eine Migration der E-Mail-Daten auf ein anderes OS war erforderlich.)
- Die Struktur der Verzeichnisse, die an der Synchronisierung teilnehmen sollen, muss identisch sein.
- Alle Mail-Server unter einer Domain mit einem einheitlichen DFS-Speicher festlegen.
- Die oben erwĂ€hnte verteilte Kerio-DomĂ€ne erstellen, da in meinem Fall eine Daten-Synchronisierung nicht nur zwischen Servern, sondern auch zwischen Domains erforderlich ist, wobei der zweite Server Kerio das selbst ĂŒbernehmen kann. (im Gegensatz zu dem ersten)
- Die zu synchronisierenden Verzeichnisse auf den DFS-Speicher leiten.
- Einen Trick ausdenken (denn ohne Trick geht es nicht).
Implementierung
Beispiel auf zwei Mail-Servern (es können auch mehr sein).
1. Kerio verteilte DomÀne.

Der Master nimmt nicht an der Synchronisierung teil, aber das ist keine zwingende Voraussetzung.
Ich werde nicht im Detail erklÀren, wie man eine verteilte Kerio-Domain einrichtet; es ist nicht kompliziert und kann in der offiziellen
Am Ende sollten Sie im Administrationskonsole folgendes Bild sehen:
![]()

Als NÀchstes interessierten mich die gemeinsamen Ordner. Auf dem Master-Server können Sie folgende Optionen angeben:
![]()

Besonders fĂŒr jede Domain â der Server wird keine öffentlichen Ordner zwischen den Domains synchronisieren
Gemeinsame fĂŒr alle Domains â alle Server werden auf vorhandene gemeinsame Ordner in jeder Domain verzichten und neue gemeinsame Ordner fĂŒr alle Domains auf jedem der Mail-Server erstellen.
Achtung! Diese Option Ă€ndert zwar die Konfigurationseinstellungen auf allen Servern, fĂŒhrt jedoch die Synchronisation separat fĂŒr jeden Server durch (d.h. ohne einen gemeinsamen Raum)
Der Administrator bleibt in der Lage, den Zugriff zwischen den Benutzern zu verteilen.
In meinem Fall â ich benötige die vollstĂ€ndige Synchronisation (in Ihrem Fall kann die Lösung anders sein). Auf jedem Server mĂŒssen identische SĂ€tze von Domains erstellt werden, die synchronisiert werden sollen.
2. Kerio-Datenverzeichnisse
Jetzt mĂŒssen identische gemeinsame Verzeichnisse erstellt werden, die auf jedem der Server synchronisiert werden mĂŒssen. Ordner, Kalender, Kontakte.
Tipp â erstellen Sie die Verzeichnisse in englischer Sprache, da die Benennung in lateinischen Buchstaben sonst in einer unverstĂ€ndlichen Kodierung erfolgt, was mindestens unpraktisch ist.
Jetzt mĂŒssen die physischen Pfade der Postordner auf jedem Server gefunden werden.
Gemeinsame fĂŒr alle Domains ~DataMailmail#publicSynchronisiertes Verzeichnis#msgs
Besonders fĂŒr jede Domain ~DataMailmail**Domain**#publicSynchronisiertes Verzeichnis#msgs
Bitte beachten Sie, dass wir nicht das gesamte Verzeichnis synchronisieren, sondern nur den Container mit den Daten. #msgs â hier werden die Objekte selbst gespeichert; alle anderen Daten fĂŒr jeden der Server mĂŒssen separat sein.
3. DFS
Ich werde nicht detailliert erklĂ€ren, wie man DFS einrichtet, da es genĂŒgend Informationen zu diesem Thema gibt.
DFS ist ein Dienst in Windows Server, der die Möglichkeit bietet, gemeinsame Ordner, die sich auf verschiedenen Servern befinden, zu verbinden.
Vor der Konfiguration von DFS mĂŒssen alle Mailserver, die an der Datensynchronisierung teilnehmen, gestoppt werden.
Nach der Einrichtung sollten Sie fĂŒr jeden synchronisierten Ordner folgendes Bild erhalten.

Es ist selbstverstÀndlich nicht notwendig, replizierbare Ordner zu veröffentlichen.

Nach der Replikation (es gibt da wenig zu replizieren â die Ordner sind leer) können die Mailserver gestartet werden.
AnschlieĂend können Sie einen der Mailserver mit Daten fĂŒllen und ĂŒberprĂŒfen, ob die Daten korrekt repliziert werden.
4. Notlösung
Beschreibung des Gedankens
Wie Sie feststellen können, nachdem die Daten mit DFS zu synchronisieren begonnen haben: Wenn Sie etwas auf dem ersten Server erstellt haben, erscheint auf dem zweiten Server entweder nichts oder nur manchmal etwas.
Es gibt keinen Grund zur Verzweiflung; es wird sicherlich irgendwann dort erscheinen, aber es ist besser, wenn es frĂŒher als spĂ€ter geschieht. Denn 'spĂ€ter' bedeutet in diesem Fall 6 bis 12 Stunden.
Das Problem ist, dass sobald Sie etwas auf dem ersten Server erstellt haben, die Datei auf dem zweiten und den nachfolgenden Servern sofort dank des DFS-Systems erscheinen wird. Allerdings, wenn das betreffende E-Mail-Verzeichnis bereits von jemandem gelesen wurde und erneut angefordert wird, wird der Server den Ordner #msgs nicht erneut lesen, sondern die Daten aus seinem eigenen Index ausgeben, der möglicherweise schon lange nicht mehr mit der RealitĂ€t ĂŒbereinstimmt.
Kerio verfĂŒgt ĂŒber einen Mechanismus zur Neuindizierung, der jedoch erst nach etwa sechs Stunden funktioniert. In dieser Zeit kann die Relevanz der Aufgabe im Kalender etwas verloren gehen.
Um die Synchronisation sofort zu ĂŒberprĂŒfen, kann die Datei im entsprechenden synchronisierten Verzeichnis index.fld gelöscht werden. Nach erneutem Zugriff auf den Ordner auf dem Mailserver und bei Fehlen dieser Datei wird Kerio das Verzeichnis erneut lesen und die Daten erscheinen. Das scheint die Lösung zu sein: Löschen Sie die Datei, wenn sich die Daten Ă€ndern. Aber das funktioniert nicht jedes Mal, sondern nur beim ersten Mal. Danach verliert Kerio merkwĂŒrdigerweise das Interesse an index.fld.
Es beginnt damit, dass unverstĂ€ndliche Nachrichten fĂŒr den Benutzer angezeigt werden â bezĂŒglich eines bestimmten Index und dass dieser bereits etwas tut.
Es gibt noch eine andere Möglichkeit, etwas zu erstellen â zum Zeitpunkt der Erstellung eines neuen Objekts könnte der Server plötzlich feststellen, dass der Dateiname, den er zuweisen wollte, bereits vergeben ist. Aber das ist ein Schneeballsystem und eine Sackgasse.
Was sollen wir tun?
Wenn wir noch einmal auf das uns bereits bekannte Bild schauen.

Aber in einer anderen Dimension können wir eine sehr interessante und nĂŒtzliche SchaltflĂ€che bemerken â Ordner neu indizieren
Und das stimmt tatsĂ€chlich. Wenn man diese SchaltflĂ€che auf einem Mailserver drĂŒckt, der nicht weiĂ, dass sich bereits etwas in den synchronisierten #msgs geĂ€ndert hat, erhalten wir ein stabiles, schnelles Ergebnis. Alles Verborgene wird offenbar.
Im Protokoll kann man sehen, wie viel Zeit dieser Prozess in Anspruch nimmt; in meinem Fall mit mehreren Tausend (15.000) EintrÀgen dauert es etwa 3-4 Minuten.
Wir mĂŒssen nur noch herausfinden, wie wir tatsĂ€chlich auf diese SchaltflĂ€che klicken können, wenn wir es brauchen.
Es stellt sich heraus, dass Kerio eine eigene API
Funktion hat, die unsere Aufgabe erfĂŒllt, die so aussieht â
session = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)
Basierend auf den obigen AusfĂŒhrungen mĂŒssen wir ein Skript erstellen, das den Zustand der relevanten Ordner ĂŒberwacht und im Falle von Ănderungen die gewĂŒnschte Funktion ausfĂŒhrt.
Ich möchte erwĂ€hnen, dass ich mehrere verschiedene Versionen von Skripten geschrieben habe, die unterschiedliche ĂberprĂŒfungen durchfĂŒhren. Ich habe mich fĂŒr die entschieden, die alle Ausgaben basierend auf der Anzahl der Dateien generiert.
Implementierung des Skripts
Beispiel fĂŒr ein CMD-Skript und Beschreibung
Re-index.bat
@echo off
set dir=%~dp0
%dir:~0,2%
CD "%~dp0"
md "%CD%LOG"
md "%CD%Setup"
ECHO -Start- >> "%CD%LOG%Computername%.log"
ECHO Start -> %Computername% %Date% %Time% >> "%CD%LOG%Computername%.log"
SetLocal EnableDelayedExpansion
for /f "UseBackQ Delims=" %%A IN ("%CD%Setup%Computername%.List") do (
set /a c+=1
set "m!c!=%%A"
)
set d=%c%
Echo Folder = %c%
ECHO Folder = %c% >> "%CD%LOG%Computername%.log"
ECHO.
ECHO. >> "%CD%LOG%Computername%.log"
:start
cls
if %c% LSS 1 exit
set /a id=1
set R=0
:Find
REM PF-Start
if "%id%" gtr "%c%" if %R% == 1 Goto Reindex
if "%id%" gtr "%c%" timeout 60 && Goto start
For /F "tokens=1-3" %%a IN ('Dir "!m%id%!#msgs" /-C/S/A:-D') Do Set 2DirSize!id!=!DS!& Set DS=%%c
if "2DirSize!id!" == "" set 1DirSize!id!=!2DirSize%id%!
echo %id%
ECHO !m%id%!
echo Count [ !1DirSize%id%! -- !2DirSize%id%! ]
if "!1DirSize%id%!" == "!2DirSize%id%!" ECHO Synk
REM DEL index.fld
if "!1DirSize%id%!" NEQ "!2DirSize%id%!" del /f /q !m%id%!index.fld && del /f /q !m%id%!indexlog.fld && del /f /q !m%id%!search.fld && set R=1 && ECHO RE-index Count && ECHO RE-index Count %Date% %Time% - Delete !m%id%! >> "%CD%LOG%Computername%.log"
set 1DirSize!id!=!2DirSize%id%!
ECHO.
ECHO.
set /a id+=1
goto Find
:Reindex
ECHO. >> "%CD%LOG%Computername%.log"
ECHO --- RE-INDEX - Start - %Date% %Time% --- >> "%CD%LOG%Computername%.log"
ECHO. >> ----------------------------------- >> "%CD%LOG%Computername%.log"
call PublicFolders.py
timeout 60
goto start
exit
Eine Kopie des Skripts wird auf jedem Mailserver ausgefĂŒhrt (kann als Dienst betrieben werden, Administratorrechte sind nicht erforderlich)
Das Skript liest die Datei Setup%Computername%.List
Wo %Computername% â der Name des aktuellen Servers (Das Verzeichnis kann eine Liste aller Server enthalten.)
Die Datei %Computername%.List enthĂ€lt die vollstĂ€ndigen Pfade der synchronisierten Verzeichnisse, jeder Pfad steht in einer neuen Zeile und es dĂŒrfen keine leeren Zeilen vorhanden sein.
Nach dem ersten Start fĂŒhrt das Skript eine Indizierungsprozedur aus, unabhĂ€ngig davon, ob sie notwendig ist oder nicht. Das Skript erstellt auĂerdem ein Index mit der Anzahl der Dateien in jedem der synchronisierten Verzeichnisse.
Die Aufgabe des Skripts besteht darin, alle Dateien im angegebenen Verzeichnis zu zÀhlen.
Nach dem ZĂ€hlen jedes Verzeichnisses, wenn in mindestens einem Verzeichnis die aktuelle Anzahl der Dateien nicht mit der vorherigen ĂŒbereinstimmt, löscht das Skript Dateien aus dem Stammverzeichnis des synchronisierten Mailverzeichnisses: index.fld, indexlog.fld, search.fld und startet den Indizierungsprozess â aller gemeinsamen Mailordner.
Im Verzeichnis LOG wird die Information ĂŒber die AusfĂŒhrung der Aufgaben gespeichert.
Indizierungsprozess
Der Indizierungsprozess besteht darin, die API-Funktion von Kerio auszufĂŒhren.
Session = callMethod("Domains.checkPublicFoldersIntegrity", {}, token)
Ein Beispiel fĂŒr die AusfĂŒhrung ist auf â python
PublicFolders.py
import json
import urllib.request
import http.cookiejar
""" Cookie-Speicherung ist erforderlich fĂŒr die Sitzungsverwaltung """
jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
urllib.request.install_opener(opener)
""" Hostname oder IP-Adresse Ihrer Kerio Control-Instanz mit Protokoll, Port und Anmeldedaten """
server = "http://127.0.0.1:4040"
username = "user"
password = "password"
def callMethod(method, params, token = None):
"""
Ruft die angegebene Methode mit den gegebenen Parametern remote auf.
:param: method string mit dem vollqualifizierten Methodennamen
:param: params dict mit den Parametern der remote aufgerufenen Methode
:param: token CSRF-Token wird immer benötigt, auĂer bei der Anmeldemethode. Verwenden Sie die Methode "Session.login", um diesen Token zu erhalten.
"""
data = {"method": method ,"id":1, "jsonrpc":"2.0", "params": params}
req = urllib.request.Request(url = server + '/admin/api/jsonrpc/')
req.add_header('Content-Type', 'application/json')
if (token is not None):
req.add_header('X-Token', token)
httpResponse = urllib.request.urlopen(req, json.dumps(data).encode())
if (httpResponse.status == 200):
body = httpResponse.read().decode()
return json.loads(body)
session = callMethod("Session.login", {"userName":username, "password":password, "application":{"vendor":"Kerio", "name":"Control Api-Local", "version":"Python"}})
token = session["result"]["token"]
print (session)
session = callMethod("Domains.checkPublicFoldersIntegrity",{"domainId": "test2.local"}, token)
print (session)
callMethod("Session.logout",{}, token)
Kann so bleiben, allerdings sollte Python dem Kerio-Zertifikat vertrauen, wenn Sie HTTPS benötigen.
Im Datei muss auch ein Benutzer mit Berechtigungen zur AusfĂŒhrung dieser Funktion angegeben werden (Admin â gemeinsame PostfĂ€cher) des Mailservers.
Ich hoffe, mein Artikel wird den Administratoren von Kerio Connect hilfreich sein.
Quelle: habr.com
