Menu Chiudi

Pillola #36: MimeDefang, un coltellino svizzero per gestione degli allegati di posta elettronica tramite server Web

Premessa, quanto segue è una soluzione SOLO per gli Amministratori di Sistema, perchè il sistema venga “digerito” dagli utenti furbacchioni è indispensabile:
– convocarli tutti (se ci stanno in un’unica stanza)
– spiegare i motivi che rendono indispensabile l’adozione del seguente “sistema”
– mostrare con degli esempi (inviando e ricevendo posta) come si comporterà il nuovo sistema e cosa dovranno fare i singoli operatori.

Premessa, quanto segue è una soluzione SOLO per gli Amministratori di Sistema, perchè il sistema venga “digerito” dagli utenti furbacchioni è indispensabile:
– convocarli tutti (se ci stanno in un’unica stanza)
– spiegare i motivi che rendono indispensabile l’adozione del seguente “sistema”
– mostrare con degli esempi (inviando e ricevendo posta) come si comporterà il nuovo sistema e cosa dovranno fare i singoli operatori.

Per provare a “tamponare” il problema connesso all’eccessiva dimensione delle cassette di posta elettronica che abitualmente gli utenti “sconsiderati” utilizzano in modo improprio è possibile adottare la seguente soluzione:
– tutti gli allegati di posta elettronica che superato una specifica dimensione vengono rimossi dal body del messaggio stesso
– gli allegati rimossi vengono posizionati su di una specifica cartella di rete e condivisi tramite un server Web
– il body del messaggio viene modificato indicando esplicitamente che il messaggio di posta elettronica è stato rimosso dal messaggio stesso e che l’allegato è reperibile ad uno specifico URL
– successivamente gli allegati restano disponibili per un periodo specifico di tempo (es. 3 mesi) dopodichè gli allegati vengono cancellati dal sistema Vantaggi: – le cassette postali rimangono “leggere”
– gli utenti sono costretti ad archiviare opportunamente gli allegati ricevuti entro il termine prestabilito
– la posta elettronica viene utilizzata come tale (NON più come sistema di storage).  

NB. per l’installazione del server è stata usata la versione squeeze di Debian

Elenco link utili:

http://www.mimedefang.com/faq 
http://www.mickeyhill.com/mimedefang-howto/#ss3.1

Lo schema di funzionamento per la POSTA IN ENTRATA sarà qualcosa di simile:
smtp-esterno –> (ASSP –> QMAIL) –> sendmail –> mimedefang –> SRVPOSTAINTERNO

Lo schema di funzionamento per la POSTA IN USCITA sarà qualcosa di simile:
SRVPOSTAINTERNO –> sendmail –> mimedefang –> (ASSP –> QMAIL) –> smtp-esterno

Gli allegati di posta elettronica vengono posizionati in /allegatiposta (si tratta di un disco dedicato e montato in automatico in fase di avvio)

# cat /etc/fstab
/dev/vdb1 	/allegatiposta 	ext3 	rw 			0 	0

alla cartella /allegatiposta sono stati assegnati i seguenti permessi

chown defang:www-data /allegatiposta
chmod 750 /allegatiposta

Apache è stato configurato nel modo seguente:

# cat /etc/apache2/sites-available/default

<VirtualHost *:80>
        ServerAdmin webmaster@localhost

        DocumentRoot /allegatiposta
        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /allegatiposta>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

#       ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
#       <Directory "/usr/lib/cgi-bin">
#               AllowOverride None
#               Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
#               Order allow,deny
#               Allow from all
#       </Directory>

        ErrorLog /var/log/apache2/error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog /var/log/apache2/access.log combined

#    Alias /doc/ "/usr/share/doc/"
#    <Directory "/usr/share/doc/">
#        Options Indexes MultiViews FollowSymLinks
#        AllowOverride None
#        Order deny,allow
#        Deny from all
#        Allow from 127.0.0.0/255.0.0.0 ::1/128
#    </Directory>

</VirtualHost>

Elenco pacchetti installati:
– sendmail
– mimedefang
– apache2 SENDMAIL + MIMEDEFANG

La configurazione dei file di sendmail va fatta in due passaggi distinti:
– modificare i file di configurazione (template)
– compilare i file di configurazione

# apt-get install sendmail
# apt-get install mimedefang

– modificare il file /etc/mail/access e “compilarlo” con il seguente comando

#makemap hash /etc/mail/access.db < /etc/mail/access
# cat /etc/mail/access

