Never block narrower than a /24
docker-build-push / build-push (push) Successful in 24s

A /32 block is close to useless against what IP scrutiny fires on: a
datacenter/VPN/proxy customer has the rest of the range sitting right
there, so blocking the single address we saw stops nothing the same
actor does a minute later from the address next door. The width ceiling
added 2026-09-13 made this the common case rather than the exception:
its fallback for an over-wide ASN route was the bare address, so a
flagged signup out of a /18 hosting allocation got a /32.

Add IP_SCRUTINY_MIN_BLOCK_PREFIX_V4/_V6 (24/48) as a floor under that
ceiling. Anything narrower than the floor -- a missing route, the /32
recorded when a route didn't contain the IP, a small hosting allocation,
or the fallback from a route wider than the ceiling -- is widened to the
network of that width containing the address. At the defaults the floor
equals the ceiling, so every v4 block is now exactly the /24 containing
the flagged address.

State the collateral cost rather than waving at it: at the live settings
(sign_up_block severity, ~30d expiry) one flagged signup now hard-refuses
registration from 256 addresses for a month. Moving the severity to
sign_up_requires_approval or shortening the expiry buys that back, and
setting the floor to 32/128 restores the old behaviour entirely.
This commit is contained in:
pmb committed 2026-09-21 22:33:00 -07:00
1 parent 9e4456b7df
commit 233458d6b8
4 files changed
+189 -67

No files matched your search

+29 -5
View File
@@ -265,13 +265,13 @@ BLOCKS_API_CACHE_SECONDS=300
# address in the same VPS block — but wrong for an ISP aggregate: routes as
# wide as /8, /9 and /11 turn up, and one `abuser` flag on a residential or
# mobile address inside one of those would wall off millions of consumer
# addresses. Anything wider than this ceiling falls back to blocking the
# single address.
# addresses. Anything wider than this ceiling falls back to the floor width
# below -- the /24 containing the address, not the address alone.
#
# /24 costs real blocking strength against large hosting allocations (an OVH
# /16 now blocks one address, not the range, so a repeat offender out of that
# block needs a fresh block each time) in exchange for making the
# mobile/residential collateral-damage case impossible. Raise toward /16 to
# /16 now blocks a /24, not the whole range, so a repeat offender out of
# another part of that allocation needs a fresh block) in exchange for making
# the mobile/residential collateral-damage case impossible. Raise toward /16 to
# trade back the other way.
#
# Applied at registration time, not retroactively: blocks already in force
@@ -298,6 +298,30 @@ IP_SCRUTINY_MAX_BLOCK_PREFIX_V4=24
# equivalent of what a /24 represents in v4.
IP_SCRUTINY_MAX_BLOCK_PREFIX_V6=48
# Narrowest network a single auto-registered IP block may cover -- the floor
# under the ceiling above. Blocking one address is close to useless against
# what this fires on: a datacenter/VPN/proxy customer has the rest of the
# range sitting right there, so a /32 blocks the address we saw and nothing
# the same actor moves to a minute later. Anything narrower than this (a
# missing route, the /32 recorded when a route didn't contain the IP, a small
# hosting allocation, or the fallback from a route wider than the ceiling) is
# widened to the network of this width containing the address.
#
# The collateral cost is real: how much a /24 hurts an innocent neighbour is
# set by the two policies around this one. With IP_SCRUTINY_IPBLOCK_SEVERITY
# =sign_up_block and a month-long IP_SCRUTINY_IPBLOCK_EXPIRES_IN, one flagged
# signup hard-refuses registration from 256 addresses for a month. Moving the
# severity to sign_up_requires_approval (the neighbour is queued for a human
# rather than refused) or shortening the expiry buys that back.
#
# At the default this equals the ceiling, so every v4 block is exactly the
# /24 containing the flagged address. Set it to 32 to restore the old
# behaviour of blocking only what the route says, down to the single address.
IP_SCRUTINY_MIN_BLOCK_PREFIX_V4=24
# The v6 floor, matching the v6 ceiling for the same reason.
IP_SCRUTINY_MIN_BLOCK_PREFIX_V6=48
# ---------------------------------------------------------------------------
# Reputation query API (pre-signup pre-blocking)
# ---------------------------------------------------------------------------