在签名表和密钥表 Opendkim 中添加多个子域名

在签名表和密钥表 Opendkim 中添加多个子域名

我需要一些主要帮助,在 opendkim 的签名表和密钥表中添加多个子域,而无需逐一列出它们。

如果我想添加 50 个子域名,那将花很长时间。

我正在从名为[电子邮件保护]

以下是我的问题:

  1. 对于 etc/opendkim.conf,我是否需要添加子域名是或将其设置为否?

  2. 对于签名表文件,是否可以添加通配符以适应所有子域,而不是逐行添加所有子域。类似这样的方法可行吗: @.mydomain.com default._domainkey.mydomain.com。我尝试过,但 DKIM 总是失败,除非我将子域名附加到选择器行,如下所示:default._domainkey.test.mydomain.com

  3. 对于 key.table 文件,我应该放什么?default._domainkey.mydomain.com mydomain.com:default:/etc/opendkim/keys/mydomain.com/default.private

或者

default._domainkey.test.mydomain.com test.mydomain.com:default:/etc/opendkim/keys/mydomain.com/default.private

同样,如果我使用第一个值,它不起作用。这意味着如果我有 50 个子域,我需要在两个文件上分别添加 50 次。

第三方 ESPS(例如 mailchimp、sendgrid、aweber)究竟是如何为数千甚至数百万个不同的客户域名和子域名自动执行这一步骤的?

如果我想成为第三方 ESP 并提供我的 smtp 作为发送批量电子邮件的服务,我该如何自动生成 DKIM 密钥和为多个客户端配置,而不必始终在所有文件中添加他们的域/子域上面引用?

答案1

DKIM 标准确实允许父域为子域签署消息:

https://datatracker.ietf.org/doc/html/rfc6376#section-3.10

3.10. 父域签名

在某些情况下,希望域代表其任何子域应用签名,而无需在每个子域中维护单独的选择器(密钥记录)
。...


在我的opendkim.confSigningTable 中,我使用正则表达式文件 ( refile:/etc/opendkim/SigningTable) 来允许通配符匹配,并将所有子域明确匹配到与父域使用的相同键。

*@*.example.com current-key._domainkey.example.com
*@example.com   current-key._domainkey.example.com

然后我就不需要为每个子域维护唯一的 DKIM 密钥,也不需要在 KeyTable 或 SigningTable 文件中维护关联的唯一条目。


一般来说,当你需要扩展你的

  • 自动化您的工作流程
  • 当然,你可以尝试自动化文本文件的管理
  • 或者尝试寻找不需要平面文本文件的自动化解决方案。
  • 简化您的配置。

以 OpenDKIM 为例,很多事情可以通过使用不同于文件的后端来实现:

http://www.opendkim.org/opendkim.8.html#DATA%20SETS列出了几种替代方案:

许多命令行和配置文件参数将引用“ dataset”作为其值。这指的是包含所需值列表的字符串,或包含这些值的文件,或者(如果在编译时启用)包含数据的数据库。
...
d) 如果字符串以“dsn:”开头,并且 OpenDKIM 库被编译为支持该数据库类型,那么字符串的其余部分就是数据存储名称,描述 ODBC 或 SQL 数据库的类型、位置参数和访问凭据。...
例如
(一行全部):

`mysql:://dbuser:dbpass@3306+dbhost/odkim/table=macros?keycol=host?datacol=v1,v2`

...
e) 如果字符串以“ ldap:”,“ ldaps:”或“ ldapi:”开头,则假定它是一组以空格分隔的一个或多个 LDAP URL,用于标识一组要查询的服务器
。...
f)如果字符串以“lua:”开头,则假定它指的是包含 Lua 脚本的文件,每次执行查询时都会执行该脚本。查询的键放在名为“query”的全局变量中,然后被调用的脚本可以访问该变量。脚本可以根据执行的查询类型返回任意数量的值。

需要注意的是,当你使用此类工具而不是文本文件或在 SigningTable 中重新归档数据集时,如果未找到子域的条目,OpenDKIM 会自动查找父域的条目:

man opendking.conf

SigningTable (dataset)

