Dovecot, Nachrichten auf dem Server mit SIEVE filtern
Zur Filtern von E-Mails auf IMAP-Servern wurde die Programmiersprache SIEVE konzipiert - die genaue Spezifikationen erfolgten hierzu im RFC 5228 und vielen Erweiterungen/Ergänzungen in weiteren RFCs. Das Hauptaugenmerk von SIEVE liegt auf Einfachheit, Erweiterbarkeit, sowie auf Unabhängigkeit von der verwendeten Zugriffsart und Architektur wie auch dem verwendeten Betriebssystem. Sieve wurde spezifiziert, um den Usern die Möglichkeit zu bieten, bereits serverseitig auf einfache Art und Weise eigene Regeln zur Filterung von E-Mails zu definieren. Sieve-Scripte werden bereits während der Zustellung der eMail am IMAP-Server ausgeführt.
Weitere Hintergrundinformationen finden man unter anderem in dem Wikipedia-Artikel zu SIEVE.
Die Unterstützung und Implementierung von SIEVE erfolgt über das Projekt managesieve von Stefan Bosch. Detaillierte Informationen zum Protokoll Managesieve sowie zum RFC 5228 und den zahlreichen Erweiterungen RFCs findet man auf der Projektseite von Stefan Bosch.
Installation
Am Einfachsten bedienen wir uns zur Installation des Paketes dovecot-pigeonhole eines aktuell gepflegten Dovecot-Repositories, wie z.B. dem Repository repo.nausch.org. Das dort enthaltene Paket wurde für den aktuellen Dovecot-release 2.2.131) gebaut.
Die Installation des Paketes geht Dank des Repositories repo.nausch.org leicht von statten, benötigen wir hierzu lediglich den Befehl yum.
# yum install dovecot-pigeonhole -y
Was uns das Paket dovecot alles mit ins System bringt, zeigt uns der Befehl rpm mit der Option -qil.
# rpm -qil dovecot-pigeonhole
Name : dovecot-pigeonhole Epoch : 1 Version : 2.2.13 Release : 2.el7.centos Architecture: x86_64 Install Date: Mon 04 Aug 2014 11:01:38 PM CEST Group : System Environment/Daemons Size : 1133200 License : MIT and LGPLv2 Signature : RSA/SHA1, Fri 01 Aug 2014 08:55:53 PM CEST, Key ID 60ecfb9e8195aea0 Source RPM : dovecot-2.2.13-2.el7.centos.src.rpm Build Date : Fri 01 Aug 2014 08:52:54 PM CEST Build Host : vml000200.dmz.nausch.org Relocations : (not relocatable) Packager : Django <django@nausch.org> Vendor : django URL : http://www.dovecot.org/ Summary : Sieve and managesieve plug-in for dovecot Description : This package provides sieve and managesieve plug-in for dovecot LDA. /etc/dovecot/conf.d/20-managesieve.conf /etc/dovecot/conf.d/90-sieve-extprograms.conf /etc/dovecot/conf.d/90-sieve.conf /usr/bin/sieve-dump /usr/bin/sieve-filter /usr/bin/sieve-test /usr/bin/sievec /usr/lib64/dovecot/lib90_sieve_plugin.so /usr/lib64/dovecot/settings/libmanagesieve_login_settings.so /usr/lib64/dovecot/settings/libmanagesieve_settings.so /usr/lib64/dovecot/sieve /usr/lib64/dovecot/sieve/lib90_sieve_extprograms_plugin.so /usr/libexec/dovecot/managesieve /usr/libexec/dovecot/managesieve-login /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2 /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/AUTHORS /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/COPYING /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/COPYING.LGPL /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/ChangeLog /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/INSTALL /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/NEWS /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/README /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/example-config /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/example-config/conf.d /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/example-config/conf.d/20-managesieve.conf /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/example-config/conf.d/90-sieve-extprograms.conf /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/example-config/conf.d/90-sieve.conf /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/sieve /usr/share/doc/dovecot-2.2-pigeonhole-0.4.2/sieve/script-location-dict.txt /usr/share/man/man1/sieve-dump.1.gz /usr/share/man/man1/sieve-filter.1.gz /usr/share/man/man1/sieve-test.1.gz /usr/share/man/man1/sievec.1.gz /usr/share/man/man1/sieved.1.gz /usr/share/man/man7/pigeonhole.7.gz
Konfiguration
Die Konfiguration vom Managesieve-Plugin dovecot-pigeonhole erfolgt über die drei Konfigurationsdateien 20-managesieve.conf, 90-sieve-extprograms.conf und 90-sieve.conf im Verzeichnis /etc/dovecot/conf.d/
20-managesieve.conf
Auf welchem Port und welcher Adresse unser Managesieve-Logindaemon horchen soll wird in der datei /etc/dovecot/conf.d/20-managesieve.conf festgelegt. Da wir ausschließlich den aktuellen Port 4190 beschränken, geben wir den Port 2000 explizit nicht an.
# vim /etc/dovecot/conf.d/20-managesieve.conf
- /etc/dovecot/conf.d/20-managesieve.conf
## ## ManageSieve specific settings ## # Uncomment to enable managesieve protocol: #protocols = $protocols sieve # Service definitions # Django : 2014-08-04 # default: unset service managesieve-login { inet_listener sieve { address = 10.0.0.70 port = 4190 } #inet_listener sieve_deprecated { # port = 2000 #} # Number of connections to handle before starting a new process. Typically # the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0 # is faster. <doc/wiki/LoginProcess.txt> #service_count = 1 # Number of processes to always keep waiting for more connections. #process_min_avail = 0 # If you set service_count=0, you probably need to grow this. #vsz_limit = 64M } #service managesieve { # Max. number of ManageSieve processes (connections) #process_limit = 1024 #} # Service configuration protocol sieve { # Maximum ManageSieve command line length in bytes. ManageSieve usually does # not involve overly long command lines, so this setting will not normally # need adjustment #managesieve_max_line_length = 65536 # Maximum number of ManageSieve connections allowed for a user from each IP # address. # NOTE: The username is compared case-sensitively. #mail_max_userip_connections = 10 # Space separated list of plugins to load (none known to be useful so far). # Do NOT try to load IMAP plugins here. #mail_plugins = # MANAGESIEVE logout format string: # %i - total number of bytes read from client # %o - total number of bytes sent to client #managesieve_logout_format = bytes=%i/%o # To fool ManageSieve clients that are focused on CMU's timesieved you can # specify the IMPLEMENTATION capability that Dovecot reports to clients. # For example: 'Cyrus timsieved v2.2.13' #managesieve_implementation_string = Dovecot Pigeonhole # Explicitly specify the SIEVE and NOTIFY capability reported by the server # before login. If left unassigned these will be reported dynamically # according to what the Sieve interpreter supports by default (after login # this may differ depending on the user). #managesieve_sieve_capability = #managesieve_notify_capability = # The maximum number of compile errors that are returned to the client upon # script upload or script verification. #managesieve_max_compile_errors = 5 # Refer to 90-sieve.conf for script quota configuration and configuration of # Sieve execution limits. }
90-sieve-extprograms.conf
Mit Hilfe der Datei /etc/dovecot/conf.d/90-sieve-extprograms.conf könnte man noch externe Programme einbinden. Da wir aber darauf verzichten, brauchen wir keinerlei Änderungen vornehmen.
# cat /etc/dovecot/conf.d/90-sieve-extprograms.conf
- /etc/dovecot/conf.d/90-sieve-extprograms.conf
# Sieve Extprograms plugin configuration # Don't forget to add the sieve_extprograms plugin to the sieve_plugins setting. # Also enable the extensions you need (one or more of vnd.dovecot.pipe, # vnd.dovecot.filter and vnd.dovecot.execute) by adding these to the # sieve_extensions or sieve_global_extensions settings. Restricting these # extensions to a global context using sieve_global_extensions is recommended. plugin { # The directory where the program sockets are located for the # vnd.dovecot.pipe, vnd.dovecot.filter and vnd.dovecot.execute extension # respectively. The name of each unix socket contained in that directory # directly maps to a program-name referenced from the Sieve script. #sieve_pipe_socket_dir = sieve-pipe #sieve_filter_socket_dir = sieve-filter #sieve_execute_socket_dir = sieve-execute # The directory where the scripts are located for direct execution by the # vnd.dovecot.pipe, vnd.dovecot.filter and vnd.dovecot.execute extension # respectively. The name of each script contained in that directory # directly maps to a program-name referenced from the Sieve script. #sieve_pipe_bin_dir = /usr/lib/dovecot/sieve-pipe #sieve_filter_bin_dir = /usr/lib/dovecot/sieve-filter #sieve_execute_bin_dir = /usr/lib/dovecot/sieve-execute } # An example program service called 'do-something' to pipe messages to #service do-something { # Define the executed script as parameter to the sieve service #executable = script /usr/lib/dovecot/sieve-pipe/do-something.sh # Use some unprivileged user for executing the program #user = dovenull # The unix socket located in the sieve_pipe_socket_dir (as defined in the # plugin {} section above) #unix_listener sieve-pipe/do-something { # LDA/LMTP must have access # user = vmail # mode = 0600 #} #}
90-sieve.conf
Die Einstellungen des Sieve-Plugins erfolgen mit Hilfe der Datei /etc/dovecot/conf.d/90-sieve.conf. Die Standard-Werte dort braucht man in aller Regel nicht abändern, somit begnügen wir uns mit der Ansicht der Datei.
# less /etc/dovecot/conf.d/90-sieve.conf
- /etc/dovecot/conf.d/90-sieve.conf
## ## Settings for the Sieve interpreter ## # Do not forget to enable the Sieve plugin in 15-lda.conf and 20-lmtp.conf # by adding it to the respective mail_plugins= settings. plugin { # The path to the user's main active script. If ManageSieve is used, this the # location of the symbolic link controlled by ManageSieve. sieve = ~/.dovecot.sieve # The default Sieve script when the user has none. This is a path to a global # sieve script file, which gets executed ONLY if user's private Sieve script # doesn't exist. Be sure to pre-compile this script manually using the sievec # command line tool. # --> See sieve_before fore executing scripts before the user's personal # script. #sieve_default = /var/lib/dovecot/sieve/default.sieve # Directory for :personal include scripts for the include extension. This # is also where the ManageSieve service stores the user's scripts. sieve_dir = ~/sieve # Directory for :global include scripts for the include extension. #sieve_global_dir = # Path to a script file or a directory containing script files that need to be # executed before the user's script. If the path points to a directory, all # the Sieve scripts contained therein (with the proper .sieve extension) are # executed. The order of execution within a directory is determined by the # file names, using a normal 8bit per-character comparison. Multiple script # file or directory paths can be specified by appending an increasing number. #sieve_before = #sieve_before2 = #sieve_before3 = (etc...) # Identical to sieve_before, only the specified scripts are executed after the # user's script (only when keep is still in effect!). Multiple script file or # directory paths can be specified by appending an increasing number. #sieve_after = #sieve_after2 = #sieve_after2 = (etc...) # Which Sieve language extensions are available to users. By default, all # supported extensions are available, except for deprecated extensions or # those that are still under development. Some system administrators may want # to disable certain Sieve extensions or enable those that are not available # by default. This setting can use '+' and '-' to specify differences relative # to the default. For example `sieve_extensions = +imapflags' will enable the # deprecated imapflags extension in addition to all extensions were already # enabled by default. #sieve_extensions = +notify +imapflags # Which Sieve language extensions are ONLY available in global scripts. This # can be used to restrict the use of certain Sieve extensions to administrator # control, for instance when these extensions can cause security concerns. # This setting has higher precedence than the `sieve_extensions' setting # (above), meaning that the extensions enabled with this setting are never # available to the user's personal script no matter what is specified for the # `sieve_extensions' setting. The syntax of this setting is similar to the # `sieve_extensions' setting, with the difference that extensions are # enabled or disabled for exclusive use in global scripts. Currently, no # extensions are marked as such by default. #sieve_global_extensions = # The Pigeonhole Sieve interpreter can have plugins of its own. Using this # setting, the used plugins can be specified. Check the Dovecot wiki # (wiki2.dovecot.org) or the pigeonhole website # (http://pigeonhole.dovecot.org) for available plugins. # The sieve_extprograms plugin is included in this release. #sieve_plugins = # The separator that is expected between the :user and :detail # address parts introduced by the subaddress extension. This may # also be a sequence of characters (e.g. '--'). The current # implementation looks for the separator from the left of the # localpart and uses the first one encountered. The :user part is # left of the separator and the :detail part is right. This setting # is also used by Dovecot's LMTP service. #recipient_delimiter = + # The maximum size of a Sieve script. The compiler will refuse to compile any # script larger than this limit. If set to 0, no limit on the script size is # enforced. #sieve_max_script_size = 1M # The maximum number of actions that can be performed during a single script # execution. If set to 0, no limit on the total number of actions is enforced. #sieve_max_actions = 32 # The maximum number of redirect actions that can be performed during a single # script execution. If set to 0, no redirect actions are allowed. #sieve_max_redirects = 4 # The maximum number of personal Sieve scripts a single user can have. If set # to 0, no limit on the number of scripts is enforced. # (Currently only relevant for ManageSieve) #sieve_quota_max_scripts = 0 # The maximum amount of disk storage a single user's scripts may occupy. If # set to 0, no limit on the used amount of disk storage is enforced. # (Currently only relevant for ManageSieve) #sieve_quota_max_storage = 0 }
dovecot.conf
Zu guter letzt fügen wir noch das Protokoll oder exakter formuliert die Script-Sprache sieve zu den Protokollen hinzu, die unser Dovecot-Server zur Verfügung stellen soll. Per Default bietet unser Dovecot-Server bisher folgende Protokolle an:
# doveconf protocols
protocols = imap pop3 lmtp
Die Erweiterung um sieve erfolgt in der Konfigurationsdatei /etc/dovecot/dovecot.conf.
# vim /etc/dovecot/dovecot.conf
- /etc/dovecot/dovecot.conf
## Dovecot configuration file # If you're in a hurry, see http://wiki2.dovecot.org/QuickConfiguration # "doveconf -n" command gives a clean output of the changed settings. Use it # instead of copy&pasting files when posting to the Dovecot mailing list. # '#' character and everything after it is treated as comments. Extra spaces # and tabs are ignored. If you want to use either of these explicitly, put the # value inside quotes, eg.: key = "# char and trailing whitespace " # Most (but not all) settings can be overridden by different protocols and/or # source/destination IPs by placing the settings inside sections, for example: # protocol imap { }, local 127.0.0.1 { }, remote 10.0.0.0/8 { } # Default values are shown for each setting, it's not required to uncomment # those. These are exceptions to this though: No sections (e.g. namespace {}) # or plugin settings are added by default, they're listed only as examples. # Paths are also just examples with the real defaults being based on configure # options. The paths listed here are for configure --prefix=/usr # --sysconfdir=/etc --localstatedir=/var # Protocols we want to be serving. # Django : 2014-08-04 # Erweiterung um die Scriptsprache/Protokoll sieve # default: #protocols = imap pop3 lmtp protocols = imap pop3 lmtp sieve # A comma separated list of IPs or hosts where to listen in for connections. # "*" listens in all IPv4 interfaces, "::" listens in all IPv6 interfaces. # If you want to specify non-default ports or anything more complex, # edit conf.d/master.conf. # Django : 2014-08-04 # IPv6-Adressen deaktivieren, Server lauscht nur auf einem Netzwerkinterface # bzw. einer IPv4-Addresse # default: #listen = *, :: # listen = 10.0.0.70 # Base directory where to store runtime data. #base_dir = /var/run/dovecot/ # Name of this instance. In multi-instance setup doveadm and other commands # can use -i <instance_name> to select which instance is used (an alternative # to -c <config_path>). The instance name is also added to Dovecot processes # in ps output. #instance_name = dovecot # Greeting message for clients. #login_greeting = Dovecot ready. # Space separated list of trusted network ranges. Connections from these # IPs are allowed to override their IP addresses and ports (for logging and # for authentication checks). disable_plaintext_auth is also ignored for # these networks. Typically you'd specify your IMAP proxy servers here. #login_trusted_networks = # Space separated list of login access check sockets (e.g. tcpwrap) #login_access_sockets = # With proxy_maybe=yes if proxy destination matches any of these IPs, don't do # proxying. This isn't necessary normally, but may be useful if the destination # IP is e.g. a load balancer's IP. #auth_proxy_self = # Show more verbose process titles (in ps). Currently shows user name and # IP address. Useful for seeing who are actually using the IMAP processes # (eg. shared mailboxes or if same uid is used for multiple accounts). # Django : 2014-07-21 # In der Prozessliste bei den POP3/IMAP-Prozessen zusätzlich den Usernamen, # die Client-IP-Adresse und den ausgeführten IMAP-Befehl anzeigen. # default: #verbose_proctitle = no verbose_proctitle = yes # Should all processes be killed when Dovecot master process shuts down. # Setting this to "no" means that Dovecot can be upgraded without # forcing existing client connections to close (although that could also be # a problem if the upgrade is e.g. because of a security fix). #shutdown_clients = yes # If non-zero, run mail commands via this many connections to doveadm server, # instead of running them directly in the same process. #doveadm_worker_count = 0 # UNIX socket or host:port used for connecting to doveadm server #doveadm_socket_path = doveadm-server # Space separated list of environment variables that are preserved on Dovecot # startup and passed down to all of its child processes. You can also give # key=value pairs to always set specific settings. #import_environment = TZ ## ## Dictionary server settings ## # Dictionary can be used to store key=value lists. This is used by several # plugins. The dictionary can be accessed either directly or though a # dictionary server. The following dict block maps dictionary names to URIs # when the server is used. These can then be referenced using URIs in format # "proxy::<name>". dict { #quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext #expire = sqlite:/etc/dovecot/dovecot-dict-sql.conf.ext } # Most of the actual configuration gets included below. The filenames are # first sorted by their ASCII value and parsed in that order. The 00-prefixes # in filenames are intended to make it easier to understand the ordering. !include conf.d/*.conf # A config file can also tried to be included without giving an error if # it's not found: !include_try local.conf
20-lmtp.conf
Da die definierten SIEVE-Regeln bei der Zustellung der Nachrichten ihre Arbeit verrichten, müssen wir bei den Konfigurationsparametern von LMTP das Plugin sieve mit aufnehmen.
# vim /etc/dovecot/conf.d/20-lmtp.conf
- /etc/dovecot/conf.d/20-lmtp.conf
## ## LMTP specific settings ## # Support proxying to other LMTP/SMTP servers by performing passdb lookups. #lmtp_proxy = no # When recipient address includes the detail (e.g. user+detail), try to save # the mail to the detail mailbox. See also recipient_delimiter and # lda_mailbox_autocreate settings. #lmtp_save_to_detail_mailbox = no # Verify quota before replying to RCPT TO. This adds a small overhead. #lmtp_rcpt_check_quota = no protocol lmtp { # Space separated list of plugins to load (default is global mail_plugins). # Django : 2014-08-04 # default: #mail_plugins = $mail_plugins mail_plugins = $mail_plugins sieve }
Horde-Framework's Ingo
Die notwendigen Konfigurationseinstellungen bei der Applikation ingo ist auf folgenden Seite ausführlich beschrieben.
Paketfilter / Firewall
Damit unsere Kunden mit Ihren Mailclients Verbindungen zum geöffneten Ports 4190 unseres Dovecot-Server aufbauen können, müssen wir für diese noch Änderungen am Paketfilter firewalld vornehmen.
# firewall-cmd --permanent --zone=public --add-port=4190/tcp
success
Anschließend können wir den Firewall-Daemon einmal durchstarten und anschließend überprüfen, ob die Regeln auch entsprechend unserer Definition, gezogen haben.
# firewall-cmd --reload
success
Abschließend prüfen wir noch, ob die Erweiterung unseres Paketfilter aktiv ist.
# iptables -nvL IN_public_allow
Chain IN_public_allow (1 references)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 10.0.0.80 10.0.0.70 tcp dpt:24 ctstate NEW
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 ctstate NEW
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:110 ctstate NEW
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:143 ctstate NEW
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:995 ctstate NEW
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:4190 ctstate NEW
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:993 ctstate NEW
Aktivierung
Zum Aktivieren unserer Änderungen starten wir den Daemon nun einmal durch.
# systemctl restart dovecot
Im Maillog wurde der Restart entsprechend dokumentiert.
# tail -n4 /var/log/maillog
Aug 4 23:41:47 vml000070 dovecot: anvil: Warning: Killed with signal 15 (by pid=1 uid=0 code=kill) Aug 4 23:41:47 vml000070 dovecot: log: Warning: Killed with signal 15 (by pid=1 uid=0 code=kill) Aug 4 23:41:47 vml000070 dovecot: master: Warning: Killed with signal 15 (by pid=1 uid=0 code=kill) Aug 4 23:41:47 vml000070 dovecot: master: Dovecot v2.2.13 starting up for imap, pop3, lmtp, sieve (core dumps disabled)
Fragen wir den Serverstatus ab, finden wir nun auch den Dienst sieve bei den Protokollen.
# systemctl status dovecot
dovecot.service - Dovecot IMAP/POP3 email server Loaded: loaded (/usr/lib/systemd/system/dovecot.service; disabled) Active: active (running) since Mon 2014-08-04 23:41:47 CEST; 2min 42s ago Process: 4156 ExecStartPre=/usr/libexec/dovecot/prestartscript (code=exited, status=0/SUCCESS) Main PID: 4161 (dovecot) CGroup: /system.slice/dovecot.service ├─4161 /usr/sbin/dovecot -F ├─4165 dovecot/anvil [0 connections] ├─4166 dovecot/log └─4168 dovecot/config Aug 04 23:41:47 vml000070.dmz.nausch.org systemd[1]: Started Dovecot IMAP/POP3 email server. Aug 04 23:41:47 vml000070.dmz.nausch.org dovecot[4161]: master: Dovecot v2.2.13 starting up for imap, pop3, lmtp, sieve (core dumps disabled)
Fragen wir mit netstat die geöffneten Ports ab, sehen wir auch dort, dass unser Dovecot-Server nun auch auf Port 4190 bei der IP-Adresse 10.0.0.70 lauscht.
# netstat -tulpen | grep dovecot
tcp 0 0 10.0.0.70:4190 0.0.0.0:* LISTEN 0 44593 4161/dovecot tcp 0 0 10.0.0.70:993 0.0.0.0:* LISTEN 0 44656 4161/dovecot tcp 0 0 10.0.0.70:995 0.0.0.0:* LISTEN 0 44619 4161/dovecot tcp 0 0 10.0.0.70:110 0.0.0.0:* LISTEN 0 44618 4161/dovecot tcp 0 0 10.0.0.70:143 0.0.0.0:* LISTEN 0 44655 4161/dovecot tcp 0 0 10.0.0.70:24 0.0.0.0:* LISTEN 0 44628 4161/dovecot
Test
Unser ersten Funktionstest werden wir nun mit SIEVE via LMTP durchführen. Bei diesem folgenden Test nutzen wir die Authentifikations-Methode PLAIN. Die Anmeldedaten müssen dabei zum einen Base64 codiert werden und das Format „\0<username>\0<password“ (mit \0 als ASCII NULL Zeichen).
AUTHENTICATE "PLAIN" "<BASE64 codierte Anmeldedaten>"
Zum Erstellen dieses Anmeldestrings nutzen wir einfach das script sieve-auth-command.pl von Stephan Bosch.
# vim /usr/local/bin/sieve-auth-command.pl
- /usr/local/bin/sieve-auth-command.pl
#!/usr/bin/perl # # sieve-auth-command.pl # --------------------- # # Generates ManageSieve AUTHENTICATE command for manually testing the protocol # using telnet or gnutls-cli (TLS) # # Usage: # sieve-auth-command.pl <username> <password> # # Prints the AUTHENTICATE "PLAIN" "<encoded>" command on standard out. # # -- # Stephan Bosch, stephan@rename-it.nl # use MIME::Base64; use strict; my $username = shift; my $password = shift; my $userpass = "\x00".$username."\x00".$password.""; my $encode=encode_base64($userpass); $encode =~ s/^\s+//; $encode =~ s/\s+$//; print "AUTHENTICATE \"PLAIN\" \"$encode\"\r\n";
Um das Script einfach ausführen zu können versehen wir nun noch die Datei-Rechte mit einem x.
# chmod +x /usr/local/bin/sieve-auth-command.pl
Für unseren User django@nausch.org mit dem Passwort Dj4n90_d3r_G33k! erstellen wir nun unseren Anmeldestring.
$ sieve-auth-command.pl django@nausch.org Dj4n90_d3r_G33k!
AUTHENTICATE "PLAIN" "AGRqYW5nb0BuYXVzY2gub3JnAERqNG45MF9kM3JfRzMzayE="
Diesen Anmeldestring verwenden wir nun bei unserem ersten Test. Bei diesem SIEVE-Test via telnet sind die Eingaben am testenden Client in der Farbe blau und die Rückmeldungen unseres Dovecot-Servers in der Farbe grün gekennzeichnet. Die Ausgaben des Befehls telnet sind in der Farbe schwarz eingefärbt.
Als erstes bauen wir eine Verbindung zu unserem Dovecot-Server zum ManageSieve-Port 4190 auf und melden uns mit unserem zuvor generierten Anmeldestring am Server an.
$ telnet 10.0.0.70 4190 Trying 10.0.0.70... Connected to 10.0.0.70. Escape character is '^]'. "IMPLEMENTATION" "Dovecot Pigeonhole" "SIEVE" "fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date ihave" "NOTIFY" "mailto" "SASL" "PLAIN LOGIN DIGEST-MD5 CRAM-MD5" "STARTTLS" "VERSION" "1.0" OK "Dovecot ready." AUTHENTICATE "PLAIN" "AGRqYW5nb0BuYXVzY2gub3JnAERqNG45MF9kM3JfRzMzayE=" OK "Logged in."
Als erste Aktion fragen wir ab, welche SIEVE-Scruipte auf dem Server vorhanden sind. Da bis dato noch keine Scripte hinterlegt wurden, sit die Antwort des Servers natürlich etwas spartanisch, nämlich leer.
LISTSCRIPTS OK "Listscripts completed."
Nun wollen wir unser erstes SIEVE Script anlegen. Mit Hilfe dieses Scriptes werden alle Nachrichten sofort gelöscht, sobald diese im Betreff das Wörtchen p0rn enthält und der Postfix-MTA die Nachricht via LMTP an unseren Backend-server Dovecot übergibt. Das entsprechende Script könnte nun wie folgt aussehen.
if header :comparator "i;ascii-casemap" :contains "Subject" "p0rn" { discard; stop; }
Das script hat insgesamt 96-Zeichen (gefolgt von einem abschließendem CR). Zusammen ergibt das also 97 Zeichen. Mit dem Befehl PUTSCRIPT laden wir nun dieses script zum Server hoch.
PUTSCRIPT "erste_sieve-regel_zum_testen" {97+} if header :comparator "i;ascii-casemap" :contains "Subject" "p0rn" { discard; stop; } OK "PUTSCRIPT completed."
Fragen wir nun erneut ab, welche Scripte auf dem Server vorliegen, sehen wir auch unser erstes Testscript erste_sieve-regel_zum_testen.
LISTSCRIPTS "erste_sieve-regel_zum_testen" OK "Listscripts completed."
Zum Scharfschalten des Scripts wird der Befehl SETACTIVE verwendet.
SETACTIVE "erste_sieve-regel_zum_testen" OK "Setactive completed."
Fragen wir nun erneut die Liste des SIEVE-Scripte ab, sehen wir ein ACTIVE hinter dem Scriptnamen erste_sieve-regel_zum_testen; d.h. dieses Script ist nunmehr aktiv.
LISTSCRIPTS "erste_sieve-regel_zum_testen" ACTIVE OK "Listscripts completed."
Wollen wir ein script Herunterladen verwenden wir den Befehl GETSCRIPT.
GETSCRIPT "erste_sieve-regel_zum_testen" {97} if header :comparator "i;ascii-casemap" :contains "Subject" "p0rn" { discard; stop; } OK "Getscript completed."
Zu guter Letzt melden wir uns nun von unserem Server mit dem Befehl LOGOUT wieder ab.
LOGOUT OK "Logout completed." Connection closed by foreign host.
Im Verzeischnis des Users django@nausch.org finden wir nun auch das Verzeichnis /srv/vmail/nausch.org/django/sieve in dem die SIEVE-Scripte abgelegt werden.
/srv/vmail/nausch.org/django/ ├── .dovecot.sieve -> sieve/erste_sieve-regel_zum_testen.sieve ├── Maildir/ │ ├── cur/ │ │ └── 1407189625.M304698P4532.vml000070.dmz.nausch.org,S=409,W=422:2, │ ├── dovecot.index.cache │ ├── dovecot.index.log │ ├── dovecot.mailbox.log │ ├── dovecot-uidlist │ ├── dovecot-uidvalidity │ ├── dovecot-uidvalidity.53dfa2ad │ ├── .Drafts/ │ │ ├── cur/ │ │ ├── dovecot.index.log │ │ ├── dovecot-uidlist │ │ ├── maildirfolder │ │ ├── new/ │ │ └── tmp/ │ ├── new/ │ ├── .Sent/ │ │ ├── cur/ │ │ ├── dovecot.index.log │ │ ├── dovecot-uidlist │ │ ├── maildirfolder │ │ ├── new/ │ │ └── tmp/ │ ├── subscriptions │ └── tmp/ └── sieve/ ├── erste_sieve-regel_zum_testen.sieve └── tmp/
Das aktive Script erkennen wir an dem symlink .dovecot.sieve im HOME-Verzeichnis des Users.
# ll /srv/vmail/nausch.org/django/.dovecot.sieve
lrwxrwxrwx 1 vmail vmail 40 Aug 5 13:01 /srv/vmail/nausch.org/django/.dovecot.sieve -> sieve/erste_sieve-regel_zum_testen.sieve
Im Maillog wurden unsere SIEVE-Script Aktivitäten mit Hilfe des Mail-Plugins ManageSieve dokumentiert.
Aug 5 12:58:29 vml000070 dovecot: managesieve-login: Login: user=<django@nausch.org>, method=PLAIN, rip=10.0.0.70, mpid=5212, secured, session=<4sFTvN//sAAKAABG> Aug 5 12:58:29 vml000070 dovecot: managesieve(django@nausch.org): Debug: Effective uid=10000, gid=10000, home=/srv/vmail/nausch.org/django Aug 5 12:58:29 vml000070 dovecot: managesieve(django@nausch.org): Debug: Namespace inbox: type=private, prefix=INBOX/, sep=/, inbox=yes, hidden=no, list=yes, subscriptions=yes location=maildir:/srv/vmail/nausch.org/django/Maildir Aug 5 12:58:29 vml000070 dovecot: managesieve(django@nausch.org): Debug: maildir++: root=/srv/vmail/nausch.org/django/Maildir, index=, indexpvt=, control=, inbox=/srv/vmail/nausch.org/django/Maildir, alt= Aug 5 12:58:29 vml000070 dovecot: managesieve(django@nausch.org): Debug: Namespace : type=private, prefix=, sep=, inbox=no, hidden=yes, list=no, subscriptions=no location=fail::LAYOUT=none Aug 5 12:58:29 vml000070 dovecot: managesieve(django@nausch.org): Debug: none: root=, index=, indexpvt=, control=, inbox=, alt= Aug 5 12:58:29 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve: Pigeonhole version 0.4.2 initializing Aug 5 12:58:29 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve: include: sieve_global_dir is not set; it is currently not possible to include `:global' scripts. Aug 5 12:58:29 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve-storage: using active sieve script path: /srv/vmail/nausch.org/django/.dovecot.sieve Aug 5 12:58:29 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve-storage: using sieve script storage directory: /srv/vmail/nausch.org/django/sieve Aug 5 12:58:29 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve-storage: using permissions from /srv/vmail/nausch.org/django/sieve: mode=0700 gid=-1 Aug 5 12:58:29 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve-storage: relative path to sieve storage in active link: sieve/ Aug 5 12:59:09 vml000070 dovecot: managesieve(django@nausch.org): Disconnected: Logged out bytes=6/41 Aug 5 12:59:25 vml000070 dovecot: master: Warning: Killed with signal 15 (by pid=1 uid=0 code=kill) Aug 5 12:59:25 vml000070 dovecot: imap-login: Warning: Killed with signal 15 (by pid=1 uid=0 code=kill) Aug 5 12:59:25 vml000070 dovecot: anvil: Warning: Killed with signal 15 (by pid=1 uid=0 code=kill) Aug 5 12:59:25 vml000070 dovecot: log: Warning: Killed with signal 15 (by pid=1 uid=0 code=kill) Aug 5 13:00:00 vml000070 dovecot: master: Dovecot v2.2.13 starting up for imap, pop3, lmtp, sieve (core dumps disabled) Aug 5 13:00:18 vml000070 dovecot: managesieve-login: Login: user=<django@nausch.org>, method=PLAIN, rip=10.0.0.70, mpid=5262, secured, session=<4prRwt//sQAKAABG> Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: Effective uid=10000, gid=10000, home=/srv/vmail/nausch.org/django Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: Namespace inbox: type=private, prefix=INBOX/, sep=/, inbox=yes, hidden=no, list=yes, subscriptions=yes location=maildir:/srv/vmail/nausch.org/django/Maildir Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: maildir++: root=/srv/vmail/nausch.org/django/Maildir, index=, indexpvt=, control=, inbox=/srv/vmail/nausch.org/django/Maildir, alt= Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: Namespace : type=private, prefix=, sep=, inbox=no, hidden=yes, list=no, subscriptions=no location=fail::LAYOUT=none Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: none: root=, index=, indexpvt=, control=, inbox=, alt= Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve: Pigeonhole version 0.4.2 initializing Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve: include: sieve_global_dir is not set; it is currently not possible to include `:global' scripts. Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve-storage: using active sieve script path: /srv/vmail/nausch.org/django/.dovecot.sieve Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve-storage: using sieve script storage directory: /srv/vmail/nausch.org/django/sieve Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve-storage: permission lookup failed from /srv/vmail/nausch.org/django/sieve Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve-storage: created storage directory /srv/vmail/nausch.org/django/sieve/tmp Aug 5 13:00:18 vml000070 dovecot: managesieve(django@nausch.org): Debug: sieve-storage: relative path to sieve storage in active link: sieve/ Aug 5 13:02:09 vml000070 dovecot: managesieve(django@nausch.org): Disconnected: Logged out bytes=276/385
Zum Abschluß unseres Tests liefern wir nun eine Nachricht via LMTP bei unserem Dovecot-Server ein.
$ telnet 10.0.0.70 24 Trying 10.0.0.70... Connected to 10.0.0.70. Escape character is '^]'. 220 imap.nausch.org Dovecot ready. LHLO mx01.nausch.org 250-imap.nausch.org 250-8BITMIME 250-ENHANCEDSTATUSCODES 250 PIPELINING mail from:<michael@nausch.org> 250 2.1.0 OK rcpt to:<django@nausch.org> 250 2.1.5 OK DATA 354 OK From: Michael NauschTo: Django [BOfH] 250 2.0.0Subject: Haben Du Interesse an p0rn? Date: Mon, 21 Jul 2014 09:00:36 -0000 HI, wenn Du haben willst lot of p0rn, Du mir sagen. Ich habe sehr viel davon. ttyl Bazibua . fs6GLxrC4FO0FAAAOs1BfA Saved quit 221 2.0.0 OK Connection closed by foreign host.
Im Maillog sehen wir nun, dass die Nachricht nicht zugestellt, sonder gelöscht wurde marked message to be discarded if not explicitly delivered (discard action).
Aug 5 13:38:02 vml000070 dovecot: lmtp(5300): Debug: none: root=, index=, indexpvt=, control=, inbox=, alt= Aug 5 13:38:02 vml000070 dovecot: lmtp(5300): Connect from 10.0.0.80 Aug 5 13:38:24 vml000070 dovecot: lmtp(5300): Debug: Loading modules from directory: /usr/lib64/dovecot Aug 5 13:38:24 vml000070 dovecot: lmtp(5300): Debug: Module loaded: /usr/lib64/dovecot/lib90_sieve_plugin.so Aug 5 13:38:24 vml000070 dovecot: lmtp(5300): Debug: auth input: django@nausch.org uid=10000 gid=10000 home=/srv/vmail/nausch.org/django Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): Debug: Effective uid=10000, gid=10000, home=/srv/vmail/nausch.org/django Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): Debug: Namespace inbox: type=private, prefix=INBOX/, sep=/, inbox=yes, hidden=no, list=yes, subscriptions=yes location=maildir:/srv/vmail/nausch.org/django/Maildir Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): Debug: maildir++: root=/srv/vmail/nausch.org/django/Maildir, index=, indexpvt=, control=, inbox=/srv/vmail/nausch.org/django/Maildir, alt= Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): Debug: Namespace : type=private, prefix=, sep=, inbox=no, hidden=yes, list=no, subscriptions=no location=fail::LAYOUT=none Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): Debug: none: root=, index=, indexpvt=, control=, inbox=, alt= Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): Debug: sieve: Pigeonhole version 0.4.2 initializing Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): Debug: sieve: include: sieve_global_dir is not set; it is currently not possible to include `:global' scripts. Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): Debug: fs6GLxrC4FO0FAAAOs1BfA: sieve: using the following location for user's Sieve script: /srv/vmail/nausch.org/django/.dovecot.sieve;name=main script Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): Debug: fs6GLxrC4FO0FAAAOs1BfA: sieve: loading script /srv/vmail/nausch.org/django/.dovecot.sieve;name=main script Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): Debug: fs6GLxrC4FO0FAAAOs1BfA: sieve: script `main script' from /srv/vmail/nausch.org/django/.dovecot.sieve;name=main script successfully compiled Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): Debug: fs6GLxrC4FO0FAAAOs1BfA: sieve: executing script from /srv/vmail/nausch.org/django/.dovecot.sieve;name=main script Aug 5 13:39:59 vml000070 dovecot: lmtp(5300, django@nausch.org): fs6GLxrC4FO0FAAAOs1BfA: sieve: msgid=unspecified: marked message to be discarded if not explicitly delivered (discard action) Aug 5 13:40:03 vml000070 dovecot: lmtp(5300): Disconnect from 10.0.0.80: Successful quit
Im Verzeichnis des Users django@nausch.org sehen wir keine neue Nachricht, da diese mit Hilfe des SIEVE-scriptes sofort gelöscht wurde.
/srv/vmail/nausch.org/django/ ├── .dovecot.sieve -> sieve/erste_sieve-regel_zum_testen.sieve ├── .dovecot.svbin ├── Maildir/ │ ├── cur/ │ │ └── 1407189625.M304698P4532.vml000070.dmz.nausch.org,S=409,W=422:2, │ ├── dovecot.index.cache │ ├── dovecot.index.log │ ├── dovecot.mailbox.log │ ├── dovecot-uidlist │ ├── dovecot-uidvalidity │ ├── dovecot-uidvalidity.53dfa2ad │ ├── .Drafts/ │ │ ├── cur/ │ │ ├── dovecot.index.log │ │ ├── dovecot-uidlist │ │ ├── maildirfolder │ │ ├── new/ │ │ └── tmp/ │ ├── new/ │ ├── .Sent/ │ │ ├── cur/ │ │ ├── dovecot.index.log │ │ ├── dovecot-uidlist │ │ ├── maildirfolder │ │ ├── new/ │ │ └── tmp/ │ ├── subscriptions │ └── tmp/ └── sieve/ ├── erste_sieve-regel_zum_testen.sieve └── tmp/
Test
… in Bearbeitung (Vorankündigung)! …