Replace RDAP/ipwhois signup-IP classifier with ipapi.is

Flags datacenter, vpn, proxy, tor, and independently-scored abuser
signals instead of regex-matching RDAP org names; anonymous tier
covers 1000 req/day, well above signup volume.
This commit is contained in:
2026-07-06 08:57:55 -07:00
parent e62e3330e4
commit 0356fe7997
7 changed files with 106 additions and 83 deletions
+10 -9
View File
@@ -61,11 +61,12 @@ without touching any account — keep it on until you've watched it for a while.
Every `account.created` delivery already carries the signup IP for free
(`Admin::Account.ip`). On each new local signup, the bot:
1. **Classifies the IP** via RDAP org lookup (`ipwhois`, cached in sqlite) as
`datacenter` (hosting/VPN-keyword match), `mobile` (carrier-keyword match,
informational only), or `residential` (everything else — never flagged).
RDAP failures classify as `unknown` and are never flagged.
2. If **`datacenter`**, the signup is treated with more scrutiny:
1. **Classifies the IP** via [ipapi.is](https://ipapi.is/) (cached in sqlite;
free, keyless tier is 1,000 req/day — `IP_SCRUTINY_IPAPI_KEY` raises the
limit if needed) as any combination of `datacenter`, `vpn`, `proxy`, `tor`,
and `abuser` (ipapi.is's own abuse score), joined with `+`, or `clean` if
none matched. API failures classify as `unknown` and are never flagged.
2. If **any signal matched**, the signup is treated with more scrutiny:
- **Moderator DM** with the IP, org, and classification.
- **Held welcome** (`IP_SCRUTINY_HOLD_WELCOME`) — the welcome DM is skipped
on `account.created` and only sent when `account.approved` fires, i.e.
@@ -130,8 +131,8 @@ A scheduled companion to the two signup-scrutiny signals above (`app/suspicious_
run via `docker exec yttrx-welcomebot python -m app.suspicious_sweep`, e.g. hourly cron on
`admin.yttrx.com`):
1. Any account flagged by **either** IP-scrutiny (datacenter/hosting) or
email-domain scrutiny (disposable/high-risk) has a grace-period clock
1. Any account flagged by **either** IP-scrutiny (datacenter/vpn/proxy/tor/
abuser) or email-domain scrutiny (disposable/high-risk) has a grace-period clock
started the moment it goes live — `account.created` if signups are open
(or auto-approved), `account.approved` if this instance requires
moderator approval. Same dual-event handling the welcome flow already
@@ -140,7 +141,7 @@ run via `docker exec yttrx-welcomebot python -m app.suspicious_sweep`, e.g. hour
that moment (`app.main.maybe_start_suspicious_watch`, table
`suspicious_watch`).
2. The sweep looks for watches past `SUSPICIOUS_GRACE_HOURS` (default 1;
lowered from the original 24 on 2026-07-06 — a datacenter/hosting-IP
lowered from the original 24 on 2026-07-06 — a flagged-IP
signup is already a strong enough spam signal that a full day of grace
was mostly just delaying an inevitable suspend) and compares current
counts to the baseline:
@@ -206,12 +207,12 @@ Copy `.env.example` to `.env` and fill in:
| `ABUSE_HELP_URL` | Appeals/help page the silenced user is linked to |
| `ABUSE_USER_DM` | Template DMed to the silenced user (`{acct}`, `{help_url}`); blank disables |
| `IP_SCRUTINY_ENABLED` | Master switch for IP-based signup scrutiny |
| `IP_SCRUTINY_IPAPI_KEY` | Optional ipapi.is API key for higher rate limits; blank uses the anonymous 1,000 req/day tier |
| `IP_SCRUTINY_DRY_RUN` | `true` — classify + DM only, no held welcome, no ip_block write |
| `IP_SCRUTINY_HOLD_WELCOME` | `true` — hold the welcome for a flagged signup until `account.approved` |
| `IP_SCRUTINY_ABUSE_THRESHOLD` | Distinct-reporter threshold used (if lower) for accounts with a flagged signup IP |
| `IP_SCRUTINY_AUTO_IPBLOCK` | Auto-register a flagged IP into Mastodon's `Admin::IpBlock` |
| `IP_SCRUTINY_IPBLOCK_SEVERITY` | `sign_up_requires_approval` (default), `sign_up_block`, or `no_access` |
| `IP_SCRUTINY_HOSTING_RE` / `IP_SCRUTINY_MOBILE_RE` | Keyword regexes matched against the RDAP org/ASN description |
| `CHECK_MAIL_ENABLED` | Master switch for disposable/high-risk email signup scrutiny |
| `CHECK_MAIL_API_KEY` | check-mail.org API key; blank disables the check |
| `CHECK_MAIL_DRY_RUN` | `true` — classify + DM only, no held welcome, no email_domain_block write, no report-triggered suspend |