Ir al contenido

SMTP con Postfix 3.10.12

Por

Madurezvalidated
Última revisión
Validación técnica28 jul 2026 · postfix-3-10-12-debian-13-1-loopback
Publicado
Última actualización

Este laboratorio utiliza Postfix 3.10.12. Comprueba que una misma sesión:

  • anuncia capacidades ESMTP mediante EHLO
  • acepta un usuario local conocido
  • rechaza un usuario local inexistente
  • rechaza un destinatario externo cuando el origen no pertenece a mynetworks
  • vuelve a estado inicial después de retirar el contenedor

La prueba no envía DATA, no entrega mensajes y no valida AUTH, STARTTLS, submission, cola, SPF, DKIM, DMARC, catch-all ni greylisting.

El contenedor usa Debian 13.1 y publica Postfix solo en 127.0.0.1:2525. La instalación se realiza dentro del recurso desechable:

Crear el contenedor
docker run -d --name offsec-kb-smtp-lab \
-p 127.0.0.1:2525:25 debian:13.1-slim sleep infinity

Instala Postfix sin preguntas interactivas. Después crea el usuario local valid, fija el dominio y arranca el servicio:

Instalar y configurar Postfix
docker exec offsec-kb-smtp-lab sh -lc '
export DEBIAN_FRONTEND=noninteractive
apt-get update
echo "postfix postfix/mailname string example.test" | debconf-set-selections
echo "postfix postfix/main_mailer_type string Internet Site" | debconf-set-selections
apt-get install -y postfix
useradd -M valid
postconf -e "myhostname = smtp-lab.example.test"
postconf -e "mydomain = example.test"
postconf -e "mydestination = example.test, localhost"
postconf -e "mynetworks = 127.0.0.0/8"
postconf -e "smtpd_relay_restrictions = permit_mynetworks, reject_unauth_destination"
postfix start
'

local_recipient_maps conserva el valor de Postfix proxy:unix:passwd.byname $alias_maps. Por eso valid@example.test corresponde al usuario creado y invalid@example.test no.

Ncat o Netcat permiten ver cada respuesta. Postfix anuncia PIPELINING después de EHLO, pero el ejemplo añade una pausa para que el registro mantenga el orden:

Comparar tres decisiones RCPT TO
{
sleep 0.3
printf 'EHLO operator.example.test\r\n'
sleep 0.3
printf 'MAIL FROM:<sender@source.test>\r\n'
sleep 0.3
printf 'RCPT TO:<valid@example.test>\r\n'
sleep 0.3
printf 'RSET\r\n'
sleep 0.3
printf 'MAIL FROM:<sender@source.test>\r\n'
sleep 0.3
printf 'RCPT TO:<invalid@example.test>\r\n'
sleep 0.3
printf 'RSET\r\n'
sleep 0.3
printf 'MAIL FROM:<sender@source.test>\r\n'
sleep 0.3
printf 'RCPT TO:<external@destination.test>\r\n'
sleep 0.3
printf 'QUIT\r\n'
} | nc 127.0.0.1 2525

Resultado saneado:

220 smtp-lab.example.test ESMTP Postfix (Debian)
250-smtp-lab.example.test
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-SMTPUTF8
250 CHUNKING
250 2.1.0 Ok
250 2.1.5 Ok
250 2.0.0 Ok
250 2.1.0 Ok
550 5.1.1 <invalid@example.test>: Recipient address rejected: User unknown in local recipient table
250 2.0.0 Ok
250 2.1.0 Ok
554 5.7.1 <external@destination.test>: Relay access denied
221 2.0.0 Bye

Los tres códigos prueban decisiones de la fase RCPT TO. No prueban entrega final. RSET descarta el envelope anterior y permite comparar los casos en la misma conexión.

Registrar las variables que sostienen el resultado
docker exec offsec-kb-smtp-lab postconf \
mail_version myhostname mydestination \
local_recipient_maps smtpd_relay_restrictions

La reproducción registró Postfix 3.10.12, mydestination = example.test, localhost y permit_mynetworks, reject_unauth_destination.

La primera ejecución envió todos los comandos al conectar, antes de leer el banner y negociar EHLO. Postfix respondió 554 5.5.0 Error: SMTP protocol synchronization. El fallo pertenecía al cliente de prueba, no a la política de destinatarios. Las pausas permitieron observar las fases en orden.

Retirar y comprobar el estado final
docker rm -f offsec-kb-smtp-lab
nc -zv 127.0.0.1 2525

El control final devolvió Connection refused. No quedó listener en loopback. La imagen local no contiene datos del entorno y puede retirarse más tarde mediante el procedimiento normal de mantenimiento de Docker.