准备工作

准备工作

我收到Google 的 DMARC 报告每天以包含 XML 文件的 zip 文件形式下载。我手动下载每个 zip 文件~/Documents/DMARC

我想汇总所有已保存的 DMARC 报告中的信息并生成一份人性化可读的报告(例如 LibreOffice Calc 电子表格中的表格)。我宁愿不要一直运行占用大量内存或 CPU 的服务。

关于如何做到这一点有什么建议吗?

背景信息

基于域的消息认证、报告和一致性 (DMARC) 是一种不断发展的技术标准DMARC 报告格式由该标准指定。它也看起来像 Ubuntu原生支持 DMARC,但我需要详细的说明。

上面的 Google 链接显示了输入 DMARC XML 文件格式和输出表格形式的示例。根据要求,它们粘贴在此处。

示例输入 XML 文件:

<?xml version="1.0" encoding="UTF-8" ?>
<feedback>
  <report_metadata>
    <org_name>solarmora.com</org_name>
    <email>[email protected]</email>
   <extra_contact_info>http://solarmora.com/dmarc/support</extra_contact_info>
    <report_id>9391651994964116463</report_id>
    <date_range>
      <begin>1335571200</begin>
      <end>1335657599</end>
    </date_range>
  </report_metadata>
  <policy_published>
    <domain>bix-business.com</domain>
    <adkim>r</adkim>
    <aspf>r</aspf>
    <p>none</p>
    <sp>none</sp>
    <pct>100</pct>
  </policy_published>
  <record>
    <row>
      <source_ip>203.0.113.209</source_ip>
      <count>2</count>
      <policy_evaluated>
        <disposition>none</disposition>
        <dkim>fail</dkim>
        <spf>pass</spf>
      </policy_evaluated>
    </row>
    <identifiers>
      <header_from>bix-business.com</header_from>
    </identifiers>
    <auth_results>
      <dkim>
        <domain>bix-business.com</domain>
        <result>fail</result>
        <human_result></human_result>
      </dkim>
      <spf>
        <domain>bix-business.com</domain>
        <result>pass</result>
      </spf>
    </auth_results>
  </record>
</feedback>

输出表样例: 输出表样例:

答案1

这些是我在 Ubuntu 22.04 上使用的步骤。我希望它们可以得到改进,以用于更广泛的用途,所以请发表评论并告诉我,我会尽力调整解决方案。

该解决方案将使用dmarcts-report-parser 包mysql 服务器来自 Ubuntu 默认存储库。最终输出是一个 csv 文件,因此此解决方案可能最适合轻度用户(例如一个或两个域)和偶尔使用 DMARC 聚合报告的用户。

以下是 LibreOffice Calc 中输出 CSV 文件的示例(显示约一半的列): 输出 csv 文件


准备工作

  1. 下载 DMARC 聚合报告:从电子邮件中下载 DMARC 聚合报告附件。这些文件通常以.xml.gz或结尾.zip,无需提取它们,因为 dmarcts-report-parser 会为您提取。

    • 注意:dmarcts-report-parser 可以配置为从 IMAP 服务器下载 DMARC 报告。出于安全考虑,我没有使用此功能。
    • 提示:除了手动下载 DMARC 报告附件之外,还可以使用 Google Apps Script(我使用这个)、Microsoft Power Automate 和各种电子邮件客户端插件自动执行此操作。
  2. 创建工作文件夹:为了本次练习,我将创建一个名为的文件夹,dmarcprocess用于包含配置文件和最终的 csv 文件输出,以及一个名为的子文件夹,Reports用于存储从步骤 1 下载的 DMARC 聚合报告。

    • 打开终端
    • mkdir ~/Documents/dmarcprocess
    • cd ~/Documents/dmarcprocess
    • mkdir Reports
    • 将所有 dmarc 报告复制到Reports文件夹中

