mail: DMARC parser — classify whole 207.174.124.0/24 as ours (warmup pool)

First live ingest (28 reports) showed our warmup rotation pool (.91-.109, out0x)
mislabeled EXTERNAL because OUR_IPS only listed 4 specific IPs -- every one was
100% DMARC-passing, clearly ours, and would have generated false spoofing alerts.
Replace the literal-IP set with an ipaddress subnet check on 207.174.124.0/24
(our whole block). The only genuinely-external failing sender is 35.174.145.124
(AWS, 32 msgs spoofing us, SPF-fail/no-DKIM, all correctly rejected by p=reject) --
exactly the signal the --alert path is meant to surface.
This commit is contained in:
justin 2026-06-19 08:54:41 -05:00
parent 8e5590b492
commit 707d538847

View file

@ -48,6 +48,7 @@ import argparse
import email
import gzip
import io
import ipaddress
import json
import os
import sys
@ -69,13 +70,20 @@ IMAP_USER = os.getenv("DMARC_IMAP_USER", "dmarc@performancewest.net")
IMAP_PASS = os.getenv("DMARC_IMAP_PASS", "")
IMAP_FOLDER = os.getenv("DMARC_IMAP_FOLDER", "INBOX")
# Our own egress IPs (so the summary can flag UNKNOWN senders failing alignment).
OUR_IPS = {
"207.174.124.71", # transactional (app server)
"207.174.124.94", # bulk / trucking (out05)
"207.174.124.107", # healthcare (hcout1)
"207.174.124.15", # co.carrierone.com relay (Carbonio)
}
# Our own egress space. The whole 207.174.124.0/24 is Performance West's block:
# the warmup rotation pool sends from .91-.109 (out0x), plus .71 transactional,
# .94 bulk, .107 hcout, .15 relay. Anything OUTSIDE this is a third party sending
# as us -- either a legit forwarder we authorized, or (if it fails) a spoofer that
# our p=reject policy is correctly rejecting.
OUR_NETS = [ipaddress.ip_network("207.174.124.0/24")]
def is_ours(ip: str) -> bool:
try:
addr = ipaddress.ip_address(ip)
except ValueError:
return False
return any(addr in net for net in OUR_NETS)
# ── attachment extraction ─────────────────────────────────────────────────────
@ -271,12 +279,13 @@ def summarize(conn, days: int = 7) -> tuple[str, list[str]]:
if total == 0:
continue
pass_pct = round(100 * passed / total)
ours = "ours" if ip in OUR_IPS else "EXTERNAL"
lines.append(f" {ip:<16} [{ours:<8}] total={total:<6} pass={pass_pct}% fail={failed}")
ours = is_ours(ip)
tag = "ours" if ours else "EXTERNAL"
lines.append(f" {ip:<16} [{tag:<8}] total={total:<6} pass={pass_pct}% fail={failed}")
# Alerts: our IP failing alignment, OR an external IP sending as us at volume.
if ip in OUR_IPS and pass_pct < 95 and total >= 20:
if ours and pass_pct < 95 and total >= 20:
problems.append(f"{ip} (ours): only {pass_pct}% DMARC pass ({failed}/{total} fail) -- alignment broken")
if ip not in OUR_IPS and failed >= 20:
if not ours and failed >= 20:
problems.append(f"{ip} (EXTERNAL): {failed} failing msgs sending as us -- possible spoofing")
return "\n".join(lines), problems