Outbound SPAM filter

Discussion in 'Server Operation' started by shawnbot, Feb 14, 2010.

  1. shawnbot

    shawnbot New Member

    Hello all,

    I'm having trouble getting my mail server to scan outbound emails for spam, incoming works fine (in as much as that it captures spammy email). Any feedback would be appreciated. My setup as follows:

    FreeBSD 6
    postfix 2.3.2
    amavisd-new 2.4.2
    spamassassin 3.1.3
    mysql 5

    conf files:

    amavisd.conf

    # @bypass_virus_checks_maps = (1); # uncomment to DISABLE anti-virus code
    # @bypass_spam_checks_maps = (1); # uncomment to DISABLE anti-spam code

    $max_servers = 2; # num of pre-forked children (2..15 is common), -m
    $daemon_user = 'vscan'; # (no default; customary: vscan or amavis), -u
    $daemon_group = 'vscan'; # (no default; customary: vscan or amavis), -g

    $mydomain = 'somedomain.com'; # a convenient default for other settings

    $MYHOME = '/var/amavis'; # a convenient default for other settings, -H
    $TEMPBASE = "$MYHOME/tmp"; # working directory, needs to exist, -T
    $ENV{TMPDIR} = $TEMPBASE; # environment variable TMPDIR
    $QUARANTINEDIR = '/var/virusmails'; # -Q
    # $quarantine_subdir_levels = 1; # add level of subdirs to disperse quarantine

    # $daemon_chroot_dir = $MYHOME; # chroot directory or undef, -R

    # $db_home = "$MYHOME/db"; # dir for bdb nanny/cache/snmp databases, -D
    # $helpers_home = "$MYHOME/var"; # working directory for SpamAssassin, -S
    # $lock_file = "$MYHOME/var/amavisd.lock"; # -L
    # $pid_file = "$MYHOME/var/amavisd.pid"; # -P
    #NOTE: create directories $MYHOME/tmp, $MYHOME/var, $MYHOME/db manually

    # @local_domains_maps = ( [".$mydomain"] );
    # @mynetworks = qw( 127.0.0.0/8 [::1] [FE80::]/10 [FEC0::]/10
    # 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 );

    @local_domains_maps = ( [".$mydomain"] );
    @mynetworks = qw( 127.0.0.0/8 x.x.x.x/24 x.x.x.x/24 x.x.x.x/24 x.x.x.x x.x.x.x/24 );

    $log_level = 5; # verbosity 0..5, -d
    $log_recip_templ = undef; # disable by-recipient level-0 log entries
    $DO_SYSLOG = 1; # log via syslogd (preferred)
    $syslog_facility = 'mail.debug'; # Syslog facility as a string
    # e.g.: mail, daemon, user, local0, ... local7
    $syslog_priority = 'debug'; # Syslog base (minimal) priority as a string,
    # choose from: emerg, alert, crit, err, warning, notice, info, debug

    #$enable_db = 1; # enable use of BerkeleyDB/libdb (SNMP and nanny)
    #$enable_global_cache = 1; # enable use of libdb-based cache if $enable_db=1

    $inet_socket_port = 10024; # listen on this local TCP port(s) (see $protocol)
    $unix_socketname = "$MYHOME/amavisd.sock"; # amavisd-release or amavis-milter
    # option(s) -p overrides $inet_socket_port and $unix_socketname

    $interface_policy{'SOCK'}='AM.PDP-SOCK'; # only relevant with $unix_socketname
    # Use with amavis-release over a socket or with Petr Rehor's amavis-milter.c
    # (with amavis-milter.c from this package or old amavis.c client use 'AM.CL'):
    $policy_bank{'AM.PDP-SOCK'} = { protocol=>'AM.PDP' };

    $sa_tag_level_deflt = 2.0; # add spam info headers if at, or above that level
    $sa_tag2_level_deflt = 6.31; # add 'spam detected' headers at that level
    $sa_kill_level_deflt = 6.31; # triggers spam evasive actions
    $sa_dsn_cutoff_level = 10; # spam level beyond which a DSN is not sent
    #$sa_debug
    # $sa_quarantine_cutoff_level = 20; # spam level beyond which quarantine is off
    # $penpals_bonus_score = 4; # (no effect without a @storage_sql_dsn database)
    # $penpals_threshold_high = $sa_kill_level_deflt; # don't waste time on hi spam

    $sa_mail_body_size_limit = 512*1024; # don't waste time on SA if mail is larger
    $sa_local_tests_only = 0; # only tests which do not require internet access?

    # @lookup_sql_dsn =
    # ( ['DBI:mysql:database=mail;host=127.0.0.1;port=3306', 'user1', 'passwd1'],
    # ['DBI:mysql:database=mail;host=host2', 'username2', 'password2'],
    # ["DBI:SQLite:dbname=$MYHOME/sql/mail_prefs.sqlite", '', ''] );
    # @storage_sql_dsn = @lookup_sql_dsn; # none, same, or separate database

    # $timestamp_fmt_mysql = 1; # if using MySQL *and* msgs.time_iso is TIMESTAMP;
    # defaults to 0, which is good for non-MySQL or if msgs.time_iso is CHAR(16)

    $virus_admin = "postmaster\@$mydomain"; # notifications recip.

    $mailfrom_notify_admin = "postmaster\@$mydomain"; # notifications sender
    $mailfrom_notify_recip = "postmaster\@$mydomain"; # notifications sender
    $mailfrom_notify_spamadmin = "postmaster\@$mydomain"; # notifications sender
    $mailfrom_to_quarantine = ''; # null return path; uses original sender if undef

    @addr_extension_virus_maps = ('virus');
    @addr_extension_spam_maps = ('spam');
    @addr_extension_banned_maps = ('banned');
    @addr_extension_bad_header_maps = ('badh');
    # $recipient_delimiter = '+'; # undef disables address extensions altogether
    # when enabling addr extensions do also Postfix/main.cf: recipient_delimiter=+

    $path = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/usr/bin:/bin';
    # $dspam = 'dspam';

    $MAXLEVELS = 14;
    $MAXFILES = 1500;
    $MIN_EXPANSION_QUOTA = 100*1024; # bytes (default undef, not enforced)
    $MAX_EXPANSION_QUOTA = 300*1024*1024; # bytes (default undef, not enforced)

    $sa_spam_subject_tag = '***SPAM*** ';
    $defang_virus = 1; # MIME-wrap passed infected mail
    $defang_banned = 1; # MIME-wrap passed mail containing banned name


    # OTHER MORE COMMON SETTINGS (defaults may suffice):

    # $myhostname = 'host.example.com'; # must be a fully-qualified domain name!

    # $notify_method = 'smtp:[127.0.0.1]:10025';
    # $forward_method = 'smtp:[127.0.0.1]:10025'; # set to undef with milter!

    # $final_virus_destiny = D_DISCARD;
    # $final_banned_destiny = D_BOUNCE;
    # $final_spam_destiny = D_BOUNCE;
    # $final_bad_header_destiny = D_PASS;

    # $os_fingerprint_method = 'p0f:127.0.0.1:2345'; # to query p0f-analyzer.pl

    ## hierarchy by which a final setting is chosen:
    ## policy bank (based on port or IP address) -> *_by_ccat
    ## *_by_ccat (based on mail contents) -> *_maps
    ## *_maps (based on recipient address) -> final configuration value


    # SOME OTHER VARIABLES WORTH CONSIDERING (see amavisd.conf-default for all)


    @bypass_virus_checks_maps = ( [qw( . )] );

    # $warnbadhsender,
    # $warnvirusrecip, $warnbannedrecip, $warnbadhrecip, (or @warn*recip_maps)
    #
    # @bypass_virus_checks_maps, @bypass_spam_checks_maps,
    # @bypass_banned_checks_maps, @bypass_header_checks_maps,
    #
    # @virus_lovers_maps, @spam_lovers_maps,
    # @banned_files_lovers_maps, @bad_header_lovers_maps,
    #
    # @blacklist_sender_maps, @score_sender_maps,
    #
    # $clean_quarantine_method, $virus_quarantine_to, $banned_quarantine_to,
    # $bad_header_quarantine_to,
    #
    # $defang_bad_header, $defang_undecipherable, $defang_spam

    $spam_quarantine_to = "spam\@$mydomain";

    # REMAINING IMPORTANT VARIABLES ARE LISTED HERE BECAUSE OF LONGER ASSIGNMENTS

    @keep_decoded_original_maps = (new_RE(
    # qr'^MAIL$', # retain full original message for virus checking (can be slow)
    qr'^MAIL-UNDECIPHERABLE$', # recheck full mail if it contains undecipherables
    qr'^(ASCII(?! cpio)|text|uuencoded|xxencoded|binhex)'i,
    # qr'^Zip archive data', # don't trust Archive::Zip
    ));


    # for $banned_namepath_re, a new-style of banned table, see amavisd.conf-sample

    $banned_filename_re = new_RE(
    # qr'^UNDECIPHERABLE$', # is or contains any undecipherable components

    # block certain double extensions anywhere in the base name
    qr'\.[^./]*[A-Za-z][^./]*\.(exe|vbs|pif|scr|bat|cmd|com|cpl|dll)\.?$'i,

    # qr'\{[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}\}?'i, # Class ID CLSID, strict
    # qr'\{[0-9a-z]{4,}(-[0-9a-z]{4,}){0,7}\}?'i, # Class ID extension CLSID, loose

    qr'^application/x-msdownload$'i, # block these MIME types
    qr'^application/x-msdos-program$'i,
    qr'^application/hta$'i,

    # qr'^(application/x-msmetafile|image/x-wmf)$'i, # Windows Metafile MIME
    # qr'^\.wmf$', # Windows Metafile file(1) type

    # qr'^message/partial$'i, # rfc2046 MIME type
    # qr'^message/external-body$'i, # rfc2046 MIME type

    # [ qr'^\.(Z|gz|bz2)$' => 0 ], # allow any in Unix-compressed
    [ qr'^\.(rpm|cpio|tar)$' => 0 ], # allow any in Unix-type archives
    # [ qr'^\.(zip|rar|arc|arj|zoo)$'=> 0 ], # allow any within such archives

    qr'.\.(exe|vbs|pif|scr|bat|cmd|com|cpl)$'i, # banned extension - basic
    # qr'.\.(ade|adp|app|bas|bat|chm|cmd|com|cpl|crt|emf|exe|fxp|grp|hlp|hta|
    # inf|ins|isp|js|jse|lnk|mda|mdb|mde|mdw|mdt|mdz|msc|msi|msp|mst|
    # ops|pcd|pif|prg|reg|scr|sct|shb|shs|vb|vbe|vbs|
    # wmf|wsc|wsf|wsh)$'ix, # banned ext - long

    # qr'.\.(mim|b64|bhx|hqx|xxe|uu|uue)$'i, # banned extension - WinZip vulnerab.

    qr'^\.(exe-ms)$', # banned file(1) types
    # qr'^\.(exe|lha|tnef|cab|dll)$', # banned file(1) types
    );
    # See http://support.microsoft.com/default.aspx?scid=kb;EN-US;q262631
    # and http://www.cknow.com/vtutor/vtextensions.htm


    # ENVELOPE SENDER SOFT-WHITELISTING / SOFT-BLACKLISTING

    @score_sender_maps = ({ # a by-recipient hash lookup table,
    # results from all matching recipient tables are summed

    # ## per-recipient personal tables (NOTE: positive: black, negative: white)
    # '[email protected]' => [{'[email protected]' => 10.0}],
    # '[email protected]' => [{'.ebay.com' => -3.0}],
    # '[email protected]' => [{'[email protected]' => -7.0,
    # '.cleargreen.com' => -5.0}],

    ## site-wide opinions about senders (the '.' matches any recipient)
    '.' => [ # the _first_ matching sender determines the score boost

    new_RE( # regexp-type lookup table, just happens to be all soft-blacklist
    [qr'^(bulkmail|offers|cheapbenefits|earnmoney|foryou)@'i => 5.0],
    [qr'^(greatcasino|investments|lose_weight_today|market\.alert)@'i=> 5.0],
    [qr'^(money2you|MyGreenCard|new\.tld\.registry|opt-out|opt-in)@'i=> 5.0],
    [qr'^(optin|saveonlsmoking2002k|specialoffer|specialoffers)@'i => 5.0],
    [qr'^(stockalert|stopsnoring|wantsome|workathome|yesitsfree)@'i => 5.0],
    [qr'^(your_friend|greatoffers)@'i => 5.0],
    [qr'^(inkjetplanet|marketopt|MakeMoney)\d*@'i => 5.0],
    ),

    # read_hash("/var/amavis/sender_scores_sitewide"),

    { # a hash-type lookup table (associative array)
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    'securityfocus.com' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]'=> -3.0,
    '[email protected]' => -3.0,
    'spamassassin.apache.org' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -3.0,
    '[email protected]' => -5.0,
    '[email protected]' => -3.0,
    'returns.groups.yahoo.com' => -3.0,
    '[email protected]' => -3.0,
    lc('[email protected]') => -3.0,
    lc('[email protected]') => -5.0,

    # soft-blacklisting (positive score)
    '[email protected]' => 3.0,
    '.example.net' => 1.0,

    },
    ], # end of site-wide tables
    });


    @decoders = (
    ['mail', \&do_mime_decode],
    ['asc', \&do_ascii],
    ['uue', \&do_ascii],
    ['hqx', \&do_ascii],
    ['ync', \&do_ascii],
    ['F', \&do_uncompress, ['unfreeze','freeze -d','melt','fcat'] ],
    ['Z', \&do_uncompress, ['uncompress','gzip -d','zcat'] ],
    ['gz', \&do_uncompress, 'gzip -d'],
    ['gz', \&do_gunzip],
    ['bz2', \&do_uncompress, 'bzip2 -d'],
    ['lzo', \&do_uncompress, 'lzop -d'],
    ['rpm', \&do_uncompress, ['rpm2cpio.pl','rpm2cpio'] ],
    ['cpio', \&do_pax_cpio, ['pax','gcpio','cpio'] ],
    ['tar', \&do_pax_cpio, ['pax','gcpio','cpio'] ],
    ['tar', \&do_tar],
    ['deb', \&do_ar, 'ar'],
    # ['a', \&do_ar, 'ar'], # unpacking .a seems an overkill
    ['zip', \&do_unzip],
    ['rar', \&do_unrar, ['rar','unrar'] ],
    ['arj', \&do_unarj, ['arj','unarj'] ],
    ['arc', \&do_arc, ['nomarch','arc'] ],
    ['zoo', \&do_zoo, ['zoo','unzoo'] ],
    ['lha', \&do_lha, 'lha'],
    # ['doc', \&do_ole, 'ripole'],
    ['cab', \&do_cabextract, 'cabextract'],
    ['tnef', \&do_tnef_ext, 'tnef'],
    ['tnef', \&do_tnef],
    # ['sit', \&do_unstuff, 'unstuff'], # broken/unsafe decoder
    ['exe', \&do_executable, ['rar','unrar'], 'lha', ['arj','unarj'] ],
    );


    @av_scanners = (

    # ### http://www.clamav.net/
    ['ClamAV-clamd',
    \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd"],
    qr/\bOK$/, qr/\bFOUND$/,
    qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
    # # NOTE: the easiest is to run clamd under the same user as amavisd; match the
    # # socket name (LocalSocket) in clamav.conf to the socket name in this entry
    # # When running chrooted one may prefer: ["CONTSCAN {}\n","$MYHOME/clamd"],

    # ### http://www.clamav.net/ and CPAN (memory-hungry! clamd is preferred)
    # ['Mail::ClamAV', \&ask_clamav, "*", [0], [1], qr/^INFECTED: (.+)/],


    main.cf:

    queue_directory = /var/spool/postfix

    command_directory = /usr/local/sbin

    daemon_directory = /usr/local/libexec/postfix

    mail_owner = postfix

    myhostname = mail.somedomain.com

    inet_interfaces = all

    $mydomain
    unknown_local_recipient_reject_code = 550
    mynetworks = x.x.x.x/24, x.x.x.x/24, x.x.x.x/24, x.x.x.x/24, x.x.x.x/24, 127.0.0.0/8

    hash:/usr/local/etc/postfix/relay_recipients

    debug_peer_level = 3

    debugger_command =
    PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
    xxgdb $daemon_directory/$process_name $process_id & sleep 5

    sendmail_path = /usr/local/sbin/sendmail

    newaliases_path = /usr/local/bin/newaliases

    mailq_path = /usr/local/bin/mailq

    setgid_group = maildrop

    html_directory = no

    manpage_directory = /usr/local/man

    readme_directory = no

    #Amavis

    content_filter = smtp-amavis:[127.0.0.1]:10024

    virtual_mailbox_base = /var/spool/postfix/virtual/
    virtual_mailbox_maps = mysql:/usr/local/etc/postfix/mysql_virtual_mailbox_maps.cf
    virtual_mailbox_domains = mysql:/usr/local/etc/postfix/mysql_virtual_domains_maps.cf
    #virtual_alias_domains =
    virtual_alias_maps = mysql:/usr/local/etc/postfix/mysql_virtual_alias_maps.cf

    virtual_uid_maps = static:5001
    virtual_gid_maps = static:5001

    virtual_transport = virtual
    maildrop_destination_recipient_limit = 1
    maildrop_destination_concurrency_limit = 1

    queue_minfree = 61457280
    mailbox_size_limit = 60971520
    message_size_limit = 40971520
    virtual_mailbox_limit = 60971520
    virtual_create_maildirsize = yes
    virtual_mailbox_extended = yes

    virtual_mailbox_limit_maps = mysql:/usr/local/etc/postfix/mysql_virtual_mailbox_limit_maps.cf
    virtual_mailbox_limit_override = yes
    virtual_maildir_limit_message = Sorry, the user's maildir is over the allowed limit. Please try again later.
    virtual_overquota_bounce = yes

    bounce_template_file = /usr/local/etc/postfix/bounce.cf

    data_directory = /var/db/postfix

    master.cf:

    #
    # Postfix master process configuration file. For details on the format
    # of the file, see the Postfix master(5) manual page.
    #
    # ==========================================================================
    # service type private unpriv chroot wakeup maxproc command + args
    # (yes) (yes) (yes) (never) (100)
    # ==========================================================================
    smtp inet n - n - - smtpd
    #submission inet n - n - - smtpd
    # -o smtpd_etrn_restrictions=reject
    # -o smtpd_client_restrictions=permit_sasl_authenticated,reject
    #smtps inet n - n - - smtpd
    # -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes
    #submission inet n - n - - smtpd
    # -o smtpd_etrn_restrictions=reject
    # -o smtpd_enforce_tls=yes -o smtpd_sasl_auth_enable=yes
    #628 inet n - n - - qmqpd
    pickup fifo n - n 60 1 pickup
    cleanup unix n - n - 0 cleanup
    qmgr fifo n - n 300 1 qmgr
    #qmgr fifo n - n 300 1 oqmgr
    tlsmgr unix - - n 1000? 1 tlsmgr
    rewrite unix - - n - - trivial-rewrite
    bounce unix - - n - 0 bounce
    defer unix - - n - 0 bounce
    trace unix - - n - 0 bounce
    verify unix - - n - 1 verify
    flush unix n - n 1000? 0 flush
    proxymap unix - - n - - proxymap
    smtp unix - - n - - smtp
    # When relaying mail as backup MX, disable fallback_relay to avoid MX loops
    relay unix - - n - - smtp
    -o fallback_relay=
    # -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
    showq unix n - n - - showq
    error unix - - n - - error
    discard unix - - n - - discard
    local unix - n n - - local
    virtual unix - n n - - virtual
    lmtp unix - - n - - lmtp
    anvil unix - - n - 1 anvil
    scache unix - - n - 1 scache
    #
    # ====================================================================
    # Interfaces to non-Postfix software. Be sure to examine the manual
    # pages of the non-Postfix software to find out what options it wants.
    #
    # Many of the following services use the Postfix pipe( delivery
    # agent. See the pipe( man page for information about ${recipient}
    # and other message envelope options.
    # ====================================================================
    #
    # maildrop. See the Postfix MAILDROP_README file for details.
    # Also specify in main.cf: maildrop_destination_recipient_limit=1
    #
    maildrop unix - n n - - pipe
    flags=DRhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient}
    # flags=DRhu user=vmail:vmail argv=/usr/local/bin/maildrop -w 90 -d ${recipient}
    # The Cyrus deliver program has changed incompatibly, multiple times.
    #
    old-cyrus unix - n n - - pipe
    flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
    # Cyrus 2.1.5 (Amos Gouaux)
    # Also specify in main.cf: cyrus_destination_recipient_limit=1
    cyrus unix - n n - - pipe
    user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
    #
    # See the Postfix UUCP_README file for configuration details.
    #
    uucp unix - n n - - pipe
    flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
    #
    # Other external delivery methods.
    #
    ifmail unix - n n - - pipe
    flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
    bsmtp unix - n n - - pipe
    flags=Fq. user=foo argv=/usr/local/sbin/bsmtp -f $sender $nexthop $recipient
    #AMAVIS

    smtp-amavis unix - - n - 2 smtp
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20
    127.0.0.1:10025 inet n - n - - smtpd
    -o content_filter=
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o smtpd_restriction_classes=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o smtpd_data_restrictions=reject_unauth_pipelining
    -o smtpd_end_of_data_restrictions=
    -o mynetworks_style=host
    -o mynetworks=127.0.0.0/8
    -o strict_rfc821_envelopes=yes
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
    retry unix - - n - - error
    proxywrite unix - - n - 1 proxymap


    spamassassin local.cf:


    rewrite_header Subject *****SPAM*****

    report_safe 1


    # Set which networks or hosts are considered 'trusted' by your mail
    # server (i.e. not spammers)
    #
    # trusted_networks 212.17.35.

    required_score 5.0

    use_bayes 1

    bayes_auto_learn 1
     

Share This Page