设置 MySQL 服务器

  1. 安装 MySQL:此步骤假设mysql服务器尚未安装。

    • sudo apt update
    • sudo apt install mysql-server
    • 检查 msql 服务器是否处于活动状态:(sudo service mysql status使用 Ctrl-C 退出)。响应应为Active: active (running)。如果不处于活动状态,请尝试sudo systemctl start mysql
    • 推荐:sudo systemctl disable mysql阻止 mysql 在 PC 启动时自动启动并使用系统资源。您可以使用sudo systemctl start mysql手动启动和sudo systemctl stop mysql手动停止 mysql 服务器。
    • 注意:mysql 服务器使用默认设置安装,不太安全(例如,root用户没有密码)。如果您打算在启动时自动启动 mysql 服务器,您可能需要稍后更改这些设置。
  2. 创建数据库和用户:我们将为 dmarcts-report-parser 创建默认数据库和默认用户。这些可以稍后自定义。

    • sudo mysql -u root -p登录 mysql 服务器,然后在“输入密码:”提示符下按 Enter,因为没有root密码。以下命令需要在mysql>提示符下输入。我还包含了服务器应如何响应每个命令。
    • CREATE DATABASE dmarc;创建一个名为 dmarc 的新数据库。服务器响应:Query OK, 1 row affected
    • USE dmarc;连接到新创建的数据库。服务器响应:Database changed
    • CREATE USER 'dmarc'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';创建新用户。服务器响应:Query OK
    • GRANT ALL PRIVILEGES ON dmarc.* TO 'dmarc'@'localhost';授予新用户对新数据库的完全访问权限。服务器响应:Query OK
    • FLUSH PRIVILEGES;重新加载权限。服务器响应:Query OK
    • quit;返回终端。

设置 dmarcts-report-parser

  1. 安装 dmarcts-report-parser

    • sudo apt install dmarcts-report-parser
  2. 配置 dmarcts-report-parser:将示例配置文件复制到工作文件夹中,然后编辑它。确保您位于~/Documents/dmarcprocess/以下命令的文件夹中。

    • cp /usr/share/doc/dmarcts-report-parser/examples/dmarcts-report-parser.conf.sample ./dmarcts-report-parser.conf复制并重命名示例配置文件。
    • sed -i "s/'dbhost'/'localhost'/" ./dmarcts-report-parser.conf将 mysql 服务器的名称更改为localhost

设置表并导出视图

  1. 首次运行 dmarcts-report-parser:dmarcts-report-parser 的第一次运行将创建数据库表,然后使用之前下载的 dmarc 报告填充数据库。

    • dmarcts-report-parser -z ./Reports/*
    • 系统应该响应Adding missing table <report> to the database.并且Adding missing table <rptrecord> to the database.这意味着 dmarcts-report-parser 需要的两个数据库表已经创建。
    • 注意:-z用于根据项目页面。我发现此选项适用于.zip.xml.gz文件。奇怪的是,此选项目前没有记录在Ubuntu 手册页。其他潜在文件类型包括 mbox ( -m)、MIME ( -e) 和 xml ( -x)。
  2. 创建数据库视图:数据库视图简化了数据的导出。

    • sudo mysql -u root -p重新登录 mysql 服务器,然后在“输入密码:”提示符下按 Enter,因为没有root密码。以下命令需要在mysql>提示符下输入。我还介绍了服务器应如何响应每个命令。
    • USE dmarc;连接到新创建的数据库。服务器响应:Database changed
    • CREATE VIEW exportview AS SELECT * FROM rptrecord INNER JOIN report USING (serial);创建一个名为的新视图导出视图来自 dmarcts-report-parser 填充的两个表。
    • quit;返回终端。

导出数据及后续使用

  1. 导出数据:以下命令将使用 dmarc 数据导出到文件中dmarc-report.csv。它假定您在~/Documents/dmarcprocess/文件夹中。

    • mysql --user='dmarc' --password='password' --batch --execute='SELECT * FROM dmarc.exportview;' | sed 's/\xml.*/xml/;s/\t/","/g;s/^/"/;s/$/"/' > ./dmarc-report.csv
    • Mysql 将会抱怨,mysql: [Warning] Using a password on the command line interface can be insecure.但是该警告不会影响上述命令的结果。
    • 新文件dmarc-report.csv是一个 CSV 文件,可以使用电子表格应用程序(例如 LibreOffice Calc)打开和分析。
    • 此命令使用 MySQL 命令行客户端连接到数据库,将视图导出为 tsv 格式。然后sed删除 xml 输出,然后将提醒转换为 csv 格式。
      • --execute= 执行以下语句并返回结果
      • --batch 使用制表符作为列分隔符打印结果。可以排除此选项,因为--execute默认情况下它似乎执行相同的操作。
      • sed 's/\xml.*/xml/;删除“xml”后面的所有文本。这是必需的,因为数据库列之一(raw_xml)包含原始 xml 数据,这使得转换为 CSV 格式变得困难。如果有人有更好的方法,请告诉我。
      • s/\t/","/g;用 替换所有制表符,
      • s/^/"/;"在每行的开头插入一个。
      • s/$/"/'"在每行末尾插入一个。
  2. 后续使用

    • 我不需要 mysql 一直运行,因此我用sudo systemctl disable mysql它来阻止 mysql 在重启时自动启动。
    • 我使用 bash 批处理文件来自动解析和导入新报告并导出结果。
      • sudo systemctl start mysql启动 mysql 服务器
      • dmarcts-report-parser -z ./Reports/*解析报告并将其存储在数据库中
      • mysql --user='dmarc' --password='password' --batch --execute='SELECT * FROM dmarc.exportview;' | sed 's/\xml.*/xml/;s/\t/","/g;s/^/"/;s/$/"/' > ./dmarc-report.csv导出文件。
      • sudo systemctl stop mysql导出完成后停止 mysql 服务器。
    • 目前我每次都会导出所有内容,但在某些时候我可能会修改导出语句以仅导出我需要的数据,同时微调 dmarc、dkim 和 spf 设置。
    • Ubuntu 手册页暗示dmarcts-报告查看器将来会由默认存储库支持。我打算在发生这种情况时更新此答案。

