Postfix - encaminhamento rejeitado por e-mails de destinatários desconhecidos para a caixa de correio de aprendizado de SPAM

3

Eu tenho o Postfix + BitDefender FRAMS rodando como gateway de higiene antes de algumas trocas. BD FRAMS pode aprender o filtro baesiano por download de e-mails SPAM e HAM de caixas de correio dedicadas. Como temos de sustentar o fluxo de SPAM para destinatários desconhecidos, tenho a ideia de redirecionar essa fonte útil de emails de SPAM diretamente para a caixa de correio de aprendizado de SPAM.

Minhas configurações:

main.cf:

myhostname = posfix.example.com
smtpd_banner = $myhostname
#myorigin = example.com
mydestination =
local_recipient_maps =
#virtual_alias_maps = hash:/etc/postfix/virtual
local_transport = error:local mail delivery is disabled

mynetworks = /etc/postfix/mynetworks

smtpd_use_tls = yes
#smtpd_tls_auth_only = yes
smtpd_tls_key_file = /etc/ssl/certs/posfix.example.com.pem
smtpd_tls_cert_file = /etc/ssl/certs/posfix.example.com.pem
smtpd_tls_CApath = /etc/ssl/certs
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s

relay_domains = mysql:/etc/postfix/relay_domains
transport_maps = mysql:/etc/postfix/transport
relay_recipient_maps = mysql:/etc/postfix/relay_recipient_maps

show_user_unknown_table_name = no
unknown_local_recipient_reject_code = 550

mailbox_size_limit = 102400000000
message_size_limit = 102400000

smtpd_delay_reject = yes
smtpd_helo_required = yes

#smtpd_helo_restrictions =
#  permit_mynetworks
#  reject_invalid_hostname
#  permit

smtpd_restriction_classes = verify_sender
verify_sender =
  reject_unverified_sender

smtpd_sender_restrictions =
  permit_mynetworks

smtpd_recipient_restrictions =
  reject_unknown_recipient_domain
  reject_non_fqdn_recipient
  permit_mynetworks
  reject_authenticated_sender_login_mismatch
  reject_unauth_destination
  check_recipient_access hash:/etc/postfix/recipient_access
  check_sender_access hash:/etc/postfix/sender_access
  #check_helo_access pcre:/etc/postfix/helo_access
  reject_non_fqdn_sender
  reject_unknown_sender_domain
  reject_unlisted_sender
  reject_invalid_hostname
  reject_unauth_pipelining
  check_sender_mx_access cidr:/etc/postfix/sender_mx_access
  #reject_non_fqdn_hostname
  #reject_unverified_sender
  #reject_multi_recipient_bounce
  permit

#smtpd_data_restrictions =
  #reject_multi_recipient_bounce

# Added by BitDefender on Mon Nov  3 15:27:43 EET 2014
smtpd_milters=unix:/var/spool/postfix/BitDefender/bdmilterd.sock
milter_protocol = 2
milter_default_action = tempfail
milter_connect_timeout = 30s
milter_command_timeout = 30s
milter_content_timeout = 30s
# End of added lines

/ etc / postfix / relay_domains:

user = postfix
password = postfix
dbname = postfix
query = SELECT name FROM relay_domains WHERE name='%s'

/ etc / postfix / transport:

user = postfix
password = postfix
dbname = postfix
query = SELECT nexthop FROM relay_domains WHERE name='%s'

/ etc / postfix / relay_recipient_maps:

user = postfix
password = postfix
dbname = postfix
query = SELECT email FROM relay_users WHERE email='%s'

meu script para o preenchimento de retransmissão de usuários do AD (gentilmente compartilhar por você) para o cron:

#!/usr/bin/python

__author__ = 'tiv'

import ldap
import MySQLdb

connections = {
    1: ['dc.example.com',  # AD domain controller
        'EXAMPLE\user',  # AD user
        'password',  # AD user password
        'dc=example, dc=local',  # AD root DN
        'mail.example.com'],  # Exchange server

    2: ['dc.example1.com',  # AD domain controller
        'EXAMPLE1\user',  # AD user
        'password',  # AD user password
        'dc=example1, dc=local',  # AD root DN
        'mail.example1.com'],  # Exchange server

    #3: 'dc.example2.com',  # AD domain controller
    #   'EXAMPLE2\user',  # AD user
    #   'password',  # AD user password
    #   'dc=example2, dc=local',  # AD root DN
    #   'mail.example2.com'],  # Exchange server
}

mysql = ['localhost',  # host
         'postfix',  # user
         'postfix',  # password
         'postfix']  # schema

def main():
    try:
        emails = []
        domains = []
        for i in connections:
            connection = connections[i]
            print('Processing LDAP server ' + connection[0] + ':')
            basedn = connections[i][3]
            nexthop = connections[i][4]
            lc = ldapconnection(connection)
            ls = ldapsearch(lc, basedn)
            rl = resultlist(ls)
            emails.extend(rl[0])
            for domain in rl[1]:
                domains.append([domain, nexthop])
            print('Processing of LDAP server ' + connection[0] + ' completed.')
        createdb(emails, domains, mysql)
        print('Operation completed successfully!')
    except:
        print('Error processing of LDAP server ' + connection[0] + '!')
        pass

def ldapconnection(ldapserver):
    try:
        print(' Trying to connect to LDAP server ' + ldapserver[0] + '...')
        ldapconnection = ldap.initialize('ldap://' + ldapserver[0])
        ldapconnection.simple_bind_s(ldapserver[1], ldapserver[2])
        ldapconnection.protocol_version = ldap.VERSION3
        ldapconnection.set_option(ldap.OPT_REFERRALS, 0)
        print(' Connection to LDAP server ' + ldapserver[0] + ' succesfull.')
    except:
        print('Error connecting to LDAP server ' + ldapserver[0] + '!')
        pass
    return ldapconnection

