Repository navigation
Enforce tiers on MTProto secrets - #16
Merged
Merged
Conversation
The Telegram relay terminates obfuscated2 itself and dials the datacenter, so it never passes through the SOCKS5 pipeline -- which meant every phone got the same unlimited pipe regardless of what the account was on the books for. A free-tier customer and a pro one looked identical on the wire. Each secret now carries a tier, and the plan is enforced where the traffic actually is: bandwidth is paced at the tier's rate, concurrent sessions are capped, and a secret that has moved its data allowance is refused. The same Tiers map the SOCKS5 port uses, so the two cannot drift into meaning different things. Counting bytes had to move from a hand-rolled relay loop into the pacer path: io.CopyBuffer cannot report what it moved, so the copy counts as it reads. That is what the plan is billed on, and it is why the data cap knows about a session at all rather than only about sessions still running. Existing installs pick the column up on the next start. SQLite has no "if not exists" for columns, so the ALTER is attempted and a duplicate-column error is the success case -- the one migration the database cannot do on its own. Secrets that were already there keep working and default to unlimited, because silently dropping someone to 1Mbps for an upgrade would be the wrong way to learn about a missing column. Verified live: a secret created as free shows its session and its bytes counted against it, and the panel shows the same. Expiry is the one part of a tier that does not apply here, and the README says so rather than leaving it to be discovered: a Telegram secret has no end date, and a cap or a revocation is how such an account is stopped.
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
📒 Files selected for processing: 8
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The gap
The Telegram relay terminates obfuscated2 itself and dials the datacenter directly, so it never passes through the SOCKS5 pipeline. Every phone therefore got the same unlimited pipe regardless of what its account was on the books for — a free-tier customer and a pro one were indistinguishable on the wire, and neither was metered.
What it does
Each secret carries a tier from the same
Tiersmap the SOCKS5 port uses, so the two cannot drift into meaning different things. The plan is enforced where the traffic actually is:The panel shows live sessions and bytes per phone, so a plan can be seen doing something rather than only being configured.
One implementation note worth a look: counting bytes had to move out of
io.CopyBuffer, which cannot report what it moved, back into the copy loop that reads. That is what the plan is billed on, and it is why the data cap knows about finished sessions at all.Migration
Existing installs pick the column up on the next start. SQLite has no
IF NOT EXISTSfor columns, so theALTERis attempted and a duplicate-column error is the success case — the one migration the database cannot do on its own.Secrets that were already there keep working and default to unlimited: silently dropping someone to 1Mbps because of an upgrade would be the wrong way for an operator to learn about a missing column. A test seeds a pre-migration row and re-runs the migration to prove both.
Verified
freethrough the API shows its session and its bytes counted against it.gofmt/go vetclean; full suite green with and without xray;-raceclean.What is still not covered
Expiry does not apply to a Telegram secret, and the README says so plainly rather than leaving it to be discovered: there is no end date on a secret, and a cap or a revocation is how such an account is stopped. Adding one would mean an expiry column and the management that goes with it — worth doing if you bill on time as well as data.
REALITY sessions still bypass tier limits entirely: xray forwards them through the socks outbound using the service's own credentials, so there is no per-UUID identity to meter. Fixing that means per-user routing rules inside the xray config, which is a much larger change than this one.