定义一个表,用于根据 From: 标题字段中找到的地址选择一个或多个要应用于邮件的签名。此表中的键因所用表的类型而异;
...

对于所有其他数据库类型,首先检查完整的 user@host,然后检查 host,然后[电子邮件保护](按顺序检查所有超级域名,因此“ foo.example.com”将首先检查“ [email protected]”,然后是“ [email protected]”,然后是“ [email protected]”),然后是 .domain ,然后是 user@* ,最后是 * 。


问题:

如果我想成为第三方 ESP 并提供我的 smtp 作为发送批量电子邮件的服务,我该如何自动生成 DKIM 密钥和为多个客户端配置,而不必始终在所有文件中添加他们的域/子域上面引用?

正如已经回答的那样,通过使用允许入职工作流程的后端,该工作流程不需要操作文本文件,而只需要创建新的数据库记录。

DKIM 要求域所有者向其域数据添加一个或多个特定 DNS 记录。这是不可避免的。

  • 一种方法是,为每个注册的域名生成一个唯一的加密密钥对,并要求域名所有者将相应的公钥添加为 DKIM DNS 记录到他们的 DNS 区域。
    益处:您使用每个客户的唯一私钥签署电子邮件。
    坏处:如果您的客户没有对其 DNS 区域进行相应的更改,您就无法轮换这些密钥。

  • 更方便的是,你需要域名所有者添加 DNS CNAME 记录而不是实际的 DKIM 记录到他们的 DNS 区域。然后,该 CNAME 记录指向您 DNS 区域中的 DKIM 记录,从而授予您完全控制权和全部责任。

    • 您可以让所有客户添加指向 DNS 区域中相同 DKIM TXT 记录的 CNAME 记录。
      益处:需要维护和保护的 DNS 记录和密钥对更少。
      坏处:安全性更脆弱,只有一个秘密保护所有客户。
      例如:

      hbruijn-1._domainkey.yourdomain. IN CNAME  dkim-1.domainkey.hbruijn.example.
      hbruijn-2._domainkey.yourdomain. IN CNAME  dkim-2.domainkey.hbruijn.example.
      
    • 您可以为每个新用户生成唯一的 DKIM TXT 记录,他们需要将自己的 CNAME 记录指向这些记录。(需要具有 API 的 DNS 解决方案,以便您轻松为每个新客户创建新的 DKIM DNS 记录。)
      益处:更强大的安全性,只需 1 个秘密即可保护您的一位客户。
      坏处: DNS 记录和密钥对的维护和保护更加复杂。
      例如:

      hbruijn-1._domainkey.yourdomain. IN CNAME  hbruijn-1.domainkey.unique-customer-ID.hbruijn.example.
      hbruijn-2._domainkey.yourdomain. IN CNAME  hbruijn-2.domainkey.unique-customer-ID.hbruijn.example.
      

这样您就可以开始使用选择器和私钥签署邮件消息hbruijn #1。然后在 6 个月后生成新的 DKIM 密钥对,将其存储为密钥hbruijn #2,更新 #2 DNS 记录,并在一段时间后允许缓存的 DNS 记录过期,重新配置 OpenDKIM 以开始使用密钥 #2 进行签名。

