DKIM (DomainKeys Identified Mail) permite que tu servidor de correo firme cada mensaje saliente con una clave privada. Los servidores que lo reciben obtienen la clave pública correspondiente de tu DNS y comprueban la firma, lo que demuestra que el mensaje procede realmente de tu dominio y no se ha modificado por el camino. Gmail, Outlook y Yahoo esperan DKIM, y es imprescindible para que una política DMARC funcione. En este tutorial instalarás OpenDKIM en Ubuntu 24.04, lo conectarás con Postfix, publicarás la clave pública en DNS y comprobarás que tus mensajes superan la verificación.

Requisitos previos

Para seguir este tutorial necesitas:

  • Un servidor con Ubuntu 24.04 LTS y una instalación de Postfix que ya envíe correo, por ejemplo un VPS de CubePath.
  • Un usuario no root con privilegios sudo.
  • Un dominio que controles, con acceso a su zona DNS. Esta guía usa your_domain como dominio de envío; sustitúyelo en todas partes por el tuyo.
  • Un buzón externo que puedas leer (Gmail u Outlook sirven) para comprobar el resultado.

Paso 1: Instalar OpenDKIM

OpenDKIM funciona como un milter: un demonio independiente al que Postfix entrega cada mensaje antes de enviarlo. Instala el demonio y sus herramientas:

sudo apt update
sudo apt install opendkim opendkim-tools

El paquete opendkim proporciona el servicio y el archivo /etc/opendkim.conf. El paquete opendkim-tools incluye opendkim-genkey y opendkim-testkey, que usarás en los pasos siguientes. Comprueba que el servicio se ha instalado:

systemctl status opendkim --no-pager
● opendkim.service - OpenDKIM Milter
     Loaded: loaded (/usr/lib/systemd/system/opendkim.service; enabled; preset: enabled)
     Active: active (running)

Paso 2: Generar el par de claves DKIM

Una clave DKIM se identifica por un selector, una etiqueta corta que forma parte del nombre DNS donde se publica la clave pública (selector._domainkey.your_domain). Usar una fecha como selector, por ejemplo 202609, facilita rotar la clave más adelante: publicas un selector nuevo, cambias a él y eliminas el antiguo.

Ubuntu incluye /etc/dkimkeys, un directorio propiedad del usuario opendkim con permisos 700, pensado para las claves privadas. Genera ahí una clave de 2048 bits:

sudo opendkim-genkey -b 2048 -d your_domain -s 202609 -D /etc/dkimkeys

Esto crea dos archivos:

  • /etc/dkimkeys/202609.private: la clave privada con la que firma OpenDKIM.
  • /etc/dkimkeys/202609.txt: la clave pública, ya con formato de registro DNS.

La clave privada solo debe poder leerla el usuario opendkim; de lo contrario, el servicio se niega a usarla:

sudo chown opendkim:opendkim /etc/dkimkeys/202609.private
sudo chmod 600 /etc/dkimkeys/202609.private
sudo ls -l /etc/dkimkeys
-rw------- 1 opendkim opendkim 1704 Sep 25 10:12 202609.private
-rw------- 1 root     root      502 Sep 25 10:12 202609.txt

Paso 3: Configurar OpenDKIM

Abre el archivo de configuración principal:

sudo nano /etc/opendkim.conf

El archivo por defecto de Ubuntu ya trae valores razonables (Canonicalization relaxed/simple, OversignHeaders From, UserID opendkim). Tienes que indicarle para qué dominio firmar, qué clave usar y dónde escuchar a Postfix. Busca las líneas comentadas Domain, Selector y KeyFile y la línea Socket, y cámbialas para que queden así:

Domain                  your_domain
Selector                202609
KeyFile                 /etc/dkimkeys/202609.private

Socket                  inet:8891@localhost

Asegúrate de que solo queda una línea Socket sin comentar. Un socket TCP en localhost es la opción más sencilla en Ubuntu, porque Postfix ejecuta su servidor SMTP en un chroot dentro de /var/spool/postfix y no puede alcanzar el socket Unix por defecto en /run/opendkim.