def ldapsearch(ldapconnection, basedn):
    try:
        print(' Sending LDAP query request...')
        scope = ldap.SCOPE_SUBTREE
        filter = '(&(proxyAddresses=smtp:*)(!(objectClass=contact)))'
        attributes = ['proxyAddresses']
        searchresults = ldapconnection.search_s(basedn, scope, filter, attributes)
        print(' LDAP query request results received.')
    except:
        print('Error sending LDAP query request!')
        pass
    return searchresults

def resultlist(searchresults):
    try:
        print(' Processing LDAP query results...')
        emails = []
        domains = []
        for i in range(len(searchresults)):
            try:
                for j in range(len(searchresults[i][1]['proxyAddresses'])):
                    r = searchresults[i][1]['proxyAddresses'][j].lower()
                    if 'smtp:' in r:
                        email = r[5:]
                        emails.append(email)
                        domain = email.split("@")[1]
                        domains.append(domain)
            except:
                pass
        print(' LDAP query results processed.')
    except:
        print('Error processing LDAP query results!')
        pass
    return removedublicates(emails), removedublicates(domains)


def createdb(emails, domains, mysql):
    try:
        print('Connecting to DB ' + mysql[3] + '...')
        try:
            db = MySQLdb.connect(host=mysql[0], user=mysql[1], passwd=mysql[2])
            cursor = db.cursor()
            sql = 'CREATE SCHEMA IF NOT EXISTS ' + mysql[3]
            cursor.execute(sql)
            db.commit()
        except:
            pass
        try:
            db = MySQLdb.connect(host=mysql[0], user=mysql[1], passwd=mysql[2], db=mysql[3])
            cursor = db.cursor()
        except:
            print('Error connecting to DB ' + mysql[3] + '!')
        print(' Check schemas and tables...')
        sql = ['CREATE TABLE IF NOT EXISTS ' + mysql[3] + '.relay_users (id INT NOT NULL, email LONGTEXT NULL, PRIMARY KEY (id))',
               'CREATE TABLE IF NOT EXISTS ' + mysql[3] + '.relay_domains (id INT NOT NULL, name LONGTEXT NULL, nexthop LONGTEXT NULL, PRIMARY KEY (id))',
               'TRUNCATE ' + mysql[3] + '.relay_users',
               'TRUNCATE ' + mysql[3] + '.relay_domains']
        for i in range(len(sql)):
            cursor.execute(sql[i])
            db.commit()
        print(' Inserting domains...')
        for i in range(len(domains)):
            sql = 'INSERT INTO postfix.relay_domains (id, name, nexthop)' \
                  'VALUES ("' + str(i) + '", "' + domains[i][0] + '", "smtp:[' + domains[i][1] + ']")'
            cursor.execute(sql)
            db.commit()
        print(' Inserting emails...')
        for i in range(len(emails)):
            sql = 'INSERT INTO postfix.relay_users (id, email)' \
                  'VALUES ("' + str(i) + '", "' + emails[i] + '")'
            cursor.execute(sql)
            db.commit()
        db.close()
        print('Connection to DB ' + mysql[3] + ' closed.')
    except:
        print('Error while operating with DB ' + mysql[3] + '!')
        pass

def removedublicates(input):
    seen = set()
    seen_add = seen.add
    return [x for x in input if not (x in seen or seen_add(x))]

if __name__ == '__main__':
    main()

Se alguém souber como fazer isso, eu serei grato. Obrigado.

    
por tiv 21.10.2014 / 13:23

2 respostas

3

Sua solicitação é um pouco complicada por causa disso. O postfix, por design, executará algo com base no resultado positivo dos mapas . Por exemplo, no seu transport_maps , ele enviará um e-mail para o host específico se o destinatário tiver resultado positivo da pesquisa de mapas. Mas, você quer executar algo - redirecionar para outra caixa de correio - se houver um resultado negativo na pesquisa relay_recipient_maps . Com seu tipo de mapas é hash , eu acho que não há outra maneira a menos que envolva o mapa sql / tcp para implementar lógica de resultado negativo no mapa.

Para a solução sql, aqui está a ideia:

Neste exemplo, usarei o sqlite. Suponha que você tenha uma tabela com uma coluna denominada relay_recipient. Agora a consulta

select ifnull(select relay_recipient from mytable WHERE relay_recipient = %s, '[email protected]')

retornará [email protected] sempre que o destinatário não existir em relay_recipient_maps. Coloque esses mapas no parâmetro virtual_alias . Então, sempre que o e-mail for enviado para um usuário desconhecido, ele será aliased para [email protected]

    
por 24.10.2014 / 15:44
2

+1 para @ tmpl7 tem uma ótima idéia sobre como implementar seu cenário com o sqlite

Agora, o problema é que você não implementou a consulta sql para ifnull no parâmetro virtual_alias_maps . Primeiro defina o virtual_alias_maps em main.cf

virtual_alias_maps = mysql:/etc/postfix/redirect2spamlearning

O conteúdo de /etc/postfix/redirect2spamlearning

user = postfix
password = postfix
dbname = postfix
query = SELECT IFNULL((SELECT email FROM relay_users WHERE email='%s'), '[email protected]')

A lógica é: Se SELECT email FROM relay_users WHERE email='%s' não retornar nada a.k.um valor nulo, o e-mail será redirecionado para [email protected].

por 20.11.2014 / 17:52