再过六个月(或者如果您愿意,可以更频繁地生成另一个新的密钥对,但将其存储为密钥#1 覆盖旧记录,更新#1 DNS 记录并重新配置 OpenDKIM 以开始使用密钥#1 进行签名。

(当您的所有客户都使用相同的 CNAME 目标时,这几乎可以手动完成。每个客户的唯一密钥对和 DNS 记录需要自动化的工作流程。)

答案2

虽然我无法回答所有问题,但几年前我遇到过类似的问题,并创建了一个简单的 BASH 脚本,它为我完成了大部分工作。但是,它非常特定于我的设置,因此如果它有用,您必须对其进行调整以与您的设置配合使用...我的方案是 rspam + PowerDNS(自托管)。该脚本带有注释,以解释我在进行过程中所做的事情。您可以向 HEREDOC 添加任意数量的域或子域。

更具体地说,我不是程序员,所以我的代码很丑陋且不完整 - 抱歉。您还必须使用一次复制/粘贴一个部分来运行它

#!/bin/bash
#START HERE#
cat << HEREDOC >mailDomains
domain1.com
domain2.org
HEREDOC

cat mailDomains; #4DBG#

fileToCreate="dnsCommandsToRun.sh";
dkimKeysBasePath="/var/lib/rspamd/dkim";
while read -r wmDomain; do
  chown _rspamd:_rspamd "$dkimKeysBasePath";
  dkimDate=$(date +%Y%m%d01); echo "$dkimDate";
  rspamadm dkim_keygen -d "$wmDomain" -s "$dkimDate" -k "${dkimKeysBasePath}/${wmDomain}.${dkimDate}.key" > "${dkimKeysBasePath}/${wmDomain}.${dkimDate}.pub";

  # We create the private_key directly into the subdir where rspam will access/use it, and the public_key to a separate file that we can use to populate the DNS
  cat "${dkimKeysBasePath}/${wmDomain}.${dkimDate}.key" "${dkimKeysBasePath}/${wmDomain}.${dkimDate}.pub";  #4DBG#

  cp "${dkimKeysBasePath}/${wmDomain}.${dkimDate}.pub" "${dkimKeysBasePath}/${wmDomain}.${dkimDate}.pub.DNS";   #Adjust the public key so you can add it to the DNS
    # Clean up the record to make the insertion into DNS manager easier
    perl -0pe 's/^(.*?)\( (.*?)\).*?$/$2/gms' -i "${dkimKeysBasePath}/${wmDomain}.${dkimDate}.pub.DNS";
    perl -0pe 's/\"\n.*?\"//gms' -i "${dkimKeysBasePath}/${wmDomain}.${dkimDate}.pub.DNS";
    perl -pe "s|\"(.*?)\".*?$|\$1|g" -i "${dkimKeysBasePath}/${wmDomain}.${dkimDate}.pub.DNS";
    dkimPDNS=$(cat "${dkimKeysBasePath}/${wmDomain}.${dkimDate}.pub.DNS";);
  commandDKIM="pdnsutil add-record $wmDomain $dkimDate._domainkey TXT 3600 \\\"\"$dkimPDNS\"\\\"";
  printf "#DKIM record\n" >> "$fileToCreate";
  echo "$commandDKIM" >> "$fileToCreate";
cat <<EOF >> /etc/rspamd/dkim_selectors.map
$wmDomain $dkimDate
EOF
done <mailDomains

cat "$fileToCreate";
chmod 700 "$fileToCreate";
sh "$fileToCreate";

cat /etc/rspamd/dkim_selectors.map

chown _rspamd:_rspamd "$dkimKeysBasePath";
chown _rspamd:_rspamd "${dkimKeysBasePath}"/*;
chown _rspamd /var/lib/rspamd/dkim/*;
chmod u=r,go= /var/lib/rspamd/dkim/*;
ls -latr "$dkimKeysBasePath"

#!to verify - AFTER you have set that up on your DNS machine and BEFORE you try to sign mails.
clear;
while read -r wmDomain; do
  printf "\n### %s""$wmDomain\n"
  newDKIM=$(grep "p=" "$dkimKeysBasePath/$wmDomain.$dkimDate.pub" | perl -pe "s/^.*?p=//g" | sed "s/\".*//");  printf "%s\n" "$newDKIM";
  digDKIM=$(dig @8.8.8.8 +short +answer TXT "${dkimDate}._domainkey.${wmDomain}"  | perl -pe "s/^.*?p=//g" | sed "s/\".*//");  printf "%s\n" "$digDKIM";
  if [ "$newDKIM" == "$digDKIM" ]; then
    printf "saved DKIM matches lookup - you should be OK to proceed\n";
    rm -f "${dkimKeysBasePath}/${wmDomain}.${dkimDate}.pub.DNS";  #Once you are sure it works
  else
    printf "saved DKIM does NOT match - something went horribly wrong\n";
  fi;
done <mailDomains

# make sure your DNS servers are in sync and then...
systemctl restart rspamd

相关内容