Si no se define Mode, OpenDKIM firma y verifica. Firma los mensajes enviados desde 127.0.0.1 (el valor por defecto de InternalHosts) y los de clientes que se autenticaron con SMTP AUTH, lo que cubre el correo enviado por un webmail en el mismo servidor y por los usuarios que envían por el puerto 587. El correo que llega de otros servidores solo se verifica.

Reinicia OpenDKIM y comprueba que escucha en el puerto 8891:

sudo systemctl restart opendkim
sudo ss -ltnp | grep 8891
LISTEN 0      4096       127.0.0.1:8891       0.0.0.0:*    users:(("opendkim",pid=4121,fd=3))

Si el servicio no arranca, consulta el motivo en el journal con sudo journalctl -u opendkim -n 30. Las causas habituales son una ruta de clave incorrecta o permisos erróneos en la clave privada.

Paso 4: Conectar Postfix con OpenDKIM

Postfix tiene que pasar cada mensaje al milter. Abre su configuración principal:

sudo nano /etc/postfix/main.cf

Añade estas líneas al final del archivo:

# Firma DKIM con OpenDKIM
milter_default_action = accept
smtpd_milters = inet:localhost:8891
non_smtpd_milters = $smtpd_milters
  • smtpd_milters se aplica al correo que llega por SMTP, incluido el de los usuarios autenticados.
  • non_smtpd_milters se aplica al correo enviado localmente con el comando sendmail, por ejemplo desde PHP o cron.
  • milter_default_action = accept mantiene el flujo de correo si OpenDKIM está caído: los mensajes salen sin firmar en lugar de rechazarse.

Si smtpd_milters ya tiene un valor (por ejemplo, de un filtro antispam), añade OpenDKIM a esa línea separado por una coma en lugar de crear una segunda.

Comprueba la configuración y recarga Postfix:

sudo postfix check
sudo systemctl reload postfix

postfix check no muestra nada si la configuración es válida.

Paso 5: Publicar la clave pública en DNS

Muestra el registro DNS que ha preparado opendkim-genkey:

sudo cat /etc/dkimkeys/202609.txt
202609._domainkey	IN	TXT	( "v=DKIM1; h=sha256; k=rsa; "
	  "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv3n..."
	  "...Q2hwIDAQAB" )  ; ----- DKIM key 202609 for your_domain

En tu proveedor de DNS, crea un registro TXT con estos valores:

CampoValor
TipoTXT
Nombre / Host202609._domainkey (algunos paneles necesitan el nombre completo 202609._domainkey.your_domain)
Valorv=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkq...IDAQAB

El archivo divide la clave en varias cadenas entre comillas porque una cadena DNS está limitada a 255 caracteres. La mayoría de los paneles DNS esperan un único valor continuo: une las partes entre comillas, sin las comillas, los paréntesis ni el comentario. Si gestionas tú mismo un archivo de zona de BIND, puedes pegar el registro tal cual.

Espera unos minutos y consulta el registro:

dig +short TXT 202609._domainkey.your_domain
"v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv3n..." "...Q2hwIDAQAB"

La respuesta puede llegar dividida en varias cadenas. Es normal: los receptores las unen.

Ahora deja que OpenDKIM compare la clave publicada con tu clave privada:

sudo opendkim-testkey -d your_domain -s 202609 -k /etc/dkimkeys/202609.private -vvv
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: key loaded from /etc/dkimkeys/202609.private
opendkim-testkey: checking key '202609._domainkey.your_domain'
opendkim-testkey: key not secure
opendkim-testkey: key OK

key OK significa que el registro DNS coincide. key not secure solo indica que tu zona no está firmada con DNSSEC y no afecta a DKIM.

Paso 6: Probar un mensaje firmado

Envía un mensaje desde el servidor a un buzón externo que puedas leer. Sustituye las direcciones por las tuyas:

printf 'From: admin@your_domain\nTo: [email protected]\nSubject: Prueba DKIM\n\nEste mensaje debería ir firmado.\n' | sudo sendmail -f admin@your_domain [email protected]

Busca en el log la línea de firma:

sudo journalctl -u opendkim -n 20 --no-pager | grep "DKIM-Signature"
Sep 25 10:31:07 mail opendkim[4121]: 4cKx2N1QzXz9sWb: DKIM-Signature field added (s=202609, d=your_domain)

Abre el mensaje en el buzón de destino y consulta el código fuente original (en Gmail: menú de tres puntos y luego Mostrar original). Los resultados de autenticación deberían incluir:

dkim=pass header.i=@your_domain header.s=202609

Firmar el correo de varios dominios

Las directivas Domain, Selector y KeyFile cubren un solo dominio. Para firmar varios, genera una clave por dominio y usa tablas de búsqueda. Genera la clave del segundo dominio en su propio directorio:

sudo mkdir -p /etc/dkimkeys/example.net
sudo opendkim-genkey -b 2048 -d example.net -s 202609 -D /etc/dkimkeys/example.net
sudo chown -R opendkim:opendkim /etc/dkimkeys/example.net
sudo chmod 600 /etc/dkimkeys/example.net/202609.private

El directorio /etc/opendkim no existe por defecto; créalo antes de editar los archivos:

sudo mkdir /etc/opendkim

Crea la tabla de claves, que asocia un nombre de clave con un dominio, un selector y un archivo de clave privada:

sudo nano /etc/opendkim/key.table
202609._domainkey.your_domain  your_domain:202609:/etc/dkimkeys/202609.private
202609._domainkey.example.net  example.net:202609:/etc/dkimkeys/example.net/202609.private

Crea la tabla de firmas, que asocia las direcciones de remitente con una clave:

sudo nano /etc/opendkim/signing.table
*@your_domain  202609._domainkey.your_domain
*@example.net  202609._domainkey.example.net

Después, en /etc/opendkim.conf, comenta las líneas Domain, Selector y KeyFile y añade:

KeyTable                /etc/opendkim/key.table
SigningTable            refile:/etc/opendkim/signing.table

El prefijo refile: permite usar comodines como *@example.net en la tabla de firmas. Reinicia OpenDKIM, publica el registro TXT de cada dominio y compruébalos uno a uno con opendkim-testkey.

Solución de problemas

  • No aparece ninguna línea DKIM-Signature field added en el log. Postfix no está pasando el mensaje a OpenDKIM, o OpenDKIM considera externo al remitente. Comprueba que postconf smtpd_milters non_smtpd_milters muestra inet:localhost:8891 y que el dominio del From coincide exactamente con el valor de Domain.
  • dkim=fail (bad signature) en el receptor. El mensaje se modificó después de firmarlo, a menudo por una lista de correo o un servicio de reenvío, o el registro DNS tiene una errata. Vuelve a ejecutar opendkim-testkey y compara el valor p= publicado con /etc/dkimkeys/202609.txt.
  • opendkim-testkey: record not found. El registro no existe, aún se está propagando o se creó como 202609._domainkey.your_domain.your_domain porque el panel añadió el dominio dos veces. Consúltalo con dig y corrige el nombre.
  • OpenDKIM no arranca con can't load key. La clave privada no pertenece a opendkim o la pueden leer otros usuarios. Vuelve a aplicar el chown y el chmod 600 del paso 2.

Conclusión

Tu servidor firma ahora el correo saliente con una clave DKIM de 2048 bits, la clave pública está publicada en DNS y los receptores informan de dkim=pass. DKIM por sí solo no indica a los receptores qué hacer con el correo sin firmar, así que el siguiente paso es publicar los registros SPF y DMARC de tu dominio. Planifica también rotar la clave una o dos veces al año: genera un selector nuevo, publícalo, cambia Selector y KeyFile y elimina el registro antiguo una semana después.