diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-08 13:24:57 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-08 13:24:57 +0200 |
| commit | 30d2fe0b495405cbecb3b544fd6c49cb6a32eebb (patch) | |
| tree | 09a8fa835279ebaa8256d8bee5b41adeb9757d62 /docs | |
| parent | e65e598f4fbdcdfdd0b837abe3c794862f66a3e6 (diff) | |
| download | abusectl-30d2fe0b495405cbecb3b544fd6c49cb6a32eebb.tar.gz abusectl-30d2fe0b495405cbecb3b544fd6c49cb6a32eebb.zip | |
plan: take the provider ranges from SPF, not from memory
Every range in the first draft was wrong. They had been written from
memory, and the correct source is each provider's own SPF record, which
is the list of addresses it declares it sends from.
Gmail is the clearest case: the table claimed eleven IPv4 ranges and
_spf.google.com publishes two. Fastmail, Proton and the rest were wrong
in the same way. Outlook and Zoho are added since they were queried
anyway, and the transcription commands are recorded in a comment so the
next check is a copy-paste rather than a search.
Google's goog.json is deliberately NOT the source, though it looks like
one: it lists all Google infrastructure, over a hundred ranges, and using
it would trust every Google-hosted service as part of the user's own mail
path. _spf.google.com is the mail-sending answer.
The table is IPv4 only. An IPv6 hop from one of these providers does not
match and the user is asked instead, which is the safe direction: a hop
wrongly trusted means the real sender is never reported.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KphFXTc2QajxXsHWyvGJ4R
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/plans/2026-09-08-parse.md | 104 |
1 files changed, 88 insertions, 16 deletions
diff --git a/docs/plans/2026-09-08-parse.md b/docs/plans/2026-09-08-parse.md index 579ff0e..8d30cae 100644 --- a/docs/plans/2026-09-08-parse.md +++ b/docs/plans/2026-09-08-parse.md @@ -1781,18 +1781,69 @@ from pathlib import Path from abusectl import parse -# Sending ranges the providers publish themselves. Static rather than read -# from SPF at runtime: SPF is a DNS lookup, and while the never-resolve rule -# is about parsing hostile mail rather than setup, a static table keeps the -# boundary unambiguous. Verify against the provider's own documentation -# before adding an entry. +# Sending ranges the providers publish in their own SPF records, transcribed +# on 2026-09-08 from: +# +# gmail dig TXT _spf.google.com +# fastmail dig TXT spf.messagingengine.com +# proton dig TXT _spf.protonmail.ch + _spf2.protonmail.ch +# outlook dig TXT spf.protection.outlook.com +# zoho dig TXT spf.zoho.eu +# +# Static rather than read from SPF at runtime: SPF is a DNS lookup, and while +# the never-resolve rule is about parsing hostile mail rather than setup, a +# static table keeps the boundary unambiguous. +# +# IPv4 only. An IPv6 hop from one of these providers is simply not matched by +# the table, which is the safe direction: the user is asked instead of a hop +# being wrongly trusted. +# +# THESE GO STALE. A range that has been reassigned means a hop is treated as +# the user's own and the real sender is never reported, so re-check the SPF +# records before a release rather than trusting the date above. PROVIDERS: dict[str, list[str]] = { - "gmail": ["35.190.247.0/24", "64.233.160.0/19", "66.102.0.0/20", - "66.249.80.0/20", "72.14.192.0/18", "74.125.0.0/16", - "108.177.8.0/21", "173.194.0.0/16", "209.85.128.0/17", - "216.58.192.0/19", "216.239.32.0/19"], - "fastmail": ["66.111.4.0/24", "103.168.172.0/22"], - "proton": ["185.70.40.0/22", "51.89.119.103/32"], + "gmail": [ + "74.125.0.0/16", + "209.85.128.0/17", + ], + "fastmail": [ + "103.168.172.128/27", + "202.12.124.128/27", + "204.75.18.128/27", + ], + "proton": [ + "185.70.40.0/24", + "185.70.41.0/24", + "185.70.43.0/24", + "79.135.106.0/24", + "79.135.107.0/24", + "109.224.244.0/24", + "85.9.206.169/32", + "85.9.210.45/32", + "37.187.220.204/32", + "51.83.17.38/32", + "57.129.93.249/32", + ], + "outlook": [ + "40.92.0.0/15", + "40.107.0.0/16", + "52.100.0.0/15", + "52.102.0.0/16", + "52.103.0.0/17", + "104.47.0.0/17", + ], + "zoho": [ + "185.20.209.0/24", + "31.186.226.0/24", + "31.186.243.0/24", + "89.36.170.0/24", + "185.20.211.0/24", + "185.172.199.0/24", + "91.135.68.104/29", + "185.230.214.0/23", + "136.143.168.0/22", + "34.241.242.183/32", + ], } @@ -1957,12 +2008,33 @@ def write(path: Path, answers: dict, force: bool = False) -> Path: Run: `python3 -m unittest tests.test_init -v` Expected: PASS, 15 tests -- [ ] **Step 5: Verify the shipped provider ranges before trusting them** +- [ ] **Step 5: Re-verify the shipped provider ranges against SPF** + +The table was transcribed from the providers' own SPF records on 2026-09-08, +which is the authoritative source: these are the addresses each provider +declares it sends from. It still goes stale, and a range that has been +reassigned means a hop is treated as the user's own and the real sender is +never reported. + +Re-check before relying on it: + +```bash +for d in _spf.google.com spf.messagingengine.com _spf.protonmail.ch \ + _spf2.protonmail.ch spf.protection.outlook.com spf.zoho.eu; do + printf '%-32s ' "$d"; dig +short TXT "$d" +done +``` + +Compare each `ip4:` entry against `PROVIDERS`. Anything that has moved gets +corrected in the table and the transcription date updated. -The table is static data and can go stale. Confirm each provider's ranges -against its own published documentation, and record the date checked in a -comment above `PROVIDERS`. A wrong range here means a hop is treated as the -user's own and the real sender is never reported. +Two properties of this table are deliberate. It is **IPv4 only**: an IPv6 hop +from one of these providers simply does not match, so the user is asked rather +than a hop being wrongly trusted. And Google publishes a much broader +`goog.json` of all its infrastructure, which is **not** what belongs here: +`_spf.google.com` is two ranges, `goog.json` is over a hundred, and using the +latter would trust every Google-hosted service as if it were the user's own +mail path. - [ ] **Step 6: Commit** |