请在评论中提供反馈以帮助改进此答案。

答案2

这是一个更轻量级的解决方案:

#!/usr/bin/env python3
import xml.etree.ElementTree as ET
import os.path

addresses = {}

dirname = os.path.expanduser("~/Documents/DMARC")
for basename in os.listdir(dirname):
    if not basename.endswith(".xml"):
        continue
    tree = ET.parse(os.path.join(dirname, basename))
    row = tree.find("record/row")
    ip = row.find("source_ip").text
    current = addresses.setdefault(ip, { "count": 0, "dmarc_pass": 0, "dmarc_fail": 0, "dkim_pass": 0, "dkim_fail": 0, "spf_pass": 0, "spf_fail": 0 })

    current["count"] += int(row.find("count").text)
    policy = row.find("policy_evaluated")
    dkim_pass = policy.find("dkim").text == "pass"
    spf_pass = policy.find("spf").text == "pass"
    current["dkim_pass" if dkim_pass else "dkim_fail"] += 1
    current["spf_pass" if spf_pass else "spf_fail"] += 1
    current["dmarc_pass" if dkim_pass and spf_pass else "dmarc_fail"] += 1

print("ip_address,email_volume,dmarc_pass,dmarc_fail,dmarc_rate,spf_pass,spf_fail,dkim_pass,dkim_fail")
for ip, current in addresses.items():
    dmarc_pass = current["dmarc_pass"]
    dmarc_fail = current["dmarc_fail"]
    print(f'{ip},{current["count"]},{dmarc_pass},{dmarc_fail},{dmarc_pass/dmarc_fail}%,{current["spf_pass"]},{current["spf_fail"]},{current["dkim_pass"]},{current["dkim_fail"]}')

将其保存到dmarc.pychmod +x dmarc.py。使用 运行它./dmarc.py > dmarc.csv。我只是猜测 DMARC XML 文件格式应该如何工作,因此可能需要进行调整。

示例输出

ip_address,email_volume,dmarc_pass,dmarc_fail,dmarc_rate,spf_pass,spf_fail,dkim_pass,dkim_fail
203.0.113.209,2,0,1,0.0%,1,0,0,1

示例输出 csv libreoffice

相关内容