Connect:localhost		RELAY
GreetPause:localhost		0
ClientRate:localhost		0
ClientConn:localhost		0

Connect:127			RELAY
GreetPause:127			0
ClientRate:127			0
ClientConn:127			0

#Connect:IPv6:::1		RELAY
#GreetPause:IPv6:::1		0
#ClientRate:IPv6:::1		0
#ClientConn:IPv6:::1		0

Connect:SRVPOSTAINTERNO		RELAY
GreetPause:SRVPOSTAINTERNO		0
ClientRate:SRVPOSTAINTERNO		0
ClientConn:SRVPOSTAINTERNO		0

– modificare opportunamente il file /etc/mail/sendmail.mc

divert(-1)dnl
#-----------------------------------------------------------------------------
# $Sendmail: debproto.mc,v 8.14.3 2010-01-29 14:02:50 cowboy Exp $
#
# Copyright (c) 1998-2008 Richard Nelson.  All Rights Reserved.
#
# cf/debian/sendmail.mc.  Generated from sendmail.mc.in by configure.
#
# sendmail.mc prototype config file for building Sendmail 8.14.3
#
# Note: the .in file supports 8.7.6 - 9.0.0, but the generated
#       file is customized to the version noted above.
#
# This file is used to configure Sendmail for use with Debian systems.
#
# If you modify this file, you will have to regenerate /etc/mail/sendmail.cf
# by running this file through the m4 preprocessor via one of the following:
#       * make   (or make -C /etc/mail)
#       * sendmailconfig
#       * m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
# The first two options are preferred as they will also update other files
# that depend upon the contents of this file.
#
# The best documentation for this .mc file is:
# /usr/share/doc/sendmail-doc/cf.README.gz
#
#-----------------------------------------------------------------------------
divert(0)dnl
#
#   Copyright (c) 1998-2005 Richard Nelson.  All Rights Reserved.
#
#  This file is used to configure Sendmail for use with Debian systems.
#
define(`_USE_ETC_MAIL_')dnl
include(`/usr/share/sendmail/cf/m4/cf.m4')dnl
VERSIONID(`$Id: sendmail.mc, v 8.14.3-5+lenny1 2010-01-29 14:02:50 cowboy Exp $')
OSTYPE(`debian')dnl
DOMAIN(`debian-mta')dnl
dnl # Items controlled by /etc/mail/sendmail.conf - DO NOT TOUCH HERE
undefine(`confHOST_STATUS_DIRECTORY')dnl        #DAEMON_HOSTSTATS=
dnl # Items controlled by /etc/mail/sendmail.conf - DO NOT TOUCH HERE
dnl #
dnl # General defines
dnl #
dnl # SAFE_FILE_ENV: [undefined] If set, sendmail will do a chroot()
dnl #   into this directory before writing files.
dnl #   If *all* your user accounts are under /home then use that
dnl #   instead - it will prevent any writes outside of /home !
dnl #   define(`confSAFE_FILE_ENV',             `')dnl
dnl #
dnl # Daemon options - restrict to servicing LOCALHOST ONLY !!!
dnl # Remove `, Addr=' clauses to receive from any interface
dnl # If you want to support IPv6, switch the commented/uncommentd lines
dnl #
FEATURE(`no_default_msa')dnl
dnl DAEMON_OPTIONS(`Family=inet6, Name=MTA-v6, Port=smtp, Addr=::1')dnl
dnl DAEMON_OPTIONS(`Family=inet,  Name=MTA-v4, Port=smtp, Addr=127.0.0.1')dnl
DAEMON_OPTIONS(`Family=inet,  Name=MTA-v4, Port=smtp')dnl
dnl DAEMON_OPTIONS(`Family=inet6, Name=MSP-v6, Port=submission, M=Ea, Addr=::1')dnl
dnl DAEMON_OPTIONS(`Family=inet,  Name=MSP-v4, Port=submission, M=Ea, Addr=127.0.0.1')dnl
DAEMON_OPTIONS(`Family=inet,  Name=MSP-v4, Port=submission, M=Ea')dnl
dnl #
dnl # Be somewhat anal in what we allow
dnl # define(`confPRIVACY_FLAGS',dnl
dnl # `needmailhelo,needexpnhelo,needvrfyhelo,restrictqrun,restrictexpand,nobodyreturn,authwarnings')dnl
dnl #
dnl # Define connection throttling and window length
dnl define(`confCONNECTION_RATE_THROTTLE', `15')dnl
dnl define(`confCONNECTION_RATE_WINDOW_SIZE',`10m')dnl
dnl #
dnl # Features
dnl #
dnl # use /etc/mail/local-host-names
dnl FEATURE(`use_cw_file')dnl
dnl #
dnl # The access db is the basis for most of sendmail's checking
FEATURE(`access_db', , `skip')dnl
dnl #
dnl # The greet_pause feature stops some automail bots - but check the
dnl # provided access db for details on excluding localhosts...
dnl FEATURE(`greet_pause', `1000')dnl 1 seconds
dnl #
dnl # Delay_checks allows sender<->recipient checking
dnl FEATURE(`delay_checks', `friend', `n')dnl
dnl #
dnl # If we get too many bad recipients, slow things down...
dnl # define(`confBAD_RCPT_THROTTLE',`3')dnl
dnl #
dnl # Stop connections that overflow our concurrent and time connection rates
dnl FEATURE(`conncontrol', `nodelay', `terminate')dnl
dnl FEATURE(`ratecontrol', `nodelay', `terminate')dnl
dnl #
dnl # If you're on a dialup link, you should enable this - so sendmail
dnl # will not bring up the link (it will queue mail for later)
dnl define(`confCON_EXPENSIVE',`True')dnl
dnl #
dnl # Dialup/LAN connection overrides
dnl #
dnl include(`/etc/mail/m4/dialup.m4')dnl
dnl include(`/etc/mail/m4/provider.m4')dnl
dnl #
dnl # Default Mailer setup
MAILER_DEFINITIONS
define(`SMART_HOST', `SRVPOSTAINTERNO')dnl
INPUT_MAIL_FILTER(`mimedefang', `S=unix:/var/spool/MIMEDefang/mimedefang.sock, F=T, T=S:1m;R:1m')dnl
MAILER(`local')dnl
MAILER(`smtp')dnl

eseguire il seguente comando per compilare i file di configurazione di sendmail e confermare tutte le opzioni

sendmailconfig

– modificare opportunamente il file /etc/mail/mimedefang-filter

# -*- Perl -*-
#***********************************************************************
#
# mimedefang-filter
#
# Suggested minimum-protection filter for Microsoft Windows clients, plus
# SpamAssassin checks if SpamAssassin is installed.
#
# Copyright (C) 2002 Roaring Penguin Software Inc.
#
# This program may be distributed under the terms of the GNU General
# Public License, Version 2, or (at your option) any later version.
#
# $Id$
#***********************************************************************

#***********************************************************************
# Set administrator's e-mail address here.  The administrator receives
# quarantine messages and is listed as the contact for site-wide
# MIMEDefang policy.  A good example would be 'defang-admin@mydomain.com'
#***********************************************************************
$AdminAddress = 'ced@MIODOMINIO';
$AdminName = "Amministratori di Rete";

#***********************************************************************
# Set the e-mail address from which MIMEDefang quarantine warnings and
# user notifications appear to come.  A good example would be
# 'mimedefang@mydomain.com'.  Make sure to have an alias for this
# address if you want replies to it to work.
#***********************************************************************
$DaemonAddress = 'mimedefang@MIODOMINIO';

#***********************************************************************
# If you set $AddWarningsInline to 1, then MIMEDefang tries *very* hard
# to add warnings directly in the message body (text or html) rather
# than adding a separate "WARNING.TXT" MIME part.  If the message
# has no text or html part, then a separate MIME part is still used.
#***********************************************************************
$AddWarningsInline = 1;

#***********************************************************************
# To enable syslogging of virus and spam activity, add the following
# to the filter:
# md_graphdefang_log_enable();
# You may optionally provide a syslogging facility by passing an
# argument such as:  md_graphdefang_log_enable('local4');  If you do this, be
# sure to setup the new syslog facility (probably in /etc/syslog.conf).
# An optional second argument causes a line of output to be produced
# for each recipient (if it is 1), or only a single summary line
# for all recipients (if it is 0.)  The default is 1.
# Comment this line out to disable logging.
#***********************************************************************
# md_graphdefang_log_enable('mail', 1);

#***********************************************************************
# Uncomment this to block messages with more than 50 parts.  This will
# *NOT* work unless you're using Roaring Penguin's patched version
# of MIME tools, version MIME-tools-5.411a-RP-Patched-02 or later.
#
# WARNING: DO NOT SET THIS VARIABLE unless you're using at least
# MIME-tools-5.411a-RP-Patched-02; otherwise, your filter will fail.
#***********************************************************************
# $MaxMIMEParts = 50;

#***********************************************************************
# Set various stupid things your mail client does below.
#***********************************************************************

# Set the next one if your mail client cannot handle multiple "inline"
# parts.
$Stupidity{"NoMultipleInlines"} = 1;

# Detect and load Perl modules
detect_and_load_perl_modules();


#***********************************************************************
# %PROCEDURE: filter_begin
# %ARGUMENTS:
#  $entity -- the parsed MIME::Entity
# %RETURNS:
#  Nothing
# %DESCRIPTION:
#  Called just before e-mail parts are processed
#***********************************************************************
sub filter_begin {
    my($entity) = @_;

    # Copy original message into work directory as an "mbox" file for
    # virus-scanning
    md_copy_orig_msg_to_work_dir_as_mbox_file();

}

#***********************************************************************
# %PROCEDURE: filter
# %ARGUMENTS:
#  entity -- a Mime::Entity object (see MIME-tools documentation for details)
#  fname -- the suggested filename, taken from the MIME Content-Disposition:
#           header.  If no filename was suggested, then fname is ""
#  ext -- the file extension (everything from the last period in the name
#         to the end of the name, including the period.)
#  type -- the MIME type, taken from the Content-Type: header.
#
#  NOTE: There are two likely and one unlikely place for a filename to
#  appear in a MIME message:  In Content-Disposition: filename, in
#  Content-Type: name, and in Content-Description.  If you are paranoid,
#  you will use the re_match and re_match_ext functions, which return true
#  if ANY of these possibilities match.  re_match checks the whole name;
#  re_match_ext checks the extension.  See the sample filter below for usage.
# %RETURNS:
#  Nothing
# %DESCRIPTION:
#  This function is called once for each part of a MIME message.
#  There are many action_*() routines which can decide the fate
#  of each part; see the mimedefang-filter man page.
#***********************************************************************
sub filter {
    my($entity, $fname, $ext, $type) = @_;

    return if message_rejected(); # Avoid unnecessary work

    # Block message/partial parts
    if (lc($type) eq "message/partial") {
        md_graphdefang_log('message/partial');
	action_bounce("MIME type message/partial not accepted here");
	return action_discard();
    }

     # sposto gli allegati superiori ad una certa dimensione in una cartella accessibile
     # tramite webserver
     $size = (stat($entity->bodyhandle->path))[7];
     if ($size > 2000000) {
        return action_replace_with_url($entity,
          "/allegatiposta",
          "http://IndirizzoDelServerWebDoveSarannoPubblicatiGliAllegati",
          "Uno degli allegati e' piu' grande di 2MB.\n" .
          "NB. l'allegato verrà rimosso in automatico entro 90 giorni dalla data odierna.\n" .
          "L'allegato puo essere scaricato direttamente a questo indirizzo\n\n" .
          "\t_URL_\n");
    }

    return action_accept();
}

#***********************************************************************
# %PROCEDURE: filter_multipart
# %ARGUMENTS:
#  entity -- a Mime::Entity object (see MIME-tools documentation for details)
#  fname -- the suggested filename, taken from the MIME Content-Disposition:
#           header.  If no filename was suggested, then fname is ""
#  ext -- the file extension (everything from the last period in the name
#         to the end of the name, including the period.)
#  type -- the MIME type, taken from the Content-Type: header.
# %RETURNS:
#  Nothing
# %DESCRIPTION:
#  This is called for multipart "container" parts such as message/rfc822.
#  You cannot replace the body (because multipart parts have no body),
#  but you should check for bad filenames.
#***********************************************************************
sub filter_multipart {
    my($entity, $fname, $ext, $type) = @_;

    return if message_rejected(); # Avoid unnecessary work

    # Block message/partial parts
    if (lc($type) eq "message/partial") {
        md_graphdefang_log('message/partial');
	action_bounce("MIME type message/partial not accepted here");
	return;
    }

    return action_accept();
}


#***********************************************************************
# %PROCEDURE: defang_warning
# %ARGUMENTS:
#  oldfname -- the old file name of an attachment
#  fname -- the new "defanged" name
# %RETURNS:
#  A warning message
# %DESCRIPTION:
#  This function customizes the warning message when an attachment
#  is defanged.
#***********************************************************************
sub defang_warning {
    my($oldfname, $fname) = @_;
    return
	"L'allegato di nome '$oldfname' e' stato convertito in '$fname'.\n";
}

# If SpamAssassin found SPAM, append report.  We do it as a separate
# attachment of type text/plain
sub filter_end {
    my($entity) = @_;

    # No sense doing any extra work
    return if message_rejected();

    # I HATE HTML MAIL!  If there's a multipart/alternative with both
    # text/plain and text/html parts, nuke the text/html.  Thanks for
    # wasting our disk space and bandwidth...

    # If you want to strip out HTML parts if there is a corresponding
    # plain-text part, uncomment the next line.
    #
    # NB. questo è molto interessante ma prima di abilitarlo valutate bene eventuali conseguenze !!
    #
    #remove_redundant_html_parts($entity);

    md_graphdefang_log('mail_in');

}

# DO NOT delete the next line, or Perl will complain.
1;

– verificare la sintassi del file mimedefan-filter

mimedefang.pl -test

– per rendere effettive le modifiche applicate al file mimedefang-filter

/etc/init.d/mimedefang reread
/etc/init.d/mimedefang restart

La rimozione degli allegati ritenuti obsoleti viene effettuata in automatico tramite un comando schedulato tramite cron.

cat /etc/cron.d/cancellaallegatiobsoleti

# m h dom mon dow user  command
05 20   * * *   root    find /allegatiposta -atime 90 -type f -exec rm {} \;

gli allegati rimossi NON devono essere sostituiti con altrettanti allegati testuali contententi il messaggio e il link all'allegato rimosso, ma vogliamo che il link stesso venga aggiunto direttamente al body del messaggio.
# diff -Nau /usr/bin/mimedefang.pl.originale /usr/bin/mimedefang.pl
--- /usr/bin/mimedefang.pl.originale 2013-05-02 16:29:54.000000000 +0200
+++ /usr/bin/mimedefang.pl 2013-05-03 09:39:42.000000000 +0200
@@ -817,7 +817,7 @@

if ($Action eq "replace") {
$Changed = 1;
- $out->add_part($ReplacementEntity);
+# $out->add_part($ReplacementEntity);
return 0;
}

@@ -848,7 +848,7 @@
# If action is "replace", replace it with $ReplacementEntity;
if ($Action eq "replace") {
$Changed = 1;
- $out->add_part($ReplacementEntity);
+# $out->add_part($ReplacementEntity);
return 0;
}

@@ -1193,15 +1193,19 @@
sub action_replace_with_warning ($) {
my($msg) = @_;
return 0 if (!in_filter_context("action_replace_with_warning"));
+
$Actions{'replace_with_warning'}++;
$Action = "replace";
- $ReplacementEntity = MIME::Entity->build(Type => "text/plain",
- Encoding => "-suggest",
- Data => [ "$msg\n" ]);
+# $ReplacementEntity = MIME::Entity->build(Type => "text/plain",
+# Encoding => "-suggest",
+# Data => [ "$msg\n" ]);
$WarningCounter++;
- $ReplacementEntity->head->mime_attr("Content-Type.name" => "warning$WarningCounter.txt");
- $ReplacementEntity->head->mime_attr("Content-Disposition" => "inline");
- $ReplacementEntity->head->mime_attr("Content-Disposition.filename" => "warning$WarningCounter.txt");
+# $ReplacementEntity->head->mime_attr("Content-Type.name" => "warning$WarningCounter.txt");
+# $ReplacementEntity->head->mime_attr("Content-Disposition" => "inline");
+# $ReplacementEntity->head->mime_attr("Content-Disposition.filename" => "warning$WarningCounter.txt");
+
+push(@Warnings, "$msg\n");
+
return 1;
}

@@ -5296,14 +5300,14 @@
$DaemonAddress = 'mailer-daemon@localhost' unless defined($DaemonAddress);
$SALocalTestsOnly = 1 unless defined($SALocalTestsOnly);

- if (!defined($GeneralWarning)) {
- $GeneralWarning =
- "WARNING: This e-mail has been altered by MIMEDefang. Following this\n" .
- "paragraph are indications of the actual changes made. For more\n" .
- "information about your site's MIMEDefang policy, contact\n" .
- "$AdminName <$AdminAddress>. For more information about MIMEDefang, see:\n\n" .
- " $URL\n\n";
- }
+# if (!defined($GeneralWarning)) {
+# $GeneralWarning =
+# "WARNING: This e-mail has been altered by MIMEDefang. Following this\n" .
+# "paragraph are indications of the actual changes made. For more\n" .
+# "information about your site's MIMEDefang policy, contact\n" .
+# "$AdminName <$AdminAddress>. For more information about MIMEDefang, see:\n\n" .
+# " $URL\n\n";
+# }

# check dir
$workdir = $ARGV[0];
WordPress Appliance - Powered by TurnKey Linux