Expire auto-registered IP blocks after 24 hours
docker-build-push / build-push (push) Successful in 5s
docker-build-push / build-push (push) Successful in 5s
Blocks were registered permanently. An IP block is a claim about who is currently behind an address, and that goes stale: VPS addresses are recycled between customers constantly, and now that the /24 ceiling means most blocks cover a single address, a permanent block increasingly punishes whoever gets that address next rather than the actor we saw. 24h is long enough to break a signup run -- the abuse arrives in bursts, not as a steady trickle -- and short enough that the blocklist stays a live picture rather than something that only ever grows. Mastodon expires these itself and reconcile_blocks already reads an elapsed expires_at as "gone", so expired blocks leave /api/blocks unaided. The one piece that needed adding is an expiry on our own dedup record: reconcile runs hourly, so between a block lapsing and the next pass, reputation_block_ installed would otherwise claim a block Mastodon had already dropped and skip re-installing it. expires_in is omitted rather than sent as 0 when the expiry is switched off. Email domain blocks have no expiry in Mastodon and are untouched.
This commit is contained in:
1 parent
147673fd49
commit
6952fbadf6
3 files changed
+124
-15
No files matched your search
@@ -1224,6 +1224,44 @@ def reputation_api_tests():
|
||||
active = {e["cidr"] for e in client.get("/api/blocks/ip-ranges").json()["items"]}
|
||||
assert "198.51.100.0/24" in active, "re-installing republishes it"
|
||||
|
||||
# M. IP blocks are registered with an expiry, and our own dedup record
|
||||
# lapses with them. Without that, a query between a block expiring and
|
||||
# the next hourly reconcile would claim a block Mastodon has already
|
||||
# dropped -- and skip re-installing it.
|
||||
main.REPUTATION_API_ENABLED = True
|
||||
params = main._ip_block_params("198.51.100.0/24", "test")
|
||||
assert params["expires_in"] == main.IP_SCRUTINY_IPBLOCK_EXPIRES_IN, params
|
||||
assert main.IP_SCRUTINY_IPBLOCK_EXPIRES_IN == 86400, "default is 24 hours"
|
||||
|
||||
saved = main.IP_SCRUTINY_IPBLOCK_EXPIRES_IN
|
||||
main.IP_SCRUTINY_IPBLOCK_EXPIRES_IN = 0
|
||||
assert "expires_in" not in main._ip_block_params("198.51.100.0/24", "test"), \
|
||||
"a 0 expiry omits the field rather than sending 0"
|
||||
main.IP_SCRUTINY_IPBLOCK_EXPIRES_IN = saved
|
||||
|
||||
# An expired record reads as not-installed, so the next query
|
||||
# re-installs rather than assuming it's still there.
|
||||
main.record_reputation_block("ip", "203.0.113.0/24", "datacenter", "Expiring Inc", 86400)
|
||||
assert main.reputation_block_installed("ip", "203.0.113.0/24")
|
||||
with main._db() as conn:
|
||||
conn.execute("UPDATE reputation_block SET expires_at = ? WHERE target = ?",
|
||||
("2020-01-01T00:00:00+00:00", "203.0.113.0/24"))
|
||||
assert not main.reputation_block_installed("ip", "203.0.113.0/24"), \
|
||||
"an expired block must not count as installed"
|
||||
active = {e["cidr"] for e in client.get("/api/blocks/ip-ranges").json()["items"]}
|
||||
assert "203.0.113.0/24" not in active, "an expired block must not be published"
|
||||
|
||||
# Email domain blocks don't expire in Mastodon, so they carry none here
|
||||
# either: recorded with no expiry, they stay installed indefinitely.
|
||||
main.record_reputation_block("email", "rep-forever.test", "", "")
|
||||
assert main.reputation_block_installed("email", "rep-forever.test"), \
|
||||
"email domain blocks have no expiry and stay installed"
|
||||
with main._db() as conn:
|
||||
row = conn.execute(
|
||||
"SELECT expires_at FROM reputation_block WHERE target = ?",
|
||||
("rep-forever.test",)).fetchone()
|
||||
assert row[0] is None, row
|
||||
|
||||
main.REPUTATION_API_ENABLED = False
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user