Ir al contenido

Servidor de Correo – Casillas y usuarios virtuales

DKIM, SPF y DMARC

Este artículo cubre el soporte de múltiples dominios y usuarios virtuales, gestión de alias y correo electrónico mediante interfaces web.

Nombre del Servidor: servidor.midominio.edu.ar
Sistema Operativo: Debian 10 “Buster”

Instalar paquetes

# apt install postfix postfix-mysql dovecot-core dovecot-imapd dovecot-pop3d dovecot-lmtpd dovecot-mysql mariadb-server dovecot-sieve dovecot-managesieved

Si estás agregando un servidor de correo a un sistema existente algunos paquetes pueden ya estar presentes. Dependiendo de la lista de paquetes previamente instalada, puede que veas o no los avisos para configurar mariadb, postfix, etc. Escoge los valores predeterminados siempre que sea posible.

Configuración de Postfix

Esta guía fue creada usando Postfix 3.4.14. Se puede verificar la versión de postfix instalada usando:

# postconf mail_version

La configuración de Postfix tiene 2 archivos importantes: main.cf y master.cf

Vamos a agregar también algunos otros archivos para el sistema virtual de dominio/correo.

Postfix – master.cf

Para que smtp ‘escuche’ en el puerto 465 (con SSL) y en el puerto 587 (con TLS), es necesario descomentar las siguientes lineas en

master.cf:
submission inet n - - - - smtpd
smtps inet n - - - - smtpd

Se recomienda hacer esto ya que la mayoría de los ISP bloquea el puerto 25 para prevenir spam.

Diffie – Hellman

El intercambio de claves Diffie-Hellman es un método de intercambio seguro de claves criptográficas a través de un canal público. Su objetivo principal es desarrollar de forma segura secretos compartidos que puedan utilizarse para derivar claves. Estas claves pueden utilizarse con algoritmos de clave simétrica para transmitir información de forma protegida.

Generación de un grupo DH único

Primero hay que generar un nuevo y único grupo Diffie-Hellman, la recomendación es que sea de 2048 bits. La forma más sencilla de hacerlo es utilizar OpenSSL:

# openssl dhparam -out dhparams.pem 2048

Esto puede representar una carga significativa en el servidor mientras se generan los parámetros – siempre se puede evitar este problema potencial mediante la generación de los parámetros en otra máquina y el uso de scp o similar para transferirlos al servidor en cuestión para su uso.

Postfix – main.cf

Agregar al main.cf las siguientes lineas hacia el final del archivo:
Agregamos y ajustamos los demás parámetros:

# other destination domains should be handled using virtual domains
mydestination = localhost
smtp_host_lookup = dns
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtpd_tls_dh1024_param_file = /etc/ssl/private/dhparams.pem
smtpd_helo_required=yes
#Secure Client-Initiated Renegotiation
# postfix 3.4 and openssl >1.1.1
tls_ssl_options = NO_RENEGOTIATION
#Enable TLS Encryption when Postfix receives incoming emails
smtpd_tls_cert_file=/etc/apache2/md/domains/midominio.edu.ar/pubcert.pem
smtpd_tls_key_file=/etc/apache2/md/domains/midominio.edu.ar/privkey.pem
# Enforce encryption during authentication
smtpd_tls_auth_only=yes
smtpd_tls_loglevel = 1
# Add information about the ciphers used during transfer to the
# message headers
smtpd_tls_received_header = yes
# Encryption is optional. Changing this to encrypt will enforce
# the use of TLS but has the side effect that MTAs without TLS
# capability won't be able to deliver mail to our server.
smtpd_tls_security_level = may
# Disallow any methods that do allow anonymous authentication
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
#Enable TLS Encryption when Postfix sends outgoing emails
# Enforce the use of TLS
smtp_tls_security_level = may
smtp_tls_loglevel = $smtpd_tls_loglevel
smtp_tls_mandatory_protocols = $smtpd_tls_mandatory_protocols
smtp_tls_mandatory_ciphers = $smtpd_tls_mandatory_ciphers
smtp_tls_exclude_ciphers = $smtpd_tls_exclude_ciphers
smtp_tls_mandatory_exclude_ciphers = $smtpd_tls_mandatory_exclude_ciphers
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# Negotiate the strongest available cipher available with the remote server.
smtpd_tls_protocols = TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_protocols = $smtpd_tls_protocols
smtp_tls_ciphers = high
smtpd_tls_ciphers = high
smtpd_tls_mandatory_protocols = $smtpd_tls_protocols
smtp_tls_mandatory_protocols = $smtpd_tls_protocols
smtp_tls_mandatory_ciphers = high
smtpd_tls_mandatory_ciphers = high
# Exclude some deprecated not so secure ciphers.
smtpd_tls_mandatory_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
smtpd_tls_exclude_ciphers = $smtpd_tls_mandatory_exclude_ciphers
smtp_tls_mandatory_exclude_ciphers = $smtpd_tls_mandatory_exclude_ciphers
smtp_tls_exclude_ciphers = $smtpd_tls_mandatory_exclude_ciphers
# Postfix will select the cipher used for communication.
tls_preempt_cipherlist = yes
# Disable all OpenSSL bug work-arounds on a 64 bit system
tls_disable_workarounds = 0xFFFFFFFFFFFFFFFF
#Handle SMTP authentication using Dovecot
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
# Don't talk to mail systems that don't know their own hostname.
smtpd_recipient_restrictions =
 reject_unknown_sender_domain,
 permit_mynetworks,
 permit_sasl_authenticated,
# DNSBL (DNS Based Blacklist/Blocklist)
 reject_rbl_client zen.spamhaus.org,
 reject_rhsbl_reverse_client dbl.spamhaus.org,
 reject_rhsbl_helo dbl.spamhaus.org,
 reject_rhsbl_sender dbl.spamhaus.org,
# Don't accept mail from domains that don't exist.
smtpd_sender_restrictions =
 reject_unknown_sender_domain
# Allow connections from trusted networks and authenticated users.
smtpd_client_restrictions =
 permit_mynetworks,
 permit_sasl_authenticated
# Relay control: local clients and
# authenticated clients may specify any destination domain.
smtpd_relay_restrictions =
 permit_mynetworks,
 permit_sasl_authenticated,
 reject_unauth_destination
#The size is in Bytes...
mailbox_size_limit = 0 # Ilimitado
message_size_limit = 20971520 # 20 Mb
# using Dovecot's LMTP for mail delivery and giving it path to store mail
virtual_transport = lmtp:unix:private/dovecot-lmtp
# virtual mailbox setups
virtual_alias_maps = mysql:/etc/postfix/mysql/virtual_alias_maps.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql/virtual_domains_maps.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql/virtual_mailbox_maps.cf

Deshabilitamos el chroot (predeterminado en Debian) modificando /etc/postfix/master.cf. Debería verse así

# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp unix - - - - - smtp

Verificar certificados

Ninguna configuración está exenta de eventuales problemas. Llegado el caso, estos comandos pueden resultar de utilidad a la hora de enfrentarlos.
Para los certificados públicos

openssl x509 -in /etc/apache2/md/domains/midominio.edu.ar/pubcert.pem -text -noout

Si no está dañado el resultado de este comando debería mostrar, entre otras cosas, los (sub)dominios para los cuales fue creado:

DNS:campus.midominio.edu.ar, DNS:eventos.midominio.edu.ar, DNS:mapa.midominio.edu.ar, DNS:nube.midominio.edu.ar, DNS:pad.midominio.edu.ar, DNS:reuniones.midominio.edu.ar, DNS:www.midominio.edu.ar

En tanto que, para los certificados privados verificamos que contengan una llave válida

openssl rsa -in /etc/apache2/md/domains/midominio.edu.ar/privkey.pem -text -noout

El resultado de este comando debería mostrar algo así:

RSA key ok

Configuración de Casillas de Correo Virtuales en Postfix

Vamos a utilizar una base de datos mariadb para dominios, usuarios y alias virtuales.
Creamos un directorio separado para almacenar toda la configuración de postfix relacionada con la base de datos:

# mkdir /etc/postfix/mysql

Mapeo de Alias Virtuales

Creamos un archivo:

# nano /etc/postfix/mysql/virtual_alias_maps.cf

Y pegamos allí lo siguiente:

user = vimbadmin
password = password
hosts = 127.0.0.1
dbname = vimbadmin
query = SELECT goto FROM alias WHERE address = '%s' AND active = '1'

Mapeo de Dominios Virtuales

Creamos un archivo:

# nano /etc/postfix/mysql/virtual_domains_maps.cf

Y pegamos allí lo siguiente:

user = vimbadmin
password = password
hosts = 127.0.0.1
dbname = vimbadmin
query = SELECT domain FROM domain WHERE domain = '%s' AND backupmx = '0' AND active = '1'

Mapeo de Casillas de Correo (usuario) Virtuales

Creamos un archivo:

# nano /etc/postfix/mysql/virtual_mailbox_maps.cf

Y pegamos allí lo siguiente:

user = vimbadmin
password = password
hosts = 127.0.0.1
dbname = vimbadmin
query = SELECT maildir FROM mailbox WHERE username = '%s' AND active = '1'

El comando postmap crea o consulta las tablas de búsqueda de Postfix, o actualiza alguna existente. Ingresamos el siguiente comando para asegurarnos que Postfix puede consultar la tabla de dominios. Reemplazar midominio.edu.ar con el primer valor almacenado. El comando debería devolver 1 si tiene éxito:

# postmap -q midominio.edu.ar mysql:/etc/postfix/mysql/virtual_domains_maps.cf

Probamos Postfix para verificar que puede obtener la primer dirección de correo de la base de datos. Reemplazar raul@midominio.edu.ar con la primer dirección de correo registrada en la tabla. Deberíamos ver un 1 si tiene éxito:

# postmap -q raul@midominio.edu.ar mysql:/etc/postfix/mysql/virtual_mailbox_maps.cf

Por último verificamos que Postfix puede consultar la tabla de alias. Reemplazar alias-raul@midominio.edu.ar con el primer valor de origen creado en la tabla. El comando debería arrojar el valor de destino para la fila:

# postmap -q alias-raul@midominio.edu.ar mysql:/etc/postfix/mysql/virtual_alias_maps.cf

Configuración de Dovecot

Dovecot es un servidor IMAP y POP. Además implementa seguridad/autenticación para IMAP/POP así como también SMTP (vía Postfix).
Usamos dovecot versión 2.3.4.1. Esto se puede verificar usando el comando:

# dovecot --version

Un usuario de linux real – vmail

Los siguientes comandos crean un usuario y un grupo llamado vmail. Se trata de un usuario de linux que será propietario de los correos electrónicos de todo el mundo (No hay que entrar en pánico por este hecho…)

# groupadd -g 5000 vmail
# useradd -g vmail -u 5000 vmail -d /var/vmail -m

Reiniciamos postfix

# service postfix restart

Dovecot está configurado de manera modular con archivos en /etc/dovecot/conf.d/
que son incluidos desde /etc/dovecot/dovecof.conf.
A Efectos prácticos es preferible tener un solo archivo de configuración en lugar de varios, así que resguardamos una copia del original. Y creamos unos nuevo copiando la salida de
dovecot -n a dovecot.conf:

# doveconf -n > /etc/dovecot/dovecot.conf.new
# mv /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
# mv /etc/dovecot/dovecot.conf.new /etc/dovecot/dovecot.conf
# nano /etc/dovecot/dovecot.conf

Configurar la ubicación de almacenamiento de correo

mail_location = maildir:/var/vmail/%d/%n

Habilitamos los protocolos necesarios

