Closes#41 — and corrects that ticket's premise. The existing limit is per address,
not per account: 50/hour keyed on the client IP. What it misses is that more addresses is
the cheapest thing an abuser buys.
Fifty accounts from one address is refused. Fifty each from two hundred addresses in one
/24 is ten thousand accounts, and one request at a time it looks exactly like a busy
afternoon. The address limit stays; a much larger ceiling now sits behind it, keyed on the
network.
/48 for IPv6, not /64. A /64 is one machine and a customer is often handed many, so
keying on it is barely better than keying on the address. A /48 is a site.
An IPv4-mapped address is IPv4. Treating ::ffff:203.0.113.7 as IPv6 would drop
every mapped address into one enormous shared bucket — the same as no limit, and worse,
since everybody in it would be punished for each other.
Unparseable input keys on itself, never on a constant. Failing open into a shared
bucket would let one attacker exhaust everybody's budget; returning empty would make the
check removable by sending nonsense. Two tests hold that, including one asserting two
different garbage values do not collide.
The allowance is eight times the per-address one, deliberately. A university, an office,
or a carrier behind CGNAT is thousands of real people on one network — refusing them is far
worse than admitting a determined abuser. A ceiling on industrial-scale registration, not a
throttle on ordinary use.
Both limits go through consumeAll, so a refusal by either does not spend the other —
otherwise one machine could burn the network budget and lock out its neighbours.
Tests: 9 new, proven able to fail — folding IPv6 into one bucket turns 8 red. 479 in 41
suites pass. Not merged, not deployed.
Closes #41 — and corrects that ticket's premise. The existing limit is per **address**,
not per account: 50/hour keyed on the client IP. What it misses is that more addresses is
the cheapest thing an abuser buys.
Fifty accounts from one address is refused. Fifty each from two hundred addresses in one
/24 is ten thousand accounts, and one request at a time it looks exactly like a busy
afternoon. The address limit stays; a much larger ceiling now sits behind it, keyed on the
network.
**/48 for IPv6, not /64.** A /64 is one machine and a customer is often handed many, so
keying on it is barely better than keying on the address. A /48 is a site.
**An IPv4-mapped address is IPv4.** Treating `::ffff:203.0.113.7` as IPv6 would drop
every mapped address into one enormous shared bucket — the same as no limit, and worse,
since everybody in it would be punished for each other.
**Unparseable input keys on itself, never on a constant.** Failing open into a shared
bucket would let one attacker exhaust everybody's budget; returning empty would make the
check removable by sending nonsense. Two tests hold that, including one asserting two
different garbage values do not collide.
The allowance is eight times the per-address one, deliberately. A university, an office,
or a carrier behind CGNAT is thousands of real people on one network — refusing them is far
worse than admitting a determined abuser. A ceiling on industrial-scale registration, not a
throttle on ordinary use.
Both limits go through `consumeAll`, so a refusal by either does not spend the other —
otherwise one machine could burn the network budget and lock out its neighbours.
**Tests:** 9 new, proven able to fail — folding IPv6 into one bucket turns 8 red. 479 in 41
suites pass. Not merged, not deployed.
added 6 commits
<ul><li>2ff45519...1a0a93fa - 4 commits from branch <code>main</code></li><li>68f644db - Count sign-ups by network, not only by address</li><li>a49a0f68 - Give network counting a switch, with zero meaning off</li></ul>
[Compare with previous version](/paulhitt/flamenet-relay/-/merge_requests/14/diffs?diff_id=2000708377&start_sha=2ff45519da9fedb1fec7c741337d43534640b405)
added 8 commits
<ul><li>a49a0f68...7da09f19 - 6 commits from branch <code>main</code></li><li>21c77f67 - Count sign-ups by network, not only by address</li><li>e7e1a787 - Give network counting a switch, with zero meaning off</li></ul>
[Compare with previous version](/paulhitt/flamenet-relay/-/merge_requests/14/diffs?diff_id=2001132006&start_sha=a49a0f6825d3ec77938098820625023e93550904)
paulhitt
(Migrated from gitlab.com)
merged commit 83f0a02920 into main2026-09-02 23:53:45 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #41 — and corrects that ticket's premise. The existing limit is per address,
not per account: 50/hour keyed on the client IP. What it misses is that more addresses is
the cheapest thing an abuser buys.
Fifty accounts from one address is refused. Fifty each from two hundred addresses in one
/24 is ten thousand accounts, and one request at a time it looks exactly like a busy
afternoon. The address limit stays; a much larger ceiling now sits behind it, keyed on the
network.
/48 for IPv6, not /64. A /64 is one machine and a customer is often handed many, so
keying on it is barely better than keying on the address. A /48 is a site.
An IPv4-mapped address is IPv4. Treating
::ffff:203.0.113.7as IPv6 would dropevery mapped address into one enormous shared bucket — the same as no limit, and worse,
since everybody in it would be punished for each other.
Unparseable input keys on itself, never on a constant. Failing open into a shared
bucket would let one attacker exhaust everybody's budget; returning empty would make the
check removable by sending nonsense. Two tests hold that, including one asserting two
different garbage values do not collide.
The allowance is eight times the per-address one, deliberately. A university, an office,
or a carrier behind CGNAT is thousands of real people on one network — refusing them is far
worse than admitting a determined abuser. A ceiling on industrial-scale registration, not a
throttle on ordinary use.
Both limits go through
consumeAll, so a refusal by either does not spend the other —otherwise one machine could burn the network budget and lock out its neighbours.
Tests: 9 new, proven able to fail — folding IPv6 into one bucket turns 8 red. 479 in 41
suites pass. Not merged, not deployed.
mentioned in merge request !25
added 6 commits
mainCompare with previous version
added 8 commits
main21c77f67- Count sign-ups by network, not only by addresse7e1a787- Give network counting a switch, with zero meaning offCompare with previous version
mentioned in commit
83f0a02920changed the description