Siempre ocurre en el peor momento: tu aplicación intenta enviar un restablecimiento de contraseña y Postfix responde con Relay access denied. Los desarrolladores dicen: «Pero funciona en mi portátil». Tu monitorización muestra que la cola crece. La dirección de correo de negocio muestra mensajes enfadados.
La solución rara vez es «activar el reenvío». La solución es «permitir el reenvío para las cosas correctas». Postfix hace su trabajo: negarse a ser usado como cañón de spam. Tu trabajo es enseñarle quién puede relayer, en qué condiciones y con la menor ambigüedad posible.
Qué significa realmente “Relay access denied”
«Relay access denied» es Postfix diciendo: «He recibido un mensaje de un cliente, pero no estoy dispuesto a reenviarlo a ese destino según la política actual». Es una falla de política, no de conectividad. El servidor puede aceptar la conversación SMTP, pero se niega a ser intermediario.
Esto suele aparecer como una de estas:
- Durante RCPT TO:
554 5.7.1 <user@remote.tld>: Relay access denied(clásico) - En los registros de Postfix:
NOQUEUE: reject: RCPT from ...: 554 5.7.1 ... Relay access denied; from=<...> to=<...> - En el rastro de pila de la aplicación: “SMTP 554 Relay access denied”
Postfix decide si reenviar en función de algunos conceptos:
- Dominios de destinatario locales: cosas que este servidor entrega localmente (vía
mydestinationyvirtual_mailbox_domains). - Dominios de reenvío: cosas para las que este servidor está dispuesto a relayer (vía
relay_domains). - Confianza del cliente: redes o identidades autorizadas para relayer (vía
mynetworks, SASL auth, certificados cliente TLS, etc.). - Restricciones de destinatario: la cadena de reglas que decide sí/no en RCPT (normalmente en
smtpd_recipient_restrictionso, en estilo más nuevo,smtpd_relay_restrictions).
La postura por defecto de Postfix es conservadora: aceptará correo hacia dominios locales, y rechazará el reenvío hacia dominios remotos arbitrarios a menos que el cliente sea de confianza. El error molesta, pero es una buena señal de que tu MTA no está haciendo «outreach comunitario» a los spammers.
Una cita para pegar en un post-it: “Hope is not a strategy.” — Gene Kranz. La política SMTP es igual: defínela, no la desees.
Guía rápida de diagnóstico (revisa esto primero)
Esta es la parte que ejecutas durante una llamada de incidente mientras alguien pregunta: «¿Podemos simplemente abrirlo?». No. Aquí está el camino más rápido a «qué falló» sin abrir las compuertas del relay.
1) Confirma dónde ocurre el rechazo
- Si el rechazo es en RCPT TO con
5.7.1, es política (permisos de relaying). - Si es en connect o MAIL FROM, estás en otro modo de fallo (firewall, requisitos TLS, restricciones de remitente).
2) Identifica la IP del cliente y el dominio del destinatario
Necesitas la IP del cliente y el dominio al que se intenta reenviar. Con esos dos datos puedes decidir si el cliente debe ser de confianza (mynetworks / SASL) y si el destinatario es local/relayable.
3) Revisa tres ajustes de Postfix, en este orden
smtpd_relay_restrictions(osmtpd_recipient_restrictionsen configuraciones antiguas): ¿tienespermit_mynetworksy/opermit_sasl_authenticatedantes dereject_unauth_destination?mynetworks: ¿incluye al cliente?mydestination,virtual_mailbox_domains,relay_domains: ¿se supone que el dominio destinatario es local, virtual o reenviable?
4) Si es un caso de envío (submission), deja de usar el puerto 25
Para usuarios/aplicaciones que deben autenticarse, usa el servicio submission en 587 (o 465) con SASL auth y TLS. El puerto 25 es para SMTP servidor-a-servidor. Puedes usarlo internamente, pero debes hacerlo de forma intencional.
5) Valida que no seas accidentalmente un relay abierto
Antes de declarar victoria, prueba el relaying desde una red no confiable. Tu objetivo: «los clientes de confianza pueden relayer; clientes aleatorios de Internet no pueden».
Chiste #1: Un relay abierto es como dejar la impresora de acreditaciones en el vestíbulo: técnicamente conveniente, espiritualmente catastrófico.
Principios fundamentales: permitir relaying sin convertirse en un relay abierto
Principio A: «Cliente de confianza» es una categoría estrecha
mynetworks debe contener solo redes que controles y que estén autorizadas a enviar correo a Internet a través de ti. Normalmente eso es:
- Loopback (
127.0.0.0/8,[::1]/128) - Subredes privadas donde solo viven servidores (no Wi‑Fi de cafetería, no toda la LAN corporativa a menos que disfrutes llamadas de incidente)
- Una subred VPN dedicada al tráfico de servidores
No pongas 0.0.0.0/0 allí. No pongas «todas las RFC1918» salvo que quieras depurar el portátil infectado del CFO.
Principio B: Usuarios autenticados relayan; extraños no autenticados no
El reenvío para usuarios móviles, runners de CI y contenedores de apps aleatorias se resuelve con autenticación SASL en submission (587/465). Activar TLS, exigir auth y permitir reenvío para identidades autenticadas.
Principio C: reject_unauth_destination es el seguro de protección
En la cadena de restricciones, reject_unauth_destination es lo que evita relays abiertos. Eliminarlo no es «una solución temporal». Es una confesión.
Postfix evalúa comúnmente el reenvío usando smtpd_relay_restrictions (moderno) y/o smtpd_recipient_restrictions (estilo legado). El patrón seguro es:
- Permitir redes de confianza
- Permitir clientes autenticados
- Rechazar destinos no autorizados
Principio D: Decide qué se supone que debe ser tu Postfix
«Relay access denied» ocurre a menudo porque nadie decidió si la máquina es:
- Servidor MX / entrante (acepta correo para tus dominios)
- Relay saliente / smarthost (acepta de clientes internos y reenvía a Internet)
- Ambos (posible, pero exige separación clara de políticas)
Si es ambos, separa la política por listener: puerto 25 para comportamiento MX entrante; puerto 587 para submission autenticado; diferentes restricciones por servicio cuando sea necesario.
Principio E: Depura pensando en la transacción SMTP
Las decisiones de reenvío ocurren en RCPT. Si no sabes qué piensa Postfix del cliente (IP, usuario SASL, estado TLS) y qué piensa del dominio destinatario (local/virtual/relay), estás adivinando. Adivinar es cómo se despliega un relay abierto.
Escenarios reales comunes y la corrección adecuada
Escenario 1: Una app interna envía por el puerto 25 y recibe relay denied
Síntoma: El servidor de la app en 10.0.2.15 se conecta a Postfix y trata de enviar a user@gmail.com; Postfix rechaza el reenvío.
Soluciones correctas:
- Preferido: Mover la app a submission (587) con SASL auth; no confiar en la IP.
- Aceptable en redes controladas: Añadir solo ese servidor (o su subred) a
mynetworks.
Escenario 2: Tu Postfix es un MX y alguien espera que relée saliente
Síntoma: El MX recibe correo entrante correctamente. El envío saliente desde hosts internos falla con relay denied.
Solución: Decide: ¿debe el MX ser tu relay saliente? Si sí, tratalo como tal: habilita submission, SASL y política saliente. Si no, despliega un relay separado (recomendado) y mantiene el MX restringido.
Escenario 3: Configuraste mydestination mal y Postfix piensa que un dominio remoto es local
Síntoma: El correo a user@partner.tld se acepta pero luego rebota localmente, o se intenta entrega local.
Solución: Quita dominios que no son tuyos de mydestination. Usa relay_domains o mapas de transporte cuando realmente pretendas relayer dominios concretos.
Escenario 4: Usas un relay SMTP de proveedor en la nube y ves relay denied internamente
Síntoma: Postfix está configurado con relayhost = [smtp.provider.tld]:587 y funciona al probar localmente, pero clientes internos reciben relay denied.
Solución: Tu Postfix no está relaying para esos clientes. O añade su red a mynetworks (estrechamente) o requiere SASL auth para ellos vía submission.
Escenario 5: Kubernetes/contenedores: la IP de origen no es la que crees
Síntoma: Añadiste la subred del nodo a mynetworks, pero el relay denied persiste; los logs muestran una IP distinta (NAT, red overlay).
Solución: Confía en la IP que realmente ves en los logs. Mejor: exige autenticación en submission y deja de jugar a «adivinar el CIDR del overlay».
Tareas prácticas: comandos, salidas, decisiones (12+)
Estas son las acciones que haces en una máquina en vivo. Cada tarea incluye: un comando, qué significa la salida y la decisión siguiente.
Task 1: Confirmar el rechazo exacto en los registros
cr0x@server:~$ sudo tail -n 50 /var/log/mail.log
Jan 03 10:14:22 mx1 postfix/smtpd[18422]: NOQUEUE: reject: RCPT from app1.internal[10.0.2.15]: 554 5.7.1 <user@gmail.com>: Relay access denied; from=<noreply@corp.example> to=<user@gmail.com> proto=ESMTP helo=<app1.internal>
Jan 03 10:14:22 mx1 postfix/smtpd[18422]: disconnect from app1.internal[10.0.2.15] ehlo=1 mail=1 rcpt=0/1 quit=1 commands=3/4
Qué significa: La IP del cliente es 10.0.2.15. El rechazo es en RCPT. Problema de política.
Decisión: Determinar si 10.0.2.15 debe ser de confianza vía mynetworks o forzar autenticación (submission).
Task 2: Ver la configuración efectiva de Postfix para restricciones de relay
cr0x@server:~$ sudo postconf -n | egrep '^(smtpd_relay_restrictions|smtpd_recipient_restrictions|mynetworks|mydestination|relay_domains|virtual_mailbox_domains|inet_interfaces|smtpd_tls_security_level|smtpd_sasl_auth_enable)'
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, localhost
mynetworks = 127.0.0.0/8 [::1]/128
relay_domains = $mydestination
smtpd_recipient_restrictions = permit_mynetworks,reject_unauth_destination
smtpd_relay_restrictions =
smtpd_sasl_auth_enable = no
smtpd_tls_security_level = may
virtual_mailbox_domains =
Qué significa: Solo localhost puede relayer (mynetworks es loopback). No hay SASL auth. Las restricciones de destinatario incluyen reject_unauth_destination (bien).
Decisión: Si quieres que las apps internas releyen, o amplías mynetworks o habilitas submission + SASL y mantienes mynetworks estrecho.
Task 3: Comprobar si la IP del cliente está en mynetworks (sin adivinar)
cr0x@server:~$ postconf mynetworks
mynetworks = 127.0.0.0/8 [::1]/128
Qué significa: 10.0.2.15 no es de confianza.
Decisión: No añadas «10.0.0.0/8» a la ligera a menos que puedas justificarlo. Prefiere submission con auth para todo lo que no sea una subred de servidores muy controlada.
Task 4: Inspeccionar la configuración a nivel de servicio (submission vs smtp)
cr0x@server:~$ sudo postconf -M | egrep '^(smtp/inet|submission/inet|smtps/inet)'
smtp/inet = smtpd
submission/inet = submission smtpd
smtps/inet = smtps smtpd
Qué significa: Existen servicios submission y smtps. Eso es bueno—ahora asegúrate de que estén configurados para exigir auth y permitir relay a clientes autenticados.
Decisión: Configura submission con smtpd_tls_security_level=encrypt y smtpd_sasl_auth_enable=yes, además de restricciones adecuadas.
Task 5: Verificar listeners de puerto (no asumas que systemd lo hizo)
cr0x@server:~$ sudo ss -lntp | egrep ':(25|587|465)\s'
LISTEN 0 100 0.0.0.0:25 0.0.0.0:* users:(("master",pid=812,fd=13))
LISTEN 0 100 0.0.0.0:587 0.0.0.0:* users:(("master",pid=812,fd=18))
LISTEN 0 100 0.0.0.0:465 0.0.0.0:* users:(("master",pid=812,fd=19))
Qué significa: Postfix escucha en 25, 587, 465. La exposición importa.
Decisión: Si esta máquina no debe servir Internet en puertos de submission, restríngele vía firewall o inet_interfaces / binding del servicio.
Task 6: Configurar una política base de relay segura (Postfix moderno)
Editar /etc/postfix/main.cf y establecer:
cr0x@server:~$ sudo postconf -e 'smtpd_relay_restrictions=permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination'
cr0x@server:~$ sudo postconf -e 'smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination'
...output...
Qué significa: Has puesto los dos permisos seguros antes de la única denegación crucial.
Decisión: Si usas ambos parámetros, mantenlos consistentes. Prefiere usar smtpd_relay_restrictions para la lógica de relaying y guarda las restricciones de destinatario para chequeos adicionales, aunque en muchas configuraciones reales verás ambos.
Task 7: Añadir una red interna estrechamente definida a mynetworks
cr0x@server:~$ sudo postconf -e 'mynetworks=127.0.0.0/8 [::1]/128 10.0.2.0/24'
cr0x@server:~$ postconf mynetworks
mynetworks = 127.0.0.0/8 [::1]/128 10.0.2.0/24
Qué significa: Solo la subred 10.0.2.0/24 puede relayer sin auth. No todo el centro de datos. No todo el universo corporativo.
Decisión: Si no puedes definir con confianza una subred pequeña, no uses confianza basada en IP. Usa submission + auth.
Task 8: Habilitar SASL auth (lado servidor) para submission
En la práctica esto suele usar Dovecot SASL. Primero verifica que Postfix crea que SASL está activado:
cr0x@server:~$ sudo postconf -e 'smtpd_sasl_auth_enable=yes'
cr0x@server:~$ sudo postconf -e 'smtpd_sasl_type=dovecot'
cr0x@server:~$ sudo postconf -e 'smtpd_sasl_path=private/auth'
cr0x@server:~$ sudo postconf smtpd_sasl_auth_enable smtpd_sasl_type smtpd_sasl_path
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
Qué significa: Postfix pedirá a Dovecot que autentique clientes.
Decisión: Si no tienes Dovecot, no copies estos valores por inercia. Usa Cyrus SASL o la pila de auth que soporte tu plataforma. La decisión es: «la autenticación existe y funciona» antes de depender de ella.
Task 9: Exigir cifrado y auth en el servicio submission
Editar /etc/postfix/master.cf para el override del servicio submission (ejemplo):
cr0x@server:~$ sudo postconf -P 'submission/inet/smtpd_tls_security_level=encrypt'
cr0x@server:~$ sudo postconf -P 'submission/inet/smtpd_sasl_auth_enable=yes'
cr0x@server:~$ sudo postconf -P 'submission/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject'
...output...
Qué significa: Submission requiere TLS y requiere auth (o rechaza). Esto reduce drásticamente el abuso.
Decisión: Si tus clientes no pueden hacer TLS, arregla los clientes. No bajes la seguridad del servidor para acomodar librerías obsoletas a menos que te guste vivir peligrosamente.
Task 10: Recargar Postfix de forma segura y vigilar errores de configuración
cr0x@server:~$ sudo postfix check
postfix/postfix-script: warning: /etc/postfix/main.cf: unused parameter: smtpd_relay_restrictions
cr0x@server:~$ sudo systemctl reload postfix
...output...
Qué significa: La advertencia sugiere que tu versión de Postfix o la ruta de configuración puede no estar usando ese parámetro como esperabas, o está sobrescrito por ajustes del servicio.
Decisión: No ignores advertencias. Confirma la versión de Postfix y confirma qué conjunto de restricciones se aplica realmente. Si es necesario, usa el parámetro que tu versión soporte (smtpd_recipient_restrictions en builds antiguos).
Task 11: Confirmar la versión de Postfix y las expectativas de características
cr0x@server:~$ postconf mail_version
mail_version = 3.5.23
Qué significa: Esto es suficientemente nuevo para usar smtpd_relay_restrictions normalmente. Si viste «unused parameter», algo más está mal (error tipográfico, archivo equivocado, chroot, valores por defecto del paquete).
Decisión: Valida la ruta del archivo de configuración en vivo y asegúrate de editar la instancia correcta (contenedores, múltiples instalaciones de Postfix, etc.).
Task 12: Probar la política SMTP desde un host de confianza (prueba positiva)
cr0x@server:~$ swaks --to user@gmail.com --from noreply@corp.example --server mx1 --port 25
=== Trying mx1:25...
=== Connected to mx1.
<- 220 mx1 ESMTP Postfix
-> EHLO app1.internal
<- 250-mx1
<- 250 PIPELINING
-> MAIL FROM:<noreply@corp.example>
<- 250 2.1.0 Ok
-> RCPT TO:<user@gmail.com>
<- 250 2.1.5 Ok
...output...
Qué significa: El reenvío ahora funciona desde el entorno cliente probado.
Decisión: Haz la prueba negativa después desde una red no confiable. El éxito sin eso no es éxito.
Task 13: Probar que no eres un relay abierto (prueba negativa)
cr0x@server:~$ swaks --to victim@remote.tld --from attacker@remote.tld --server mx1 --port 25 --ehlo evil.remote.tld
=== Trying mx1:25...
=== Connected to mx1.
<- 220 mx1 ESMTP Postfix
-> EHLO evil.remote.tld
<- 250-mx1
-> MAIL FROM:<attacker@remote.tld>
<- 250 2.1.0 Ok
-> RCPT TO:<victim@remote.tld>
<- 554 5.7.1 <victim@remote.tld>: Relay access denied
...output...
Qué significa: Un cliente no confiable no puede relayer a un dominio remoto. Eso es lo que quieres.
Decisión: Si esta prueba tiene éxito (es decir, sí relaya), tienes un incidente, no una característica.
Task 14: Confirmar la clasificación del dominio destinatario (local vs relay)
cr0x@server:~$ postconf mydestination relay_domains virtual_mailbox_domains
mydestination = $myhostname, localhost.$mydomain, localhost
relay_domains = $mydestination
virtual_mailbox_domains =
Qué significa: Este servidor considera locales solo su hostname/localhost. No relaya por política para dominios específicos.
Decisión: Si esperas que acepte correo para corp.example, debes añadirlo a mydestination (entrega local) o configurar dominios virtuales. Si esperas que relaye para corp.example hacia otro backend, usa relay_domains más un transporte.
Task 15: Inspeccionar la cola para distinguir “rechazo” de “aceptado pero fallando después”
cr0x@server:~$ mailq
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
B3C2A1D4F9 1249 Fri Jan 3 10:18:01 noreply@corp.example
user@gmail.com
-- 1 Kbytes in 1 Request.
Qué significa: Este mensaje fue aceptado y encolado; el problema podría ser ahora la entrega saliente (DNS, puerto 25 bloqueado, auth del relayhost), no el permiso de relaying.
Decisión: Si el correo está en cola, ya pasaste la etapa de «relay access denied». Cambia la investigación a logs de entrega saliente y egress de red.
Task 16: Rastrear un mensaje en cola de extremo a extremo
cr0x@server:~$ sudo postcat -q B3C2A1D4F9 | sed -n '1,40p'
*** ENVELOPE RECORDS ***
message_size: 1249 1249
message_arrival_time: Fri Jan 3 10:18:01 2026
sender: noreply@corp.example
*** MESSAGE CONTENTS ***
Received: from app1.internal (app1.internal [10.0.2.15])
by mx1 (Postfix) with ESMTP id B3C2A1D4F9
for <user@gmail.com>; Fri, 3 Jan 2026 10:18:01 +0000 (UTC)
Subject: test
...output...
Qué significa: Confirma la identidad del cliente y el destinatario, útil para auditorías y para probar qué host está enviando.
Decisión: Si ves un host remitente inesperado, tu límite de confianza es incorrecto. Arregla mynetworks y el firewall, luego investiga ese host.
Tres microhistorias desde las trincheras del correo corporativo
Microhistoria 1: El incidente causado por una suposición equivocada
Tenían una VM «mail relay» que todo el mundo trataba como plomería: existía, por tanto funcionaba. Un equipo de aplicaciones desplegó un nuevo servicio en una subred diferente tras una reorganización de red. Mismo centro de datos, misma empresa, distinto CIDR.
El despliegue fue limpio hasta el primer correo de restablecimiento. Postfix respondió con “Relay access denied” y el servicio se degradó como si hubiera una caída de autenticación. El ingeniero on-call de la app miró su código porque «SMTP es solo otra llamada HTTP, ¿no?». No lo es.
La suposición equivocada fue simple: mynetworks no incluía «todas las redes internas». No. Incluía exactamente un /24 de hace años, y la única documentación era un comentario en un archivo de configuración que nadie leía.
Lo arreglaron añadiendo la nueva subred a mynetworks. El arreglo de segundo orden—el que realmente importó—fue mover apps a submission autenticado en 587 y reducir mynetworks a unos pocos boxes de infraestructura. Menos excepciones basadas en IP, menos sorpresas futuras.
Microhistoria 2: La optimización que salió mal
Otra compañía quiso «reducir la complejidad» usando una sola instancia de Postfix para todo: MX entrante, relay saliente y notificaciones internas. Una caja, una IP, un lugar para parchear. El diagrama quedaba perfecto.
Optimizaban también la política. Alguien decidió que la cadena de restricciones era «demasiado estricta» para apps internas y esparció reglas permit hasta que los correos empezaron a fluir. Se lanzó un viernes, claro está.
Durante el fin de semana, la caja empezó a enviar mucho correo. No su correo. Parte pasaba a través desde IPs origen extrañas que eran «internas» gracias a un pool de clientes VPN y a una entrada mynetworks demasiado amplia. Cuando los spammers encuentran un relay abierto, no lo guardan en secreto.
El lunes fue un desfile: reputación IP por los suelos, correo legítimo diferido y colas salientes explotadas. Se habían optimizado hasta provocar un incidente de reputación. La solución fue poco glamorosa: separar roles entrantes y salientes, apretar mynetworks, exigir SASL auth en submission y mantener reject_unauth_destination exactamente donde corresponde.
Microhistoria 3: La práctica aburrida pero correcta que salvó el día
Una gran empresa tenía una capa de relays que casi nunca hacía noticia. Eso fue intencional. La trataban como cualquier otro sistema de producción: control de cambios, gestión de configuración y un runbook aburrido pero efectivo.
Un día un equipo de seguridad aplicó un cambio de ACL de red que forzó involuntariamente una ruta NAT para ciertas subredes. De pronto, los logs de Postfix mostraron IPs cliente viniendo de un rango distinto. El reenvío falló para un puñado de servicios, pero el radio de impacto se mantuvo pequeño porque nada confiaba en «toda la red interna».
El on-call siguió el runbook: comprobar los logs para la IP del cliente, verificar si está en mynetworks, confirmar que la autenticación en submission funciona y luego decidir si añadir temporalmente un CIDR estrecho. Añadieron un /28 como parche y abrieron un ticket para arreglar el NAT.
Como tenían la prueba negativa de relay en el runbook, también verificaron que la caja seguía rechazando relaying desde el exterior. Sin relay abierto, sin daño de reputación, sin pánico. Lo aburrido ganó otra vez.
Datos interesantes y contexto histórico (8 puntos)
- Los relays abiertos solían ser comunes. La cultura temprana de internet asumía buen comportamiento; el abuso obligó a endurecer los MTAs por defecto.
- Postfix se diseñó como una alternativa más segura a Sendmail. Wietse Venema lo construyó con arquitectura enfocada en seguridad: múltiples procesos, mínimo privilegio y límites de contención.
- La postura de la industria cambió alrededor de los años 2000. Los proveedores principales empezaron a bloquear o listar agresivamente relays abiertos, empujando a los admins a controles de relay estrictos.
reject_unauth_destinationse convirtió en un pilar. Es efectivamente «no relaye a menos que esté explícitamente permitido», el único comportamiento sensato hoy en Internet.- El puerto 587 existe porque el 25 se volvió un lío. Submission se estandarizó para que usuarios finales se autenticasen y enviasen correo sin mezclar políticas con SMTP servidor-a-servidor.
- Las RBLs cambiaron el comportamiento operativo. Las listas de bloqueo en tiempo real facilitaron que receptores castiguen rápido el mal comportamiento al enviar—a veces demasiado rápido.
- NAT y contenedores complicaron la «confianza por IP». La infraestructura moderna hace que «esta IP es ese host» sea menos fiable; la submission con auth escala mejor.
- «Relay denied» suele ser una señal de éxito. Significa que tu MTA se negó a ser weaponizado—hasta que lo configuras mal.
Errores comunes: síntoma → causa raíz → solución
Esta sección es deliberadamente específica. Si reconoces tu síntoma, obtendrás una solución que no convierte tu servidor de correo en un servicio comunitario.
Equivocación 1: «Funciona localmente pero no desde otros servidores»
- Síntoma:
sendmaildesde el host de Postfix funciona; servidores de apps remotos obtienenRelay access denied. - Causa raíz:
mynetworkssolo contiene loopback, o las restricciones no permiten tu CIDR interno. - Solución: Añade un CIDR estrecho a
mynetworkso exige autenticación en submission. No amplíes a «todo lo privado».
Equivocación 2: «Quitamos reject_unauth_destination y se arregló»
- Síntoma: El correo fluye y luego la reputación colapsa. O tu monitorización muestra volumen saliente inusual.
- Causa raíz: Creaste un relay abierto (o casi).
- Solución: Vuelve a poner
reject_unauth_destination. Añadepermit_mynetworksypermit_sasl_authenticatedantes de él. Prueba el relaying negativo desde redes no confiables.
Equivocación 3: «Pusimos nuestro dominio en mydestination para que relaye»
- Síntoma: El correo a un dominio se acepta pero se entrega localmente, rebota o entra en el mecanismo de buzón equivocado.
- Causa raíz: Confundir «entrega local» con «reenviar para un dominio».
- Solución: Usa
relay_domainsy un mapa de transporte si vas a relayer a otro sistema de correo; usamydestinationsolo cuando entregas localmente.
Equivocación 4: «Confiamos en todo el subnet de la VPN»
- Síntoma: Endpoints aleatorios pueden enviar correo saliente sin auth; seguridad está nerviosa con razón.
- Causa raíz: Los pools de clientes VPN no son «servidores». La confianza por IP es un límite erróneo.
- Solución: Exige SASL auth para usuarios remotos; elimina rangos de clientes VPN de
mynetworks.
Equivocación 5: «Habilitamos submission, pero el relaying sigue denegado»
- Síntoma: El cliente se autentica (o cree hacerlo) en 587, pero RCPT aún recibe relay denied.
- Causa raíz: Falta
permit_sasl_authenticateden la cadena de restricciones de relay para ese servicio, o el servicio submission no está realmente exigiendo auth. - Solución: Añade
permit_sasl_authenticatedasmtpd_relay_restrictionsy/o overrides del servicio submission; confirma que SASL funciona en logs (sasl_username=).
Equivocación 6: «Añadimos la subred, pero Postfix sigue diciendo relay denied»
- Síntoma: Añadiste
10.0.2.0/24pero los logs muestran al cliente como10.244.3.18u otra IP NAT. - Causa raíz: NAT, proxy, redes overlay, o la app no viene desde donde crees.
- Solución: Confía en lo que muestran los logs de Postfix. Ajusta
mynetworksen consecuencia—o deja de confiar en IPs y pasa a submission con auth.
Equivocación 7: «Usamos relayhost y asumimos que los clientes pueden relayer»
- Síntoma: Postfix puede enviar saliente cuando se ejecuta localmente, pero clientes internos reciben relay denied.
- Causa raíz: La configuración de
relayhostafecta la entrega saliente desde Postfix mismo; no autoriza automáticamente a clientes entrantes a relayer a través de él. - Solución: Configura la autorización de clientes entrantes (
mynetworkso auth en submission) por separado.
Chiste #2: SMTP es simple hasta que intervienen los humanos; entonces se convierte en una danza interpretativa con logs.
Listas de verificación / plan paso a paso
Paso a paso: Arreglar relay denied para servidores internos (modelo confianza por IP)
- Identifica la IP del cliente en los logs (
tail -n 50 /var/log/mail.log). - Decide si el cliente debe ser de confianza (¿es un servidor que controlas, parcheado y monitorizado?).
- Añade un CIDR estrecho a mynetworks (preferir /32 o /28–/24, no /8).
- Asegura que las restricciones incluyan:
permit_mynetworks, luegoreject_unauth_destination. - Recarga y prueba desde un host de confianza (prueba positiva).
- Prueba desde un host no confiable (prueba negativa) para confirmar que no es un relay abierto.
- Documenta el CIDR y su propietario (el tú del futuro preguntará por qué existe).
Paso a paso: Arreglar relay denied para usuarios/apps (modelo auth en submission)
- Habilita submission (587) y asegúrate de que solo escuche donde corresponde (firewall/bind).
- Exige TLS en submission (
smtpd_tls_security_level=encryptpara ese servicio). - Habilita SASL auth (Dovecot o Cyrus) y verifica la autenticación en los logs.
- Permite relaying para autenticados (
permit_sasl_authenticatedantes dereject_unauth_destination). - Opcionalmente restringe identidades remitentes por usuario/app para reducir potencial de abuso.
- Prueba con un cliente real que se autentique y envíe a un dominio remoto.
- Ejecuta la prueba negativa de open-relay en el puerto 25 desde redes no confiables.
Paso a paso: Separar roles MX entrante y relay saliente (mejor práctica)
- Mantén el MX estricto: puerto 25 expuesto, sin relaying general, acepta solo tus dominios entrantes.
- Despliega un relay saliente: acepta de redes internas y/o auth en submission, reenvía saliente.
- Separa reputaciones IP: la IP saliente puede tener límites de tasa y monitoreo independiente.
- Usa enrutamiento explícito: los clientes internos apuntan al relay; el MX no se convierte en catch-all.
- Audita ambos: logs, comportamiento de la cola y tasas de rechazo de relay son señales claras.
Preguntas frecuentes (lo que la gente realmente pregunta)
1) ¿Qué hace realmente reject_unauth_destination?
Rechaza destinatarios que no están en tus dominios locales/virtuales/de relay a menos que el cliente esté autorizado para relayer. Es la regla principal para prevenir relays abiertos en muchas configuraciones de Postfix.
2) ¿Es seguro añadir mi subred de apps a mynetworks?
Puedes hacerlo si la subred contiene solo servidores controlados (no endpoints de usuarios) y tienes seguridad sólida en hosts. Es arriesgado cuando las redes son compartidas, dinámicas o incluyen clientes VPN. La auth en 587 escala mejor.
3) ¿Por qué no permitir relaying desde todos los rangos RFC1918?
Porque las redes RFC1918 aparecen donde no esperas: pools VPN, NAT mal configurado, redes de laboratorio puenteadas a producción y, a veces, un atacante con presencia interna. Los límites de confianza amplios envejecen mal.
4) ¿Debo arreglar esto poniendo relay_domains = *?
No. Ese es un camino clásico a «nos convertimos en un relay abierto en espíritu». Los dominios de relay son para los dominios de destinatario que relayeas como servicio; no reemplazan la autorización de clientes.
5) Mis usuarios son remotos. ¿Necesito abrir el puerto 25 entrante?
Para submission de usuarios, no. Usa puerto 587 (o 465) con TLS y auth. El puerto 25 es para correo servidor-a-servidor. Si ejecutas un MX, necesitas 25 entrante para la entrega desde Internet.
6) Habilité SASL pero sigue diciendo relay denied. ¿Qué debo buscar en los logs?
Busca sasl_username= en los logs smtpd de Postfix durante la sesión. Si falta, la auth no ocurre. Si está presente, asegúrate de que permit_sasl_authenticated esté en la cadena de restricciones de relay para ese servicio.
7) ¿Puedo permitir relaying solo a ciertos dominios externos?
Sí. Es una decisión de política: usa chequeos de restricción (recipient access maps) para permitir solo dominios destinatarios aprobados para clientes no autenticados, y exige auth para todo lo demás. Ten cuidado: estás creando un conjunto de reglas que habrá que mantener bajo presión.
8) ¿Cómo sé si creé accidentalmente un relay abierto?
Prueba desde una red no confiable: intenta enviar desde un remitente no local a un destinatario no local a través de tu servidor. El resultado correcto es rechazo en RCPT con Relay access denied (o similar). También vigila logs por volumen de relay inusual e IPs cliente desconocidas.
9) ¿Por qué Postfix a veces rechaza con “Relay access denied” incluso para mi propio dominio?
Si el dominio no aparece en mydestination o virtual_mailbox_domains (o no está correctamente definido como dominio de relay), Postfix lo trata como no local y aplica reglas de relay. Corrige primero la clasificación del dominio.
10) ¿Debería ejecutar entrante y saliente en la misma instancia de Postfix?
Puedes, pero te apuntas a complejidad de políticas. Si puedes separar roles, mejor: MX entrante y relay saliente tienen perfiles de riesgo y operaciones distintos.
Conclusión: próximos pasos prácticos
«Relay access denied» no es que Postfix sea difícil. Es que Postfix se niega a convertirse en el problema de spam de otro. Tu solución es definir explícitamente quién puede relayer y cómo: confianza IP estrecha para servidores controlados, submission autenticado para todo lo demás y mantener reject_unauth_destination justo donde está.
Próximos pasos que puedes ejecutar hoy:
- Extrae una línea real de log e identifica la IP del cliente + el dominio destinatario.
- Decide si ese cliente debe ser de confianza por IP. Si dudas, exige autenticación.
- Implementa la cadena segura de restricciones y recarga Postfix con
postfix checkprimero. - Ejecuta ambas pruebas: «cliente de confianza puede relayer» y «cliente no confiable no puede».
- Escribe la política en un párrafo y guárdala con la configuración. El tú del futuro estará cansado y agradecido.