# Enable installed protocols
!include_try /usr/share/dovecot/protocols.d/*.protocol
protocols = imap lmtp sieve

Buscamos la linea ssl = no, y la eliminamos. Luego insertamos el siguiente bloque:

service imap-login {
 inet_listener imap {
 port = 0
 }
 inet_listener imaps {
 port = 993
 }
}
ssl = required
ssl_cert = </etc/apache2/md/domains/midominio.edu.ar/pubcert.pem
ssl_key = </etc/apache2/md/domains/midominio.edu.ar/privkey.pem
ssl_prefer_server_ciphers=yes
### Protocolos
ssl_protocols = !SSLv3 !TLSv1 !TLSv1.1 #Dovecot 2.2.x
ssl_min_protocol=TLSv1.2 #Dovecot 2.3.x o superior

Con esto forzamos el uso de TLS/SSL, especificamos nuestros certificados, deshabilitamos IMAP (definiendo el puerto igual a 0) y configuramos el servicio imap-login en el puerto 993 (IMAPS).

Configurar la autenticación

disable_plaintext_auth = no
auth_mechanisms = plain login

Finalmente agregamos soporte para autenticación basada en mariadb en la parte inferior:

passdb {
 driver = sql
 args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
 driver = static
 args = uid=5000 gid=5000 home=/var/vmail/%d/%n allow_all_users=yes
}

El Protocolo de Transferencia de Correo Local, o LMTP, es en esencia el que permite a Postfix y Dovecot hablar entre sí. Y es necesario, además, para establecer reglas de filtrado u otro tipo de procesamiento inteligente de la entrega de correo.

service lmtp {
 unix_listener /var/spool/postfix/private/dovecot-lmtp {
 mode = 0600
 user = postfix
 group = postfix
 }
}
protocol lmtp {
 postmaster_address = administrador@midominio.edu.ar
}

Configurar los parámetros mariadb en dovecot

# nano /etc/dovecot/dovecot-sql.conf.ext

Pegar lo siguiente al final:

default_pass_scheme = SHA512-CRYPT
driver = mysql
connect = host=localhost dbname=vimbadmin user=vimbadmin password=password
password_query = \
 SELECT username AS user, password, \
 homedir AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \
 FROM mailbox WHERE username = '%u'
# iterate_query = SELECT username AS user FROM mailbox

Resulta fundamental para el funcionamiento de nuestro sistema que se defina el esquema utilizado para almacenar las contraseñas en la base de datos, en este caso SHA512-CRYPT.
Por otro lado, en toda la configuración relacionada al vínculo entre mariadb y dovecot puede ser necesario reemplazar la referencia al localhost por 127.0.0.1

Verificar configuración de dovecot

Nos aseguramos que contenga lo siguiente:

service auth {
 unix_listener /var/spool/postfix/private/auth {
 mode = 0666
 user = postfix
 group = postfix
 }
 unix_listener auth-userdb {
 mode = 0600
 user = vmail
 }
 user = dovecot
}
service auth-worker {
 user = vmail
}

Registro de Errores

Dovecot siempre registra un mensaje detallado del error en caso que algo salga mal. Estos mensajes pueden registrarse en un archivo diferente que los mensajes informativos. Podemos encontrar la ubicación tales archivos con:

doveadm log find

Para más detalles acerca del registro de errores, se recomienda ver los parámetros disponibles en la documentación de dovecot.

Doveconf

Al hacer tantos cambios resulta fácil perderse. En esos casos se pueden listar los cambios hechos en toda la configuración de dovecot, para ello:

# doveconf -n

De manera similar, doveconf -a muestra la configuración completa de dovecot (incluyendo los valores predeterminados).

Reiniciar dovecot

# systemctl restart dovecot

ViMbAdmin – Administración web del Servidor de Correo Virtual

ViMbAdmin tiene una estética agradable y usa PHP.

Instalación Composer

Dependencias necesarias

# apt install curl php-cli php-mbstring git unzip

Descarga e instalación de Composer

# cd ~
# curl -sS https://getcomposer.org/installer -o composer-setup.php

Comprobamos que el instalador coincide con el hash SHA-384 para el último instalador que se encuentra en la página [Claves públicas de composer / Firmas][composer-sigs]. Copiamos el hash de esa página y lo guardamos como una variable de shell:

HASH=48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5

Ejecutamos el siguiente script PHP para verificar que el script de instalación es seguro de ejecutar:

php -r "if (hash_file('SHA384', 'composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"

Verás la siguiente salida:

Installer verified

Si ves que Instaler corrupt, tendrás que descargar el script de instalación de nuevo y comprobar que estás usando el hash correcto. A continuación, ejecuta el comando para verificar el instalador de nuevo. Una vez que tengas un instalador verificado, puedes continuar.
Para instalar composer globalmente, usa el siguiente comando que lo descargará e instalará como un comando para todo el sistema llamado composer, en /usr/local/bin:

php composer-setup.php --install-dir=/usr/local/bin --filename=composer

Verás lo siguiente:

All settings correct for using Composer
Downloading...
Composer (version 1.8.6) successfully installed to: /usr/local/bin/composer
Use it: php /usr/local/bin/composer

Para probar tu instalación, ejecuta:

composer

Y verás la salida que muestra la versión y los argumentos de composer, similar a esto:

 ______
 / ____/___ ____ ___ ____ ____ ________ _____
 / / / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__ ) __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
 /_/
Composer version 1.8.6 2019-06-11 15:03:05
...

Instalación ViMbAdmin v3

# export INSTALL_PATH=/srv/vimbadmin
# git clone https://github.com/opensolutions/ViMbAdmin.git $INSTALL_PATH
# cd $INSTALL_PATH
# composer install --prefer-dist --no-dev
# chown -R www-data: $INSTALL_PATH/var

Pese a las recomendaciones, se efectuó la instalación como root y luego se cambió la propiedad del directorio vimbadmin a www-data, también se estableció el setgid
Creamos una base de datos y usuario en mariadb para vimbadmin, para ello ejecutamos lo siguiente en la consola de mariadb

CREATE DATABASE `vimbadmin`;
GRANT ALL ON `vimbadmin`.* TO `vimbadmin`@`localhost` IDENTIFIED BY 'password';
FLUSH PRIVILEGES;

Archivo de configuración de vimbadmin

# cp $INSTALL_PATH/application/configs/application.ini.dist $INSTALL_PATH/application/configs/application.ini
# nano $INSTALL_PATH/application/configs/application.ini
securitysalt = "superadmin-password"
defaults.mailbox.uid = 5000
defaults.mailbox.gid = 5000
defaults.mailbox.homedir = "/var/vmail/"
resources.doctrine2.connection.options.driver = 'pdo_mysql'
resources.doctrine2.connection.options.dbname = 'vimbadmin'
resources.doctrine2.connection.options.user = 'vimbadmin'
resources.doctrine2.connection.options.password = 'contraseña'
resources.doctrine2.connection.options.host = 'localhost'

Verificamos que los datos de acceso a mariadb sean los correctos en la configuración anterior.

Entorno de aplicación

Como mínimo, debe copiar este archivo .htaccess de ejemplo incluido.

# cp $INSTALL_PATH/public/.htaccess.dist $INSTALL_PATH/public/.htaccess

Modificamos el archivo, de modo que la última línea se vea así:

RewriteRule ^.*$ /index.php [NC,L]

Crear las tablas mariadb

Lo siguiente creará las tablas mariadb para lo cual ya hemos configurado postfix y dovecot.

./bin/doctrine2-cli.php orm:schema-tool:create

Configuración de Apache

En este caso vamos a definir un subdominio

 <VirtualHost vma.midominio.edu.ar:80>
 ServerAdmin administrador@midominio.edu.ar
 ServerName vma.midominio.edu.ar
 ServerAlias vma.midominio.edu.ar
 DocumentRoot /srv/vimbadmin/public
 <Directory /srv/vimbadmin/public>
 Options FollowSymLinks
 AllowOverride FileInfo
 Require all granted
 </Directory>
 ErrorLog ${APACHE_LOG_DIR}/error_vma.log
 CustomLog ${APACHE_LOG_DIR}/access_vma.log combined
 </VirtualHost>

A partir de aquí se puede visitar vma.midominio.edu.ar y crear una cuenta de administrador ViMbAdmin. Por favor, notar que esta cuenta ViMbAdmin no es una cuenta virtual de correo electrónico.
Es posible agregar dominio, usuarios virtuales de correo electrónico luego de ingresar a vma.midominio.edu.ar usando la cuenta ViMbAdmin.

Probando la configuración

Local
La herramienta cliente de OpenSSL ofrece una manera de conectar y diagnosticar servidores:

# openssl s_client -starttls smtp -connect midominio.edu.ar:587
# openssl s_client -connect midominio.edu.ar:993

ambos comandos deben arrojar
Verify return code: 0 (ok)
como una de las últimas líneas.

Servidor
En una nueva terminal, nos conectamos al servidor

# tail -f /var/log/mail.log

para verificar si postfix y dovecot están (re-)arrancando sin inconvenientes:

# service postfix restart
# service dovecot restart

Luego verificamos los puertos 25, 587 y 993 aparecen en la columna ‘Local Address’:

# netstat -ltnp

Configuración de MUA (Mail User Agent) ej. Mozilla Thunderbird

Correo entrante IMAP:

Nombre de host: midominio.edu.ar
Puerto: 993
SSL: SSL/TLS
Autenticación: Clave normal
Nombre de usuario: administrador@midominio.edu.ar

Correo saliente SMTP:

Nombre de host: midominio.edu.ar
Puerto: 587
SSL: STARTTLS
Autenticación: Clave normal
Nombre de usuario: administrador@midominio.edu.ar

Configuración automática de los clientes de correo para IMAP/SMTP

Algunos clientes de correo emplean un sistema denominado “Autodiscover” para averiguar cuáles son los parámetros de uso imap/smtp.
Puedes configurar esto si quieres, básicamente requiere un subdominio y un registro SRV.
Puedes agregar el registro SRV en cualquier dominio para el que quieras usar esta configuración.
Si tienes un certificado SSL global en dovecot para tu nombre de host, esta sería una buena forma de asegurarte de que los clientes utilizan el valor correcto, para que no obtengan errores de certificado SSL.
Supongamos que vas a tener a tus clientes con

midominio.edu.ar

conectados a

correo.midominio.edu.ar

tanto para IMAP como para SMTP.
Creamos un subdominio llamado

autodiscover.midominio.edu.ar

para almacenar el XML.
Configuramos un registro SRV en la zona DNS de midominio.edu.ar:

_autodiscover._tcp.midominio.edu.ar. 3600 IN SRV 10 10 443 autodiscover.midominio.edu.ar.

Luego, creamos el subdominio autodiscover.midominio.edu.ar y añadimos el siguiente código en un archivo llamado autodiscover.php:

<?php
//get raw POST data so we can extract the email address
$data = file_get_contents("php://input");
preg_match("/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $data, $matches);
//set Content-Type
header("Content-Type: application/xml");
echo '<?xml version="1.0" encoding="utf-8" ?>'; ?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
 <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
 <Account>
 <AccountType>email</AccountType>
 <Action>settings</Action>
 <Protocol>
 <Type>IMAP</Type>
 <Server>correo.midominio.edu.ar</Server>
 <Port>993</Port>
 <DomainRequired>off</DomainRequired>
 <LoginName><?php echo $matches[1]; ?></LoginName>
 <SPA>off</SPA>
 <SSL>on</SSL>
 <AuthRequired>on</AuthRequired>
 </Protocol>
 <Protocol>
 <Type>SMTP</Type>
 <Server>correo.midominio.edu.ar</Server>
 <Port>587</Port>
 <DomainRequired>off</DomainRequired>
 <LoginName><?php echo $matches[1]; ?></LoginName>
 <SPA>off</SPA>
 <Encryption>TLS</Encryption>
 <AuthRequired>on</AuthRequired>
 <UsePOPAuth>off</UsePOPAuth>
 <SMTPLast>off</SMTPLast>
 </Protocol>
 </Account>
 </Response>
</Autodiscover>

Ten en cuenta que el registro SRV utiliza el puerto 443 para autodiscover.midominio.edu.ar, así que asegúrate de tener una configuración de certificado válida para este subdominio.
Puedes probar yendo a https://autodiscover.midominio.edu.ar para asegurarte de que tienes un candado verde. El script busca la entrada XML en la etiqueta <EMailAddress> para insertar en el campo de resultado <LoginName>.
Si es necesario, puedes configurar SMTP para usar el puerto 465, pero tendrías que cambiar la <Encriptación> de TLS a SSL, ya que el protocolo es diferente en el 465.
El puerto 587 requiere smtp-auth pero se salta algunas comprobaciones de spam y usa STARTTLS para habilitar SSL. El puerto 465 es SSL completo pero los clientes pueden tener problemas para enviar si su IP/rango está en una RBL.
Por último, necesitaremos configurar un archivo .htaccess para que cualquier petición al subdominio autodiscover.midominio.edu.ar resulte en que se llame al autodiscover.php. En el DocumentRoot del subdominio, añade este código:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ autodiscover.php [NC,L]
Thunderbird

A diferencia de la auto-detección de Microsoft, Thunderbird hace un intento directo a
http://autoconfig.midominio.edu.ar/mail/config-v1.1.xml?emailaddress=user@midominio.edu.ar
Esto puede ser manejado creando un subdominio llamado “autoconfig”, y en el área web de este subdominio, crear una carpeta llamada “mail”, y dentro de este directorio “mail”, crear un archivo llamado config-v1.1.xml. Una ruta de ejemplo podría ser similar a:
/domains/midominio.edu.ar/public_html/autoconfig/mail/config-v1.1.xml
Dentro de este archivo, colocamos el código:

<clientConfig version="1.1">
 <emailProvider id="midominio.edu.ar">
 <domain>midominio.edu.ar</domain>
 <displayName>%EMAILADDRESS%</displayName>
 <incomingServer type="imap">
 <hostname>mail.midominio.edu.ar</hostname>
 <port>993</port>
 <socketType>SSL</socketType>
 <username>%EMAILADDRESS%</username>
 <authentication>password-cleartext</authentication>
 </incomingServer>
 <outgoingServer type="smtp">
 <hostname>smtp.midominio.edu.ar</hostname>
 <port>587</port>
 <socketType>STARTTLS</socketType>
 <username>%EMAILADDRESS%</username>
 <authentication>password-cleartext</authentication>
 </outgoingServer>
 </emailProvider>
</clientConfig>

Instalación de Roundcube

Creamos un directorio y nos ubicamos allí:

# mkdir /srv/roundcube
# cd /srv/roundcube

Descargamos y descomprimimos el tar.gz de RoundCube:

# wget https://github.com/roundcube/roundcubemail/releases/download/1.4.10/roundcubemail-1.4.10-complete.tar.gz
# tar xfz roundcubemail-1.4.10-complete.tar.gz

Los archivos de RoundCube ahora están en la carpeta /srv/roundcube/roundcubemail-1.4.10. El próximo paso es moverlos un nivel hacia arriba a /srv/roundcube.

# mv roundcubemail-1.4.10/* .
# mv roundcubemail-1.4.10/.htaccess .

El punto al final de ambos comandos es requerida y parte de la sentencia, ¡no lo olvides! Eliminamos el directorio y el archivo tar.gz.

# rmdir roundcubemail-1.4.10
# rm roundcubemail-1.4.10-complete.tar.gz

Cambiamos la propiedad de todos los archivos al usuario que está utilizando el Apache.

# chown -R www-data:www-data /srv/roundcube

Instalamos la base de datos de RoundCube

Roundcube requiere una base de datos para almacenar la configuración de la casilla de correo, contactos, etc. Vamos a crear una base de datos con el nombre “roundcubemail” y un usuario con el mismo nombre “roundcube” en MariaDB.
Ingresamos a la consola de MariaDB con el siguiente comando:

# mysql --defaults-file=/etc/mysql/debian.cnf

Luego ejecutamos los siguientes comandos para crear la base de datos y el usuario. Reemplazando “clavesecreta” con la contraseña que prefieras.

CREATE DATABASE roundcubemail;
GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost IDENTIFIED BY 'clavesecreta';
FLUSH PRIVILEGES;
QUIT

Ahora importaremos las tablas de RoundCube desde el archivo mysql.initial.sql en nuestra nueva base de datos. Para ello ejecutamos el comando en la consola de Linux:

# mysql --defaults-file=/etc/mysql/debian.cnf roundcubemail < /srv/roundcube/SQL/mysql.initial.sql

Configurar RoundCube y Apache

En este paso, vamos a configurar los detalles de la base de datos en RoundCube y también a agregar un archivo de configuración en Apache.
Ejecutamos el siguiente comando para crear un nuevo archivo config.inc.php basado en la configuración de ejemplo y lo abrimos.

# cd /srv/roundcube/config
# cp -pf config.inc.php.sample config.inc.php
# nano config.inc.php

Hallar la linea de configuración de la base de datos que comienza con $config[‘db_dsnw’] y reemplazarla con lo siguiente:

$config['db_dsnw'] = 'mysql://roundcube:clavesecreta@localhost/roundcubemail';

Luego modificamos la configuración predeterminada.

// The IMAP host chosen to perform the log-in.
$config['default_host'] = 'ssl://correo.midominio.edu.ar';
// TCP port used for IMAP connections
$config['default_port'] = 993;
$config['imap_auth_type'] = PLAIN;
// IMAP socket context options
$config['imap_conn_options'] = array(
 'ssl' => array(
 'peer_name' => 'correo.midominio.edu.ar',
 'verify_peer_name' => true,
 'capath' => '/usr/lib/ssl/certs/',
 'local_cert' => '/etc/letsencrypt/live/correo.midominio.edu.ar/fullchain.pem',
 'verify_peer' => true,
 ),
);
// SMTP server host (for sending mails).
$config['smtp_server'] = 'tls://correo.midominio.edu.ar';
// SMTP port (default is 25; use 587 for STARTTLS or 465 for the
// deprecated SSL over SMTP (aka SMTPS))
$config['smtp_port'] = 587;
// SMTP socket context options
$config['smtp_conn_options'] = array(
 'ssl' => array(
 'peer_name' => 'correo.midominio.edu.ar',
 'verify_peer_name' => true,
 'capath' => '/usr/lib/ssl/certs/',
 'local_cert' => '/etc/letsencrypt/live/correo.midominio.edu.ar/fullchain.pem',
 'verify_peer' => true,
 ),
);
// Name your service. This is displayed on the login screen and in the window t$
$config['product_name'] = 'Correo de Mi Dominio';
// List of active plugins (in plugins/ directory)
$config['plugins'] = array(
 'password',
 ...
);

Ahora es necesario configurar Apache. Creamos un nuevo archivo de configuración roundcube.conf en /etc/apache2/sites-available/.

# nano /etc/apache2/sites-available/roundcube.conf

Agregamos las siguientes lineas y lo guardamos.

<VirtualHost correo.midominio.edu.ar:80>
 ServerAdmin administrador@midominio.edu.ar
 ServerName correo.midominio.edu.ar
 ServerAlias correo.midominio.edu.ar
 DocumentRoot /srv/roundcube
 <Directory />
 Options FollowSymLinks
 AllowOverride None
 </Directory>
 <Directory /srv/roundcube>
 Options +FollowSymLinks
 # AddDefaultCharset UTF-8
 AddType text/x-component .htc

 <IfModule mod_rewrite.c>
 RewriteEngine On
 RewriteRule ^favicon\.ico$ skins/larry/images/favicon.ico
 # security rules:
 # - deny access to files not containing a dot or starting with a dot
 # in all locations except installer directory
 RewriteRule ^(?!installer)(\.?[^\.]+)$ - [F]
 # - deny access to some locations
 RewriteRule ^/?(\.git|\.tx|SQL|bin|config|logs|temp|tests|program\/(include|lib|localization|steps)) - [F]
 # - deny access to some documentation files
 RewriteRule /?(README\.md|composer\.json-dist|composer\.json|package\.xml)$ - [F]
 </IfModule>
 <IfModule mod_deflate.c>
 SetOutputFilter DEFLATE
 </IfModule>
 <IfModule mod_expires.c>
 ExpiresActive On
 ExpiresDefault "access plus 1 month"
 </IfModule>
 FileETag MTime Size
 <IfModule mod_autoindex.c>
 Options -Indexes
 </ifModule>
 AllowOverride None
 Require all granted
 </Directory>
 <Directory /srv/roundcube/plugins/enigma/home>
 Options -FollowSymLinks
 AllowOverride None
 Require all denied
 </Directory>
 <Directory /srv/roundcube/config>
 Options -FollowSymLinks
 AllowOverride None
 Require all denied
 </Directory>
 <Directory /srv/roundcube/temp>
 Options -FollowSymLinks
 AllowOverride None
 Require all denied
 </Directory>
 <Directory /srv/roundcube/logs>
 Options -FollowSymLinks
 AllowOverride None
 Require all denied
 </Directory>
</VirtualHost>

Habilitamos la configuración y recargamos apache:

# a2site roundcube
# systemctl reload apache2

RoundCube estará disponible desde correo.midominio.edu.ar.

Casi todos tienen su propio archivo de configuración ubicado en el directorio del plugin. Inicialmente este archivo de configuración se llama config.inc.php.dist. Debemos renombrarlo a config.inc.php.

Luego editamos el archivo config.inc.php para comprobar si alguna de las opciones requiere ser modificada. Basta con seguirlas instrucciones proporcionadas en el propio archivo o en el archivo README del plugin.

Agregar el complemento a la configuración de Roundcube.

Ahora que el plugin está copiado y configurado, necesitamos indicar a Roundcube que debe ser cargado. Para ello, se debe añadir el nombre del plugin al archivo de configuración principal de Roundcube.

# nano /srv/roundcube/config/config.inc.php

Buscamos la linea $config[‘plugins’] = array(); y agregamos el complemento que deseamos. Por ejemplo, para la gestión de contraseñas sería

$config['plugins'] = array('password');

En caso que ya hubiera algunos complementos, debemos añadir el nombre del nuevo al final de la lista. Por ejemplo, la matriz de podría tener este aspecto:

$config['plugins'] = array('zipdownload', 'archive');

La forma correcta de añadir otro plugin es:

$config['plugins'] = array('zipdownload', 'archive', 'password');

Siguiendo con el ejemplo del complemento para gestionar las contraseñas desde Roundcube, editamos el archivo de configuración de ese complemento.

# nano /srv/roundcube/plugins/password/config.inc.php

Indicamos el algoritmo de encriptación y las credenciales de acceso a la base de datos.

/plugins/password/config.inc.php
$config['password_algorithm'] = 'sha512-crypt';
$config['password_dovecotpw'] = '/usr/local/sbin/doveadm pw'; // for dovecot-2.x
$config['password_dovecotpw_method'] = 'SHA512-CRYPT';
$config['password_db_dsn'] = 'mysql://vimbadmin:contraseña@localhost/vimbadmin';
$config['password_query'] = 'UPDATE mailbox SET password=%c,modified=NOW() WHERE username=%u ';
$config['password_crypt_hash'] = 'sha512';

En este punto ya tendremos habilitada la opción Contraseña dentro de las opciones de Configuración

DKIM, SPF y DMARC

DKIM, SPF y DMARC son estándares que habilitan diferentes aspectos de la autenticación de correo electrónico. Abordan cuestiones complementarias.

  • SPF permite a los remitentes definir qué direcciones IP pueden enviar correo para un dominio determinado.
  • DKIM proporciona una clave de cifrado y una firma digital que verifica que un mensaje de correo electrónico no fue falsificado o alterado.
  • DMARC unifica los mecanismos de autenticación de SPF y DKIM en un marco común y permite a los propietarios de los dominios declarar cómo desean que se maneje el correo electrónico de ese dominio si no pasa una prueba de autorización.

Instalación Básica

# apt install opendkim opendkim-tools postfix-policyd-spf-python postfix-pcre

Agregar el usuario postfix al grupo opendkim de modo que Postfix pueda acceder al socket de OpenDKIM cuando lo necesite:

# adduser postfix opendkim

Configurar SPF

Agregar registros SPF al DNS

midominio.edu.ar.IN TXT "v=spf1 mx a ip4:170.210.45.130 ip6:2800:110:44:6260::130 a:correo.midominio.edu.ar -all"
  • La etiqueta v=spf1 es necesaria y tiene que ser la primera.
  • La última etiqueta, -all, indica que el correo de nuestro dominio solo debería proceder de los servidores identificados en la cadena SPF.
  • mx señala a todos los hosts listados en los registros MX de nuestro dominio.
  • La etiqueta a permite identificar un host específico por nombre o dirección IP, con esto podemos definir que hosts están autorizados.

Agregar el agente de directivas SPF a Postfix

El agente de directivas SPF basado en Python agrega la verificación de directivas SPF a Postfix. El registro SPF para el dominio del remitente del correo entrante será verificado y, si existe, el correo será manejado en consecuencia.

  1. Al usar SpamAssassin, puede que querramos editar/etc/postfix-policyd-spf-python/policyd-spf.confpara cambiar la configuración deHELO_rejectyMail_From_rejectaFalse. Esto hará que el agente de directivas SPF ejecute sus pruebas y agregue un mensaje al encabezado con los resultados y no rechace ningún mensaje. Esto también resulta útil si queremos ver los resultados del procesamiento de no aplicarlos al procesamiento de coreo. De otro modo, basta continuar con la configuración estándar.
  2. Editamos/etc/postfix/master.cfy agregamos lo siguiente al final:
    policyd-spf unix - n n - 0 spawn user=policyd-spf argv=/usr/bin/policyd-spf
  3. Abrir/etc/postfix/main.cfy agregar esta entrada para incrementar el timeout del agente de directivas de Postfix, con lo cual evitaremos que Postfix aborte al agente si las transacciones se enlentecen:
    policyd-spf_time_limit = 3600
  1. Editar la entradasmtpd_recipient_restrictionspara agregar check_policy_service:
    smtpd_recipient_restrictions =
     ...
     reject_unauth_destination,
     check_policy_service unix:private/policyd-spf,
     ...

    Debemos asegurarnos de agregar la entrada check_policy_service después de
    reject_unauth_destination para evitar que nuestro sistema se convierta en un relay abierto. Si reject_unauth_destination es la última entrada en nuestra lista de restricciones, es necesario agregar una coma a continuación de ella y omitir la coma al final de check_policy_service.

  2. Reiniciar Postfix
    systemctl restart postfix

Podemos verificar el funcionamiento del agente de directivas buscando en los encabezados originales en del correo entrante el encabezado de resultados SPF. El encabezado que el agente de directivas agrega a los mensajes debería ser similar a este:

Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=127.0.0.1; helo=mail.midominio.edu.ar; envelope-from=text@midominio.edu.ar; receiver=tknarr@silverglass.org

Esto indica una verificación exitosa contra las directivas SPF del dominio remitente. Si cambiamos las directivas definidas en el paso 1 para que no rechace el correo que no pasa la validación SPF, podríamos ver resultados fallidos en este encabezado. Este encabezado no aparecerá en correo saliente o local.
El agente de directivas SPF también registra su actividad en /var/log/mail.log. Allí veremos mensajes como este:

Jan 7 06:24:44 arachnae policyd-spf[21065]: None; identity=helo; client-ip=127.0.0.1; helo=mail.midominio.edu.ar; envelope-from=test@midominio.edu.ar; receiver=tknarr@silverglass.org
Jan 7 06:24:44 arachnae policyd-spf[21065]: Pass; identity=mailfrom; client-ip=127.0.0.1; helo=mail.midominio.edu.ar; envelope-from=test@midominio.edu.ar; receiver=tknarr@silverglass.org

El primer mensaje es una verificación del comando HELO, en este caso indicando que no existe información SPF alguna que coincida con el HELO (lo cual está perfectamente bien). El segundo mensaje es una verificación contra la dirección From, e indica que pasó la verificación y procede de uno de los servidores de envío que el servidor del dominio remitente ha informado que se encuentra habilitado a enviar correo para ese dominio.
Consideraciones:
Existe un bug en las versiones de Bind9 incluidas en Debian por el cual es posible que tengamos mensajes como este en el log:

found SPF/TXT record but no SPF/SPF record found, add matching type SPF record

A partir de 2014 los registros SPF fueron ‘deprecados’ y fueron reemplazados por registros TXT con la información inherente a SPF.
No obstante, habiendo seguido los pasos para configurar el registro SPF en nuestro DNS, el servidor de correo pasará las validaciones.

Configurar OpenDkim

Esto implica configurar el paquete OpenDKIM, anexarlo a Postfix, y agregar un registro al DNS.

El archivo principal de configuración de OpenDKIM /etc/opendkim.conf debe verse así:

# Log to syslog
Syslogyes
# Required to use local socket with MTAs that access the socket as a non-
# privileged user (e.g. Postfix)
UMask002
# OpenDKIM user
# Remember to add user postfix to group opendkim
UserIDopendkim
# Socket smtp://localhost
Socketinet:12301@localhost
# Map domains in From addresses to keys used to sign messages
KeyTable/etc/opendkim/keytable
SigningTablerefile:/etc/opendkim/signingtable
# Hosts to ignore when verifying signatures
ExternalIgnoreListrefile:/etc/opendkim/trustedhosts
InternalHostsrefile:/etc/opendkim/trustedhosts
Selectorcorreo
Canonicalizationrelaxed/simple
Modesv
SubDomainsno
AutoRestartyes
AutoRestartRate10/1M
Backgroundyes
DNSTimeout5
SignatureAlgorithmrsa-sha256
OversignHeadersFrom

Aquí el dato clave es el valor que asignemos al selector.

Debemos asegurarnos que los permisos del archivo se definieron correctamente:

# chmod u=rw,go=r /etc/opendkim.conf

Creamos los directorios donde se alojarán los archivos de datos de OpenDKIM, asignamos la propiedad al usuario opendkim, y restringimos los permisos de archivo:

# mkdir /etc/opendkim
# mkdir /etc/opendkim/keys
# chown -R opendkim:opendkim /etc/opendkim
# chmod go-rw /etc/opendkim/keys

Creamos la tabla de firmas /etc/opendkim/signingtable. Debe contener una línea por cada dominio para el cual gestionamos correo. Y cada una de ellas debería verse así:

*@midominio.edu.ar correo._domainkey.midominio.edu.ar

El archivo signingtable le indica a OpenDKIM como usar tus llaves, que remitentes deberían usar cuales selectores para sus firmas. En el ejemplo anterior, estamos señalando que todos (*) quienes envían correo desde “midominio.edu.ar” deberían usar el selector llamado “correo.” Es importante notar que el comodín * solamente funcionará si la opción SigningTable usa el prefijo refile: antes del nombre de archivo.
Creamos la tabla de llaves /etc/opendkim/keytable. Debe tener una línea por cada dominio en la tabla de firmas. Cada linea debería verse así:

correo._domainkey.midominio.edu.ar midominio.edu.ar:correo:/etc/opendkim/keys/correo.private

El primer campo conecta las tablas signing y key. Vale aclarar que tanto la tabla signing como la tabla key pueden estar tranquilamente en el /etc/opendkim, solo es cuestión de preferencias.
El segundo campo está dividido en 3 secciones separadas por ‘:’.

    • La primera sección es el nombre de dominio para el cual la llave es usada.
    • La segunda sección es el selector usado al buscar registros en el DNS. Fue definido en/etc/opendkim.conf
    • La tercera sección identifica al archivo que contiene la llave para el dominio.

Creamos el archivo de hosts de confianza /etc/opendkim/trustedhosts. Al igual que las tablas, también podría estar en /etc/opendkim. Su contenido debe ser:

127.0.0.1
localhost
170.210.45.130
2800:110:44:6260::130
*.midominio.edu.ar

Generamos las llaves para cada dominio:

# opendkim-genkey -b 2048 -h sha256 -r -s correo -d midominio.edu.ar -v

Esto generará dos archivos, correo.private con la llave y correo.txt con el registro TXT que tendremos que agregar al DNS.
Debemos asegurarnos que el directorio /etc/opendkim/keys solamente sea accesible por el propietario:

# chown -R opendkim:opendkim /etc/opendkim
# chmod -R go-rwx /etc/opendkim/keys

Conectamos el milter a Postfix:

# nano /etc/default/opendkim

Añadimos la siguiente línea, editamos el número de puerto sólo si se utiliza uno personalizado:

SOCKET="inet:12301@localhost"

Verificamos que OpenDKIM se inicia correctamente:

# systemctl restart opendkim

No debería haber mensajes de error, pero si los hay, así comienza la diversión:

# systemctl status -l opendkim

Configurar el DNS

Al igual que SPF, DKIM emplea registros TXT para mantener la información acerca de la llave para cada dominio. Es necesario crear un registro TXT para el host correo._domainkey para cada dominio por el que gestione correo. Su valor puede ser encontrado en el archivo correo.txt para cada dominio. Estos archivos se ven así:

correo._domainkey IN TXT ( "v=DKIM1; k=rsa; "
 "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu5oIUrFDWZK7F4thFxpZa2or6jBEX3cSL6b2TJdPkO5iNn9vHNXhNX31nOefN8FksX94YbLJ8NHcFPbaZTW8R2HthYxRaCyqodxlLHibg8aHdfa+bxKeiI/xABRuAM0WG0JEDSyakMFqIO40ghj/h7DUc/4OXNdeQhrKDTlgf2bd+FjpJ3bNAFcMYa3Oeju33b2Tp+PdtqIwXRZksfuXh7m30kuyavp3Uaso145DRBaJZA55lNxmHWMgMjO+YjNeuR6j4oQqyGwz"
 "PaVcSdOG8Js2mXt+J3Hr+nNmJGxZUUW4Uw5ws08wT9opRgSpn+ThX2d1AgQePpGrWOamC3PdcwIDAQAB" ) ; ----- DKIM key correo for midominio.edu.ar

Copiamos todo y pegamos ese valor en nuestro archivo de zona de Bind. Luego de algunos retoques, debería verse así:

correo._domainkey.midominio.edu.ar. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu5oIUrFDWZK7F4thFxpZa2or6jBEX3cSL6b2TJdPkO5iNn9vHNXhNX31nOefN8FksX94YbLJ8NHcFPbaZTW8R2HthYxRaCyqodxlLHibg8aHdfa+bxKeiI/xABRuAM0WG0JEDSyakMFqIO40ghj/h7DUc/4OXNdeQhrKDTlgf2bd+FjpJ3bNAFcMYa3Oeju33b2Tp+PdtqIwXRZksfuXh7m30kuyavp3Uaso145DRBaJZA55lNxmHWMgMjO+YjNeuR6j4oQqyGwzPaVcSdOG8Js2mXt+J3Hr+nNmJGxZUUW4Uw5ws08wT9opRgSpn+ThX2d1AgQePpGrWOamC3PdcwIDAQAB"

Es necesario repetir esto para cada dominio para el cual gestionemos correo, usando la información del archivo .txt para ese dominio.

Probamos la configuración

Para probar las el correcto firmado y verificación de las llaves usamos:

# opendkim-testkey -d midominio.edu.ar -s correo

Si todo está bien no deberíamos ver ninguna salida. Para tener más información, agregamos -vvv al final del comando. Eso produce una salida detallada. El último mensaje debería ser “key OK”. Justo antes de eso podríamos ver un mensaje “key not secure”. Eso es normal y no es señal de error, se debe a que la DNSSEC no está habilitada en su nombre de dominio. Se trata de un estándar de seguridad para la consulta segura del DNS. La mayoría de los nombres de dominio no tienen habilitada la DNSSEC.

Vinculamos OpenDKIM a Postfix

Definimos el socket correcto para Postfix en /etc/default/opendkim

# Command-line options specified here will override the contents of
# /etc/opendkim.conf. See opendkim(8) for a complete list of options.#DAEMON_OPTS=""
#
# Uncomment to specify an alternate socket
# Note that setting this will override any Socket value in opendkim.conf
#SOCKET="local:/var/run/opendkim/opendkim.sock" # default
#SOCKET="inet:54321" # listen on all interfaces on port 54321
#SOCKET="inet:12345@localhost" # listen on loopback on port 12345
#SOCKET="inet:12345@192.0.2.1" # listen on 192.0.2.1 on port 12345
SOCKET="inet:8891@localhost"

Editamos /etc/postfix/main.cf y agregamos una sección para activar el procesamiento de correo a través del demonio OpenDKIM:

# OpenDKIM
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:8891
non_smtpd_milters = $smtpd_milters

Consideraciones:
El formato del smtpd:milter (inet:localhost:8891) difiere de la configuración de OpenDKIM (inet:8891@localhost). Invertir el orden host / puerto en uno u otro puede acarrear varias horas de diversión.
La línea lógica que define la configuración de OpenDKIM en Postfix no puede estar identada, es decir que cada línea de configuración debe comenzar en la columna cero.
Si bien podemos colocar la configuración relativa a postfix en cualquier lugar del archivo. Lo usual es hacerlo a continuación de la entrada
smtpd_recipient_restrictions.
Reiniciamos el demonio OpenDKIM de modo que defina el socket correcto para Postfix:

# systemctl restart opendkim

Reiniciamos Postfix para que comience a utilizar OpenDKIM al procesar correo:

# systemctl restart postfix

Verificando que todo funciona

Existen varios servicios en línea para verificar la configuración de nuestro sistema de correo, pero una de las maneras más sencillas de hacerlo es enviar un mensaje a una dirección @gmail.com. En esa cuenta de GMail abrimos el correo enviado y le indicamos “Mostrar original”, veremos algo como esto:

ID del mensaje <af03eed8efab9c95ab3fc22fbff9d1d9@midominio.edu.ar>
Creado el: 8 de septiembre de 2017, 15:07 (Entregado después de 5 segundos)
De: drodriguez@midominio.edu.ar
Para: drodriguez@unau.edu.ar
Asunto: isso é só uma prova
SPF: PASS con el IP 170.210.45.133 Más información
DKIM: PASS con el dominio midominio.edu.ar Más información
DMARC: PASS Más información

 

Configurar OpenDKIM para múltiples dominios

Para hacerlo debes añadir los demás dominios en los archivos signingtable, keytable y trustedhosts.
A continuación, genera las claves DKIM privada/pública y añade la clave pública DKIM en el DNS para los otros dominios. Reinicia OpenDKIM y ya está.

Opcional: Configurar ADSP (Set up Author Domain Signing Practices)

Como ítem final, podemos agregar una política ADSP a nuestro dominio indicando que todos los correos deben contar con una firma DKIM. Como siempre, lo hacemos agregando un registro TXT:

_adsp._domainkey.midominio.edu.ar.IN TXT "dkim=all;"

Esto no es necesario, pero hacerlo dificulta que cualquiera pueda hacer pasar un correo como de nuestro dominio porque los servidores de destino verán la ausencia de la firma DKIM y rechazarán el mensaje.

Configurar DMARC (Domain Message Authentication, Reporting & Conformance)

El registro DNS DMARC puede ser agregado para indicar a los servidores de correo que pensamos deben hacer cuando mensajes, alegando ser de nuestro dominio, fallan la validación con SPF y/o DKIM. DMARC solo debería ser definido si tenemos SPF y DKIM configurados y funcionando adecuadamente. Si agregamos el registro DMARC sin tener SPF y DKIM en su lugar, los mensajes de nuestro dominio fallarán la validación lo cual causará que sean descartados o relegados a la carpeta de spam.
El registro DMARC es un registro TXT para el host _dmarc en nuestro dominio conteniendo los siguientes valores recomendados:

v=DMARC1;p=reject;sp=none;adkim=r;aspf=r

Esto solicita a los servidores de correo que coloquen en cuarentena cualquier mensaje que falle las verificaciones SPF o DKIM. No se solicita informe. Si bien muy pocos servidores implementan el software para generar informes sobren mensajes fallidos, podría ser innecesario solicitarlos. Pero como nunca sabemos lo que nos puede deparar el futuro, agregamos los parámetros necesarios:

_dmarc.midominio.edu.ar.IN TXT "v=DMARC1;p=reject;sp=none;pct=100;ruf=mailto:administrador@midominio.edu.ar;rua=mailto:administrador@midominio.edu.ar"

Control de SPAM

El filtro de spam se hace en dos etapas:

  1. El spam es identificado al ingreso al sistema.
  2. El spam es entregado en una carpeta dedicada en la cuenta del usuario.

Estas etapas son cosas separadas. Spamassassin identifica y etiqueta al spam mientras que el plugin Sieve de Dovecot permite colocarlo automáticamente en la carpeta spam del usuario. Primero identificaremos el spam.

Verificar la aceptación de correo

Agregamos un nuevo conjunto de verificaciones a /etc/postfix/main.cf para reducir la cantidad de correo que acepta el sistema

### Para descartar correo mal formado
smtpd_helo_required = yes
strict_rfc821_envelopes = yes
disable_vrfy_command = yes
unknown_address_reject_code = 554
unknown_hostname_reject_code = 554
unknown_client_reject_code = 554
smtpd_helo_restrictions =
 permit_mynetworks,
 reject_invalid_hostname,
## Al modificar sender_checks, el archivo debe ser regenerado
## usando postmap <archivo>, para generar una Berkeley DB
 regexp:/etc/postfix/helo.regexp,
 permit
smtpd_recipient_restrictions =
 check_client_access hash:/etc/postfix/helo_client_exceptions,
 check_sender_access hash:/etc/postfix/sender_checks,
 reject_invalid_hostname,
## Puede provocar problemas con Auth SMTP
 reject_non_fqdn_hostname,
##################################
 reject_non_fqdn_sender,
 reject_non_fqdn_recipient,
 reject_unknown_sender_domain,
 reject_unknown_recipient_domain,
 permit_mynetworks,
 reject_unauth_destination,
## Agregamos excepciones RBL, al hacer cambios el archivo debe ser regenerado usando
## postmap <archivo>, para generar una Berkeley DB
 check_client_access hash:/etc/postfix/rbl_client_exceptions,
 reject_rbl_client cbl.abuseat.org,
 reject_rbl_client sbl-xbl.spamhaus.org,
 reject_rbl_client bl.spamcop.net,
 reject_rhsbl_sender dsn.rfc-ignorant.org
 permit

Ahora necesitamos crear dos archivos:
El primero /etc/postfix/helo.regexp que contendrá:

/^subdominio\.host\.com$/ 550 No uses mi nombre de host
/^xxx\.yyy\.zzz\.xxx$/ 550 No uses mi dirección IP
/^\[xxx\.yyy\.zzz\.xxx\]$/ 550 No uses mi dirección IP
/^[0-9.]+$/ 550 Tu software no cumple con RFC 2821
/^[0-9]+(\.[0-9]+){3}$/ 550 Tu software no cumple con RFC 2821

Esto por sí solo hará que los spammers que intentan enviar el comando helo y hacerse pasar por el servidor que recibe el correo por IP o por nombre de host, así como rechazar algunos de los correos que no cumplen con la RFC 2821.
Luego necesitamos crear /etc/postfix/helo_client_exceptions

# Estas direcciones IP pueden evitar los controles fqdn
# Algún comentario para identificar el IP de abajo
www.xxx.yyy.zzz OK

Este archivo es necesario en caso un servidor de correo que se comporta mal no puede enviar el helo correcto y tienes que permitir que se acepte el correo de esa fuente. Cosas como dispositivos independientes, cámaras de CCTV son pobres en el cumplimiento de las normas, por lo que podría tener que hacer una excepción para esto.
Antes de que cualquier cambio en este archivo sea utilizable, hay que ejecutar

# postmap /etc/postfix/helo_client_exceptions

Esto creará un archivo llamado /etc/postfix/helo_client_exceptions.db
Más adelante tenemos /etc/postfix/sender_checks que permite evitar varios controles FQDN y habilitar un remitente determinado. Esto resulta particularmente útil cuando si una empresa tiene un midominio.edu.ar para trabajar pero el correo funcionar en interno.midominio.edu.ar y no hay configuración DNS para interno.midominio.edu.ar, estos es genial para la seguridad pero los DNS externos desconocen la existencia de tal estructura interna y, a consecuencia de ello, postfix rechazará interno.midominio.edu.ar.

usuario@midominio.edu.ar REJECT
usuario@interno.midominio.edu.ar OK

Una vez modificado el archivo es necesario crear una Berkely DB usando:

# postmap /etc/postfix/sender_checks

Luego tenemos las verificaciones RBL. Existen muchos sitios dedicados a ello (en el ejemplo hay 4) que brindan listas actualizadas constantemente con IPs y nombres de host que los spammers utilizan para enviar correo. Cada IP que intenta enviar correo a nuestro servidor de correo será verificado contra esas listas y si la IP no está listada en las RBLs, el servidor aceptará el correo. Eventualmente los servidores pueden aparecer listados y removerlos puede demorar 24 horas luego de un brote de spam de modo que siempre es bueno contar con una manera de evitar los controles.
Para hacerlo creamos un archivo llamado /etc/postfix/rbl_client_exceptions

## Algún comentario
www.xxx.yyy.zzz OK

Una vez más será necesario generar la Berkeley DB

postmap /etc/postfix/rbl_client_exceptions

Instalar Spamassassin

# apt-get install spamassassin spamc

Creamos un usuario para spamc. Se trata de la mitad cliente de la pareja spamc/spamd. Debería ser usado en lugar de “spamassassin” en scripts para procesar el correo. Leerá el correo desde STDIN, y lo pondrá en la cola de su conexión a spamd, luego leer el resultado y lo imprime a STDOUT. Spamc tiene un impacto muy bajo en el rendimiento, por lo que debería ser mucho más rápida su carga comparado con el programa spamassassin completo.”

# adduser spamd --disabled-login

Basta con presionar enter ante cada pregunta.
Habilitamos el inicio de Spamassassin en cada arranque:

# systemctl enable spamassassin.service

Editamos /etc/default/spamassassin

OPTIONS="--create-prefs --max-children 5 --username spamd --helper-home-dir /home/spamd/ -s /home/spamd/spamd.log"
# Habilita la actualización automática de las reglas de Spamassassin cada noche.
CRON=1

Luego editamos /etc/spamassassin/local.cf para establecer las reglas de SPAM:

rewrite_header Subject ***** SPAM _SCORE_ *****
# Muestra el mensaje spam original en lugar de un mensaje
# que contenga al correo con spam como adjunto.
report_safe 0
required_score 5.0
use_bayes 1
bayes_auto_learn 1
skip_rbl_checks 0
use_dcc 0
use_pyzor 0

Iniciamos el filtro de spam:

# systemctl start spamassassin

Le indicamos a Postfix que tenemos activo un filtro de contenido. En
/etc/postfix/master.cf
encontrar la linea

smtp inet n - - - - smtpd

y directamente debajo agregamos:

 -o content_filter=spamassassin

En este caso la linea que comienza con -o debe tener uno o más espacios en blanco al comienzo. De no ser así, al recargar la configuración Postfix ‘dirá’: “/usr/sbin/postconf: fatal: invalid type field”. Nuevamente, incontables horas de diversión.
Ya que postfix enviará el recipiente a spamc, necesitamos indicarle a postfix que entregue el correo a cada usuario de separadamente. Agregamos la siguiente linea a /etc/postfix/main.cf

spamassassin_destination_recipient_limit = 1

Necesitamos indicar a Postfix que encamine el correo a spamd. Para ello, al final de
/etc/postfix/master.cf
agregamos:

spamassassin unix - n n - - pipe
 user=spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}

Nuevamente hay que tener en cuenta el espacio al comienzo de la segunda linea.

# systemctl restart spamassassin
# postfix reload

En este punto es necesario enviar un correo de prueba hacia y desde nuestra cuenta en Roundcube para cerciorarnos que aún funciona.
Si no fuera así, removemos las últimas entradas de /etc/postfix/master.cf, reiniciamos Postfix e intentamos nuevamente. Verificamos no haber ingresado algo mal y que al reiniciar Postfix no arroja ningún error. Solamente vamos a continuar si el envío y la recepción funcionan.

Probando el filtro de spam

Enviamos un correo a nuestro recipiente con el GTUBE. Es el EICAR para los filtros de spam: es una cadena especial de caracteres que los filtros de spam reconocen como tal para propósito de pruebas. Más en: http://spamassassin.apache.org/gtube/
Así que enviamos un correo con esta cadena en el cuerpo del mensaje:

XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X

Al ingresar a Roundcube el mensaje debería estar etiquetado como *****SPAM*****. Un mensaje sin esta cadena no debería contener esa alerta.
Abrimos el mensaje etiquetado como *****SPAM***** y vamos a “Mostrar código”.
Deberíamos ver algo así:

X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on servidor
X-Spam-Flag: YES
X-Spam-Level: **************************************************
X-Spam-Status: Yes, score=1001.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID,
DKIM_VALID_AU,FREEMAIL_FROM,GTUBE,PYZOR_CHECK,RCVD_IN_MSPIKE_H2,
SPF_PASS autolearn=no autolearn_force=no version=3.4.2
X-Spam-Report:
* 1000 GTUBE BODY: Generic Test for Unsolicited Bulk Email

Mover automáticamente el spam a la carpeta Basura

Esto es en realidad parte de algo más grande, llamado sistema de filtrado de correo. Usando filtros (también llamados reglas) podemos aplicar acciones a correo usando lógica, por ejemplo mover correo que está etiquetado como spam a la carpeta Basura.

Suscribir automáticamente usuarios a las carpetas especiales IMAP

En primer lugar necesitamos asegurarnos que el cliente IMAP está suscripto a la carpeta a la que el spam será movido.
Al abrir Roundcube vemos que solo existen dos carpetas: Entrada y Enviados. Apuntamos a subscribir automáticamente los usuarios a varias carpetas IMAP especiales de modo que siempre estén allí. En /etc/dovecot/dovecot.conf agregamos:

namespace inbox {
 mailbox Drafts {
 special_use = \Drafts
 auto = subscribe
 }
 mailbox Junk {
 special_use = \Junk
 auto = subscribe
 }
 mailbox Trash {
 special_use = \Trash
 auto = subscribe
 }
 #mailbox Archive {
 # special_use = \Archive
 # auto = subscribe
 }
 mailbox Sent {
 special_use = \Sent
 auto = subscribe
 }
 #mailbox "Sent Messages" {
 # special_use = \Sent
 #}
}

A las carpetas comentadas Roundcube no las reconoce, pero puede ser que algún otro MUA sí lo haga.
Luego

# dovecot reload

y volvemos a entrar a Roundcube ya que las carpetas especiales son creadas al ingresar.

Sieve

Dovecot cuenta con un plugin llamado Managesieve que permite definir reglas de filtrado en el servidor IMAP, de modo que todos los clientes veran lo mismo independientemente de la plataforma.
Para habilitarlo, en /etc/dovecot/dovecot.conf agregamos:

protocol lmtp {
 mail_plugins = $mail_plugins sieve
 postmaster_address = administrador@midominio.edu.ar
}
plugin {
 sieve = file:~/sieve;active=~/.dovecot.sieve
}

Luego reiniciamos dovecot

# systemctl restart dovecot

Probamos la conexión

# telnet localhost 4190

Deberíamos obtener algo así

Connected to localhost.
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"
"VERSION" "1.0"
OK "Dovecot ready."

lo cual significa que Sieve está funcionando. Hay que presionar Enter tres veces para salir.
Si surgen inconvenientes, es necesario verificar la configuración, reiniciar Dovecot y volver a intentar.

# doveconf -n

puede ayudar a comprobar errores de tipeo y cosas por el estilo.
Es posible crear reglas sieve predeterminadas. Esto tiene una enorme contra: tan pronto como el usuario crea sus propias reglas (por ejemplo, define una respuesta automática para cuando no está en la oficina) las reglas predeterminadas ya no son tenidas en cuenta aún luego de eliminar la regla personal.

Definir regla de spam de manera global

Vamos a definir una regla de spam global que moverá el spam automáticamente a la carpeta Basura del usuario.

sieve_default = /etc/dovecot/sieve/spamfilter.sieve

Esta carpeta y archivo son arbitrarios pero me parecieron lógicos.
Creamos la carpeta:

# mkdir /etc/dovecot/sieve

Cambiamos permisos ya que de no hacerlo dovecot se va a quejar.

# chown dovecot:dovecot /etc/dovecot/sieve/ -R

En /etc/dovecot/sieve/spamfilter.sieve

require ["fileinto"];
if header :contains "X-Spam-Flag" "YES" {
 fileinto "Junk";
}

Esta regla verifica un encabezado llamado ‘X-Spam-Flag’. Si contiene YES el mensaje es almacenado en la carpeta Basura.
Recargamos Dovecot y enviamos un mensaje con la cadena GTUBE para verificar si funciona.

Eliminar spam automáticamente luego de 30 días

Usando doveadm podemos eliminar automáticamente todo el correo en la carpeta Basura más antiguo que cierto tiempo, por ejemplo 30 días.
Doveadm es es la utilidad de administración de Dovecot. Con man doveadm se puede consulta por mayor información sobre la utilidad. Otra lectura relevante para este caso: man doveadm-search y man doveadm-search-query.
Digamos que queremos buscar todos los documentos en todas las bandejas de entrada de más de cuatro horas de antigüedad:

# doveadm search -A mailbox Inbox savedbefore 4h
administrador@midominio.edu.ar 74b4db2757f9f05661350000595b2a1f 1
administrador@midominio.edu.ar 74b4db2757f9f05661350000595b2a1f 2

-A significa revisar todas las casillas, no solo la especificada.
No queremos buscar solo la Bandeja de entrada y queremos correo de más de 30 días:

# doveadm search -A mailbox Junk savedbefore 30d
administrador@midominio.edu.ar 4adeeb2ca5c1ca565c3b000038e0142a 1
administrador@midominio.edu.ar 4adeeb2ca5c1ca565c3b000038e0142a 2
administrador@midominio.edu.ar 4adeeb2ca5c1ca565c3b000038e0142a 3

Para más información sobre el formato de consulta.

$ man doveadm-search-query

Pero no queremos buscar solamente sino eliminar esos correos. (Usamos search primero para verificar que obtenemos los resultados que estábamos esperando.)

# doveadm expunge -A mailbox Junk savedbefore 30d

Como seguramente no vamos a querer correr esto manualmente todos los días. Lo programamos:

# crontab -e

Agregamos esta línea:

@hourly /usr/bin/doveadm expunge -A mailbox Junk savedbefore 30d

En caso que no querramos recibir un aviso por correo sobre la salida de esta programación la cambiamos a

@hourly /usr/bin/doveadm expunge -A mailbox Junk savedbefore 30d > /dev/null 2>&1

Lo anterior ejecutará el comando cada hora. Cambiarlo a

@daily /usr/bin/doveadm expunge -A mailbox Junk savedbefore 30d > /dev/null 2>&1

hará que se ejecute cada día
Postfix puede generar hasta 100 procesos de servidor SMTP para manejar las conexiones de clientes SMTP. Se puede comprobar el límite de procesos ejecutando el siguiente comando.

# postconf default_process_limit
default_process_limit = 150

Si hay spambots intentando acceder constantemente al servidor, habrá menos procesos de Postfix para aceptar mensajes de correo legítimos. Y cuando el número de clientes SMTP excede el número de procesos del servidor Postfix, otros clientes SMTP deben esperar hasta que un proceso del servidor esté disponible.

Al bloquear los spambots con Postscreen, podemos reservar los procesos del servidor para los clientes SMTP legítimos. Postscreen está diseñado como una primera capa de defensa contra los spammers. Está implementado como un único proceso que escucha en el puerto 25 y puede manejar múltiples conexiones SMTP entrantes.

Medidas utilizadas por Postscreen contra los spambots

La mayoría de los spambots tienen una implementación defectuosa del protocolo SMTP. Postscreen puede aprovechar este hecho y utilizar varias medidas para bloquearlos.

  • Prueba de saludo previo. Si el cliente SMTP habla antes de su turno, detiene la conexión.
  • Comprobación de la lista negra en tiempo real. Si la dirección IP del cliente está en una lista negra, como la de Spamhaus, interrumpe la conexión.
  • Prueba profunda de protocolo.

Paso 1: Habilitar Postscreen en Postfix

Postscreen se introdujo por primera vez en Postfix 2.8. Si estás usando cualquier distribución de Linux actual, deberías tener Postfix 3.0 o superior. Para comprobar la versión de Postfix, ejecutar

# postconf mail_version
mail_version = 3.3.0

Edite el archivo de configuración master de Postfix.

nano /etc/postfix/master.cf

Comentar la siguiente línea

smtp inet n - y - - smtpd

Luego descomentar las siguientes 4 líneas

smtp inet n - y - 1 postscreen
smtpd pass - - y - - smtpd
dnsblog unix - - y - 0 dnsblog
tlsproxy unix - - y - 0 tlsproxy

Donde:

  • Las dos primeras líneas activan Postscreen. Tanto Postscreen como el demonio smtpd escucharán en el puerto 25. Postscreen comprobará primero el cliente SMTP y luego pasará la conexión al demonio smtpd.
  • El servicio dnsblog (DNS Blacklist Logger) permite registrar las comprobaciones de la lista negra de DNS.
  • El servicio tlsproxy habilita el soporte de STARTTLS para postscreen, por lo que los clientes SMTP remotos pueden establecer una conexión encriptada cuando Postscreen está habilitado.

Guardar y cerrar el archivo.

Crear una lista blanca/negra permanente

Editar el archivo de configuración main de Postfix.

nano /etc/postfix/main.cf

Necesitamos añadir nuestras propias direcciones IP a la lista blanca de Postscreen para que nuestras propias peticiones SMTP no sean comprobadas por Postscreen (prueba de saludo previo, comprobación de la lista negra, test de protocolo profundo, etc). Añadir las siguientes dos líneas al final del archivo.

postscreen_access_list = permit_mynetworks cidr:/etc/postfix/postscreen_access.cidr
postscreen_blacklist_action = drop

Guardar y cerrar el archivo. El valor permit_mynetworks pondrá en la lista blanca cualquier dirección IP listada en el parámetro mynetworks.

También se pueden añadir manualmente direcciones IP adicionales en el archivo /etc/postfix/postscreen_access.cidr.

nano /etc/postfix/postscreen_access.cidr

Es posible que necesitemos poner en la lista blanca la dirección IPv4 e IPv6 pública del servidor de correo. Así que agregamos las siguientes líneas en el archivo. Tener en cuenta que se debe utilizar la notación CIDR: Para una única dirección IPv4, añadir /32 al final; Para una única dirección IPv6, añadir /128 al final.

#permitir mis propias direcciones IP.
179.0.132.51/32 permit
2800:110:5::66/128 permit

Para poner una dirección IP en la lista negra de forma permanente

12.34.56.78/32 reject

Guardar y cerrar el archivo. Reiniciar Postfix para que los cambios surtan efecto.

systemctl restart postfix

Nota: Postscreen escucha en el puerto 25 solamente, así que los usuarios autenticados del puerto 587 o 465 no serán afectados por Postscreen.

El propio Postscreen también mantiene una lista blanca dinámica para minimizar el retraso de los correos legítimos, definida por el parámetro postscreen_cache_map.

# postconf postscreen_cache_map
postscreen_cache_map = btree:$directory/postscreen_cache

Cada dirección IP de la lista blanca dinámica tiene un tiempo de vida.

Paso 2: Prueba de saludo previo

Hay una prueba de saludo previo en Postscreen para detectar el spam. En el protocolo SMTP, el servidor SMTP receptor debe declarar siempre su nombre de host antes de que lo haga el servidor SMTP emisor. Algunos spammers violan esta regla y declaran sus nombres de host antes de que lo haga el servidor SMTP receptor.

Postscreen habilita la prueba de saludo previo de manera predeterminada, pero no hará nada con el resultado de la prueba. Como se puede ver en las siguientes líneas de log de ejemplo, el texto “PREGREET” indica que el cliente SMTP declaró su nombre de host primero, pero Postscreen igualmente pasó la conexión al demonio smtpd de Postfix.

mail postfix/postscreen[24075]: CONNECT from [156.96.118.171]:62604 to [23.254.225.226]:25
mail postfix/postscreen[24075]: PREGREET 11 after 0.07 from [156.96.118.171]:62604: EHLO User\r\n
mail postfix/smtpd[24076]: connect from unknown[156.96.118.171]
mail postfix/smtpd[24076]: disconnect from unknown[156.96.118.171] ehlo=1 quit=1 commands=2

Para rechazar clientes SMTP que violan esta regla, editar el archivo main de configuración de Postfix.

/etc/postfix/main.cf

Agregar la siguiente linea al final.

postscreen_greet_action = enforce

Guardar y cerrar el archivo. Luego reiniciar Postfix.

systemctl restart postfix

}

A partir de ahora, Postscreen detendrá la conexión si un cliente SMTP viola esta regla. Como se puede ver en el siguiente registro, Postscreen detuvo la conexión, por lo que el spammer no tiene la oportunidad de acosar al demonio smtpd.

mail postfix/postscreen[6471]: CONNECT from [192.241.239.123]:48014 to [23.254.225.226]:25
mail postfix/postscreen[6471]: PREGREET 19 after 0 from [192.241.239.123]:48014: EHLO zg-0131a-136\r\n
mail postfix/postscreen[6471]: DISCONNECT [192.241.239.123]:48014

Postscreen sigue permitiendo que se completen otras pruebas antes de detener la conexión. Para interrumpir la conexión inmediatamente sin realizar otras pruebas, utilizar la siguiente configuración en su lugar.

postscreen_greet_action = drop

Paso 3: Uso de listas negras y blancas públicas

El parámetro postscreen_dnsbl_sites puede ser utilizado para comprobar la dirección IP del cliente SMTP contra las listas negras públicas (DNSBL). Es posible que ya esté utilizando el reject_rbl_client de Postfix smtpd para rechazar un cliente SMTP si su dirección IP está en una lista negra pública. Sin embargo, eso puede causar falsos positivos porque la dirección IP de un servidor SMTP inocente podría estar en una lista negra por cualquier razón, incluso si usas permit_dnswl_client para verificar también contra la lista blanca pública (DNSWL).

Para reducir los falsos positivos, Postscreen le permite comprobar múltiples listas negras y añadir un factor de peso a cada lista negra. Por ejemplo, si una dirección IP está en la lista negra de Spamhaus, añade 3 puntos; si una dirección IP está en la lista negra de BarracudaCentral, añade 2 puntos. Si la puntuación combinada es lo suficientemente alta (definida por postscreen_dnsbl_threshold), rechaza el cliente SMTP. Este sistema de puntuación es similar al de SpamAssassin.

En la siguiente configuración, fijamos el umbral en 3 puntos. Spamhaus tiene un peso de 3. BarracudaCentral tiene un peso de 2. SpamCop tiene un peso de 1. Si la puntuación combinada es igual o mayor que 3, Postscreen rechazaría el cliente SMTP.

postscreen_dnsbl_threshold = 3
postscreen_dnsbl_action = enforce
postscreen_dnsbl_sites =
        zen.spamhaus.org*3
        b.barracudacentral.org=127.0.0.[2..11]*2
        bl.spameatingmonkey.net*2
        bl.spamcop.net
        dnsbl.sorbs.net

También se puede usar postscreen_dnsbl_sites para verificar la dirección IP del cliente SMTP contra la lista blanca pública (DNSWL). Si la dirección IP del cliente está en la lista blanca, agregar puntaje negativo.

postscreen_dnsbl_sites =
        zen.spamhaus.org*3
        b.barracudacentral.org=127.0.0.[2..11]*2
        bl.spameatingmonkey.net*2
        bl.spamcop.net
        dnsbl.sorbs.net
       swl.spamhaus.org*-4,
       list.dnswl.org=127.[0..255].[0..255].0*-2,
       list.dnswl.org=127.[0..255].[0..255].1*-4,
       list.dnswl.org=127.[0..255].[0..255].[2..3]*-6

Si utiliza el parámetro reject_rbl_client o permit_dnswl_client de Postfix smtpd, se debería eliminarlos, para que el demonio smtpd no realice comprobaciones de IP de nuevo después de Postscreen. Postscreen no comprueba el nombre de dominio basado en la lista negra/blanca, por lo que deberíamos seguir utilizando reject_rhsbl para realizar la búsqueda de nombres de dominio en las listas negras públicas.

smtpd_recipient_restrictions =
     permit_mynetworks,
     permit_sasl_authenticated,
     ...
     ...
     reject_rhsbl_helo dbl.spamhaus.org,
     reject_rhsbl_reverse_client dbl.spamhaus.org,
     reject_rhsbl_sender dbl.spamhaus.org,

Guardar y cerrar el archivo de configuración main de Postfix. Luego reiniciar Postfix para que los cambios surtan efecto.

systemctl restart postfix

Nota: Si ve el siguiente mensaje en su registro de correo, significa que la dirección IP del cliente SMTP no está en la lista blanca (list.dnswl.org). Esto no es un error.

warning: dnsblog_query: lookup error for DNS query 179.0.132.51.list.dnswl.org: Host or domain name not found. Name service error for name=179.0.132.51.list.dnswl.org type=A: Host not found, try again

Si está en la lista blanca, el mensaje será como este:

postfix/dnsblog[21188]: addr xx.xx.xx.xx listed by domain list.dnswl.org as 127.0.10.0

Si una dirección IP aparece como 127.0.0.255 en list.dnswl.org, como en el siguiente mensaje, significa que ha alcanzado el límite de consulta. Se eberá ejecutar un DNS local propio.

postfix/dnsblog[11951]: addr 202.66.174.152 listed by domain list.dnswl.org as 127.0.0.255

Es necesario tener en cuenta también que BarracudaCentral Blocklist requiere un registro, que es gratuito. Después de crear una cuenta, simplemente hay que añadir la dirección IP del DNS y ya está.

Utilizar DNS local propio

Debemos tener en cuenta que se debe configurar un DNS local cuando se utilicen listas negras y blancas públicas, porque la mayoría de ellas tienen un límite de consultas. Si se emplea un DNS público como 8.8.8.8, es probable que se alcance el límite de consulta antes de lo pensado.

Algunos sitios DNSBL muertos o cerrados

No se debe utilizar sitios DNSBL muertos o cerrados, o el servidor de correo rechazará correos legítimos.

dnsbl.njabl.org: está desactivado desde 2013.
dnsbl.ahbl.org: el acceso público a la lista finalizó en 2015.

Paso 4: Habilitar las pruebas de protocolo profundo

Hay 3 pruebas profundas de protocolo comunes en Postscreen:

  • Prueba de canalización SMTP
  • Prueba de comandos no SMTP
  • Prueba de línea nueva vacía

La canalización es una extensión del protocolo SMTP. Permite al cliente SMTP enviar múltiples comandos SMTP a la vez sin esperar la respuesta del servidor SMTP. Postfix los soporta de manera predeterminada. Para comprobarlo, se puede utilizar telnet para conectar al servidor de correo.

telnet correo.midominio.edu.ar 25

A continuación, utilizar el comando EHLO para declarar el nombre de host.

EHLO mail.google.com

La respuesta del servidor SMTP que aparece a continuación indica que admite la canalización.

250-PIPELINING
250-SIZE 157286400
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

Luego cerrar la conexión.

quit

Algunos spammers utilizan la canalización de comandos para emitir varios comandos RCPT TO: a la vez, con el fin de enviar spam a varios destinatarios en una sesión SMTP. Si el servidor SMTP no anuncia el soporte de canalización, entonces el cliente SMTP no debería emitir múltiples comandos a la vez.

Agregar las siguientes dos líneas en el archivo /etc/postfix/main.cf para habilitar la prueba de canalización y rechazar a los clientes SMTP que fallen esta prueba.

postscreen_pipelining_enable = yes
postscreen_pipelining_action = enforce

Como el nombre sugiere, la prueba de comandos no SMTP hace que Postscreen detecte clientes SMTP que envían comandos no SMTP. Agregar las siguientes dos líneas en el archivo /etc/postfix/main.cf para rechazar tales clientes SMTP.

postscreen_non_smtp_command_enable = yes
postscreen_non_smtp_command_action = enforce

Un problema de vieja data para los administradores de sistemas, debido al diferente soporte de los distintos sistemas operativos, es la diferencia entre los retornos de carro y los saltos de línea, conocidos como y , respectivamente, en SMTP.

La prueba de nuevas líneas limpias permite a Postscreen detectar clientes SMTP que terminan una línea con , en lugar del estándar . Agregar las siguientes dos líneas en el archivo /etc/postfix/main.cf para rechazar tales clientes SMTP.

postscreen_bare_newline_enable = yes 
postscreen_bare_newline_action = enforce

Guardar y cerrar el archivo. A continuación, reiniciar Postfix para que los cambios surtan efecto.

systemctl restart postfix

El efecto de greylisting de las pruebas de protocolo profundas

La limitación de las pruebas de protocolo profundas es que Postscreen desconectaría a los nuevos clientes SMTP sin importar si las pruebas se superan o no. Postscreen desconecta cada cliente con el siguiente mensaje:

450 4.3.2 Service currently unavailable

Y el cliente debe volver a intentarlo más tarde desde la misma dirección IP. Esto es efectivamente una forma de greylisting, por lo que se necesita desactivar otras formas de greylisting. Por ejemplo, si se usa Postgrey como servidor de política de greylisting, entonces en el archivo /etc/postfix/main.cf hay que comentar la línea

check_policy_service inet:127.0.0.1:10023,

Guardar y cerrar el archivo. Luego reiniciar Postfix.

systemctl restart postfix

Cómo minimizar la mala experiencia del usuario

Las listas grises son bastante molestas para el usuario final, ya que éste tiene que esperar varios minutos más para que le llegue el correo electrónico. Para minimizar esta mala experiencia, hay 3 formas posibles cuando se utilizan las pruebas de protocolo profundo de Postscreen.

  • Crear un segundo registro MX que apunte a la misma dirección IP.
  • Si la dirección IP de un cliente SMTP está en una lista blanca pública, omitir las pruebas profundas de protocolo.
  • Utilizar Postwhite para añadir direcciones IP buenas y conocidas a la lista blanca de Postscreen.
Crear un segundo registro MX que apunte a la misma dirección IP

Se puede especificar más de un registro MX para el nombre de dominio como se indica a continuación.

Registro   Nombre    Servidor de Correo        Prioridad

MX           @       correo.midominio.edu.ar    0
MX           @       correo.midominio.edu.ar    5

El remitente intentará el primer servidor de correo (con prioridad 0). Si correo.midominio.edu.ar rechaza el correo por greylisting, entonces el remitente intentará inmediatamente el segundo servidor de correo (con prioridad 5).

El greylisting en Postscreen no tiene un tiempo de retraso como en Postgrey. Si los dos nombres de host del servidor de correo tienen la misma dirección IP, entonces cuando el remitente intente el segundo, el correo electrónico será aceptado inmediatamente (si todas las demás comprobaciones pasan) y los usuarios finales no notarán el retraso del correo electrónico causado por la lista gris.

Tener en cuenta que no todos los servidores de correo intentarán inmediatamente el segundo host MX. Algunos, como Gmail, usarán una dirección IP diferente para intentarlo de nuevo, que por supuesto será rechazada de nuevo. Postfix intentaría el segundo host MX.

Omitir pruebas de protocolo profundas si la dirección IP de un cliente SMTP está en una lista blanca pública

Gmail nunca volverá a intentar enviar un correo electrónico desde la misma dirección IP. Sin embargo, la dirección IP de Gmail está en list.dnswl.org. Podemos decirle a Postscreen que ignore a estos clientes SMTP. Añadir la siguiente línea en el archivo /etc/postfix/main.cf para ignorar a los clientes cuya puntuación sea igual a -2 o inferior.

postscreen_dnsbl_whitelist_threshold = -2

Reiniciar Postfix para que los cambios surtan efecto.

systemctl restart postfix

El siguiente mensaje del log de correo indica que Postscreen no realizó pruebas de protocolo profundas y pasó la conexión al demonio smtpd porque la dirección IP de Gmail está en la lista blanca pública.


Feb 10 10:31:14 mail postfix/postscreen[16579]: CONNECT from [209.85.166.44]:38543 to [23.254.225.226]:25
Feb 10 10:31:14 mail postfix/dnsblog[16582]: addr 209.85.166.44 listed by domain list.dnswl.org as 127.0.5.0
Feb 10 10:31:15 mail postfix/postscreen[16579]: PASS NEW [209.85.166.44]:38543
Feb 10 10:31:15 mail postfix/smtpd[16639]: connect from mail-io1-f44.google.com[209.85.166.44]

De hecho, la mayoría de los principales proveedores de correo (Gmail, Hotmail/Outlook, Yahoo Mail, GMX Mail, ProtonMail, etc) están en la lista blanca de list.dnswl.org. También incluye servidores de correo de otros sectores, como puede verse en dnswl.org.

Así que el uso de postscreen_dnsbl_whitelist_threshold ayudará a omitir el greylisting la mayor parte del tiempo.

Uso de Postwhite

Postwhite es un script escrito por Steve Jenkins para generar automáticamente una lista blanca de IPs estáticas para Postscreen utilizando los registros SPF publicados de webmailers conocidos, redes sociales, proveedores de comercio electrónico y remitentes masivos que cumplen con los requisitos. De debe teern en cuenta que esta lista blanca hace que Postscreen omita todas las pruebas (prueba de saludo previo, comprobación de lista negra/lista blanca pública, pruebas de protocolo profundas) para las direcciones IP de la lista blanca, por lo que ayudará a reducir la carga de Postscreen y las solicitudes de DNS a las listas negras/listas blancas públicas.

Para usar Postwhite, primero ir a /usr/local/bin/.

cd /usr/local/bin/

Instalar git.

apt install git

Clonar los repositorios SPF-Tools y Postwhite de Github.

git clone https://github.com/spf-tools/spf-tools.git
git clone https://github.com/stevejenkins/postwhite.git

Copiar el archivo postwhite.conf a /etc/.

cp /usr/local/bin/postwhite/postwhite.conf /etc/

Ejecutar Postwhite.

/usr/local/bin/postwhite/postwhite

La lista blanca ser guarda como /etc/postfix/postscreen_spf_whitelist.cidr. Editar el main.cf de Postfix.

/etc/postfix/main.cf

En la linea

postscreen_access_list = permit_mynetworks cidr:/etc/postfix/postscreen_access.cidr

Agregar el archivo de lista blanca

postscreen_access_list = permit_mynetworks cidr:/etc/postfix/postscreen_access.cidr cidr:/etc/postfix/postscreen_spf_whitelist.cidr

Guardar y cerrar el archivo. Luego reiniciar Postfix para que los cambios surtan efecto.

systemctl restart postfix

Editar el crontab del usuario root.

crontab -e

Añadir las dos siguientes líneas al final para actualizar regularmente la lista blanca.

@daily /usr/local/bin/postwhite/postwhite > /dev/null 2>&1 #Actualizar las listas blancas de Postscreen
@weekly /usr/local/bin/postwhite/scrape_yahoo > /dev/null 2>&1 #Update Yahoo! IPs para las listas blancas de Postscreen

Guardar y cerrar el archivo. Ahora, si se envía un correo electrónico desde Gmail a la dirección de correo del dominio, y se comprueba el registro de correo, se verá que Postscreen no realiza ninguna prueba, porque la dirección IP está en la lista blanca.

Feb 10 13:04:17 mail postfix/postscreen[24895]: CONNECT from [209.85.166.44]:38257 to [23.254.225.226]:25
Feb 10 13:04:17 mail postfix/postscreen[24895]: WHITELISTED [209.85.166.44]:38257
Feb 10 13:04:17 mail postfix/smtpd[26596]: connect from mail-io1-f44.google.com[209.85.166.44]
Cuando un correo electrónico no se envía, termina en una de las dos colas dentro de Postfix: pending (pendiente) y deferred (diferido).
La cola de pendientes incluye todos los mensajes que has enviado a Postfix que aún no han sido enviados y entregados al servidor del destinatario. La cola de correo diferido contiene todos los mensajes que han fallado y se necesita reintentar enviarlos (fallo temporal).
Postfix intentará reenviar los mensajes de la cola diferida a intervalos establecidos. Esto está configurado a 5 minutos de manera predeterminada, pero este proceso es totalmente configurable.
Introduciendo cualquiera de los siguientes comandos, puedes inspeccionar y gestionar tus colas de mensajes de Postfix con facilidad.

Cómo revisar las colas de mensajes de Postfix

1) Visualizar las colas de correo: diferido y pendiente

# mailq

o

# postqueue -p

Alternativamente, para guardar la salida en un archivo de texto, ejecuta

# mailq > mailqueue.txt

o

# postqueue -p > mailqueue.txt

Cualquiera de estos comandos mostrará el remitente, los destinatarios y el ID, pero no el mensaje en sí. Aunque el ID ayudará a localizar los mensajes individuales.

Ver el mensaje (contenido, cabecera y cuerpo) en la cola de Postfix

Los ID de los mensajes están disponibles en la cola de mensajes. Así que, para ver un mensaje con el ID XXXXXXX, ingresar

# postcat -vq XXXXXXXXXX

O, para guardarlo en un archivo, introducí

# postcat -vq XXXXXXXXXX > emailXXXXXXXX.txt

Una característica útil para los servidores web es habilitar mail.add_x_header = on en la configuración de Postfix.
Esto añadirá una cabecera a todos los mensajes de correo electrónico salientes mostrando el script y el usuario que generó cada mensaje. Una vez habilitado esto añadirá la siguiente cabecera extra al mensaje:

X-PHP-Originating-Script: 1001:spamEmailer.php

En este ejemplo, 1001 es el ID del usuario y spamEmailer.php es el script que envía el mensaje. Esto permite rastrear rápidamente el origen de cualquier mensaje de spam enviado desde nuestro servidor.

Monitoreo de la cola en tiempo real

# watch -n1 mailq

Para filtrar la salida con grep es necesario especificar el comando entre comillas

# watch 'mailq | grep "[^A-F0-9]"'

Cómo eliminar el correo en cola de espera

Forzar el procesamiento de la cola

# postqueue -f

o

# postfix flush

Eliminar el correo en cola

Un comando permite eliminar todos los mensajes en cola en Postfix. Esto incluye los mensajes de las pending (pendiente) y deferred (diferido):

# postsuper -d ALL

Para borrar específicamente todos los mensajes de la cola diferida (es decir, sólo los que el sistema pretende reintentar más tarde), ingresá

# postsuper -d ALL deferred

Eliminar selectivamente el correo de la cola

También se pueden eliminar mensajes específicos de la cola de correo. Esto no es algo que esté incluido de forma nativa con las herramientas estándar de Postfix, pero (gracias a que usamos software libre) existe una solución para ello.

Así, para eliminar todos los mensajes de la cola de correo enviados por o a usuario@ejemplo.com (el comando es el mismo independientemente de si se trata de la dirección del remitente o del destinatario), se puede utilizar este comando:

# mailq | tail +2 | awk 'BEGIN { RS = "" } / usuario@ejemplo\.com$/ { print $1 }' | tr -d '*!' | postsuper -d -

O

# postqueue -p | tail -n +2 | awk 'BEGIN { RS = "" } /@dominio\.com/ { print $1 }' | tr -d '*!' | postsuper -d -
Pflogsumm crea un análisis/resumen de los registros para de Postfix. Está diseñado para proporcionar una visión general de la actividad de Postfix, con el suficiente detalle para dar al administrador un “aviso” de los posibles puntos problemáticos.
Pflogsumm genera resúmenes y, en algunos casos, informes detallados de de los volúmenes de tráfico del servidor de correo, el correo electrónico rechazado y rebotado, y las advertencias, errores y pánicos del servidor. advertencias, errores del servidor.
Se encuentra disponible en los repositorios de Debian, así que su instalación es sencilla.

# apt install -y pflogsumm

Usar el siguiente comando para generar un reporte,

para hoy

pflogsumm -d today /var/log/mail.log

para ayer

pflogsumm -d yesterday /var/log/mail.log

para esta semana

pflogsumm /var/log/mail.log

Para emitir informes de “problemas” (rebotes, diferidos, advertencias, rechazos) antes de las estadísticas “normales”, usar el parámetro –problems-first.

pflogsumm -d today /var/log/mail.log --problems-first

Para añadir la dirección de correo electrónico de origen a cada informe de rechazo, utilizar el parámetro –rej-add-from.

pflogsumm -d today /var/log/mail.log --rej-add-from

Para mostrar el detalle completo en los resúmenes de rechazo, usar el parámetro –verbose-msg-detail.

pflogsumm -d today /var/log/mail.log --rej-add-from --verbose-msg-detail

Se puede añadir una tarea cron para que pflogsumm envíe un informe a una dirección de correo electrónico cada día.

crontab -e

Agregar la siguiente línea, que generará un informe cada día a las 4:00 AM.

0 4 * * * /usr/sbin/pflogsumm -d yesterday /var/log/mail.log --problems-first --rej-add-from --verbose-msg-detail -q

Para recibir el informe por correo electrónico, añadir la siguiente línea por encima de todos los trabajos cron.

MAILTO="casilla@dominio.edu.ar"

Se debe prestar atención a la sección de detalles de los mensajes rechazados, para ver por qué razón se rechazan esos correos electrónicos y si hay algún falso positivo.

En caso de preferir una interfaz gráfica se puede optar por instalar Lightmeter, una herramienta basada en web, cuya instalación se describe en monitoreo de servidor de correo con lightmeter.

Una característica muy buena que tiene Postfix es la capacidad de depurar hosts individuales específicos. Sólo hay que añadir esto al main.cf:

# Depurar hosts individuales
debug_peer_level=3
debug_peer_list=regexp:/etc/postfix/debug_peers

El nivel predeterminado es 2. En el caso del ejemplo estamos usando un archivo de mapeo, pero no es estrictamente necesario. Basta con ingresar valores separados por coma:

debug_peer_list=170.0.131.2,ejemplo.edu.ar

Utilizando regex podemos capturar múltiples IPs y dominios similares. Este es un ejemplo:

# Esta es una lista disimulada como un hash clave-valor.
# Los campos de la derecha sólo son útiles para las pruebas.
# Por alguna extraña razón, el regex de Postfix no soporta
# el parámetro "\d": /185\.234\.219\d{1,3}/ A
/170\.0\.131\.[0-9]{1,3}/ A
/[0-9]{4}.com/ B
/139\.176\.255\.106/ C

Es necesario tener en cuenta que esto es sólo un listado y no un mapa real, pero Postfix utiliza el mismo código de análisis para estos por lo que hay que presentar como un archivo de mapeo. Así que los campos de la derecha (A, B y C) – no significan nada. Son sólo marcadores de posición. Pero son útiles para probar los patrones de coincidencia.
Por supuesto, cuando se configura el archivo de mapeo resulta necesario procesarlo con postmap:

postmap debug_peers

Para evitar recibir errores al procesar el archivo de mapeo hay que ingresar valores con una descripción al lado, por ejemplo:

lists.isc.org #Listas de Correo de la ISC

También se puede ejecutar “postmap -q” para probar el mapeo:

postmap -q "170.0.131.2" regexp:debug_peers

Esto es especialmente útil con regex, ya que a veces el regex es un poco desordenado. De esta manera, podemos cerciorarnos que el mapeo está configurado como queremos.
Además de regex – se puede hacer un hash directo que es sólo un mapa de pares clave-valor; se puede hacer pcre que es como la versión Perl de regex; y se puede hacer CIDR. Al ejecutar el comando “postconf -m”, mostrará con qué se compiló Postfix (el tipo de mapas) que podemos utilizar:

# postconf -m
btree
cidr
environ
fail
hash
inline
internal
memcache
nis
pipemap
proxy
randmap
regexp
socketmap
sqlite
static
tcp
texthash
unionmap
unix

Verbosidad

También se puede configurar la verbosidad en todo el servicio SMTP de Postfix simplemente añadiendo un “-v” en el archivo master.cf:

smtp      inet  n       -       y       -       -       smtpd -v

Luego recargamos Postfix

# systemctl reload postfix

Veremos grandes cantidades de datos, pero podría ser bastante útil a veces. Se puede hacer lo mismo para otros procesos esclavos de Postfix.
Para más detalles recomendamos revisar los documentos de depuración de Postfix.

Herramientas de Análisis

Etiquetas: