Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul core Tracker: review whitelist functionality #1268

Closed
Tracked by #1181
josecelano opened this issue Feb 14, 2025 · 0 comments · Fixed by #1269
Closed
Tracked by #1181

Overhaul core Tracker: review whitelist functionality #1268

josecelano opened this issue Feb 14, 2025 · 0 comments · Fixed by #1269
Assignees
Labels
- Developer - Torrust Improvement Experience Code Cleanup / Refactoring Tidying and Making Neat

Comments

@josecelano
Copy link
Member

josecelano commented Feb 14, 2025

Parent issue: #1261

Context

Some months ago I wrote a comment on the function to handle an announce request in the tracker core.

    pub fn announce(
        &self,
        info_hash: &InfoHash,
        peer: &mut peer::Peer,
        remote_client_ip: &IpAddr,
        peers_wanted: &PeersWanted,
    ) -> AnnounceData {
        // code-review: in the `scrape` function we perform an authorization check.
        // We check if the torrent is whitelisted. Should we also check authorization here?
        // I think so because the `Tracker` has the responsibility for checking authentication and authorization.
        // The `Tracker` has delegated that responsibility to the handlers
        // (because we want to return a friendly error response) but that does not mean we should
        // double-check authorization at this domain level too.
        // I would propose to return a `Result<AnnounceData, Error>` here.
        // Besides, regarding authentication the `Tracker` is also responsible for authentication but
        // we are actually handling authentication at the handlers level. So I would extract that
        // responsibility into another authentication service.

        tracing::debug!("Before: {peer:?}");
        peer.change_ip(&assign_ip_address_to_peer(remote_client_ip, self.config.net.external_ip));
        tracing::debug!("After: {peer:?}");

        let stats = self.upsert_peer_and_get_stats(info_hash, peer);

        let peers = self
            .in_memory_torrent_repository
            .get_peers_for(info_hash, peer, peers_wanted.limit());

        AnnounceData {
            peers,
            stats,
            policy: self.config.announce_policy,
        }
    }

The tracker can work on listed mode, meaning it only accepts torrents whose info-hash have been included in the whitelist. There was an smell in the code because the whitelist authorization is performed at the delivery layer (controllers) for the announce request but in the scrape handler (domain) in the tracker core for the scrape request. It's strange that is not done at the same level.

In this issue I'm going to explain how the whitelist currently works and how I think it should work. I'm also going to explain how it's implemented (specially the design) and how I think it should be implemented.

Whitelist functionality

Current behavior

For the announce request, the request is rejected immediately (in the controller) and the client receives an error.

For the scrape request, there is no check at the controller level. All requests reach the domain layer. The scrape handler includes all the requested torrents in the response. However, torrents that have not been included in the whitelist return zeroed stats.

Proposal for a behavior change (not implemented in this issue)

For me, It's confusing to return always data for non-allowed torrents because there is no way to know if that torrent is not allow or there is no data for the torrent because there are no peers yet.

I think there are some alternatives:

  1. Return zeroed data for the not allowed one (what we are doing right now).
  2. Return info only for the allowed ones.
  3. Return an error.
  • With a generic message indicating that at least one of the requested torrents is not allowed.
  • With a message indicating the list of non allowed infohashes.

I have asked ChatGTP (see the response at the end of the issue description) and It said the most common approach is option 2. Apparently (I have not confirm it) OpenTracker and XBT Tracker do that.

I also think option 2 is the best because:

  • The client can know anyway if a torrent is included in the list or nor by making an announce request for that torrent.
  • The client can stop scraping non allowed torrents because it would have a way to know that the torrent is not allowed, directly from the scrape response.
  • If we confirmed that is the common behavior, we would follow the non-official but common practices.

NOTE: That would be a breaking change because clients always expect to receive one item for each torrent in the response. If we decide to change it it should be done in the next major version.

Whitelist design

I'm going to explain how the functionality is implemented now and the changes I want to make immediately. Those changes are not intended to implement the proposal for a behavior change described above. There are independent of that change in the functionality.

Current design

Image

Proposal for a design change

There are some things I would like to refactor:

  1. Introduce submodules for handlers in UDP: servers::udp::handlers::{announce, scrape}.
  2. Create the missing services (app layer) in the UDP tracker. There is no intermediary level between handlers and the core tracker. It will moved to its own package udp-tracker-core
  3. Move the service services::announce::invoke() in the HTTP tracker to the http-tracker-core package.
  4. Move the service services::announce::invoke() in the UDP tracker to the udp-tracker-core package.
  5. Move whitelist authorization from the handler (in the framework level) to the application service in the http-tracker-core and udp-tracker-core packages.
  6. In the tracker-core announce handler return a Result<AnnounceData, AnnounceError> when the torrent is not included in the whitelist.
  7. In the tracker-core scrape handler return a Result<ScrapeData, ScrapeError> so we are able to return errors in the future without breaking the public API.
  8. Add version module also for the UDP tracker. I don't see any reason to use v1 in the http tracker but not in the UDP tracker.

cc @da2ce7


Part of the ChatGTP response about how scrape works for listed trackers:

Image

@josecelano josecelano added - Developer - Torrust Improvement Experience Code Cleanup / Refactoring Tidying and Making Neat labels Feb 14, 2025
@josecelano josecelano self-assigned this Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
@josecelano josecelano linked a pull request Feb 14, 2025 that will close this issue
13 tasks
This was referenced Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit to josecelano/torrust-tracker that referenced this issue Feb 14, 2025
josecelano added a commit that referenced this issue Feb 14, 2025
eca5c59 refactor: [#1268] move scrape logic from udp server to udp_tracker_core package (Jose Celano)
c0fc390 refactor: [#1268] move announce logic from udp server to udp_tracker_core package (Jose Celano)
37a142e refactor: [#1268] move scrape logic from axum to http_tracker_core package (Jose Celano)
74815ab refactor: [#1268] move announce logic from axum to http_tracker_core package (Jose Celano)
e48aaf5 [#1268] move udp services to udp_tracker_core package (Jose Celano)
73753e3 [#1268] move http services to http_tracker_core package (Jose Celano)
dec742e refactor: [#1268] extract servers::udp::services::scrape service (Jose Celano)
3c07b26 refactor: [#1268] extract servers::udp::services::announce service (Jose Celano)
81825c9 refactor: [#1268] separate UDP handlers into diferent modules (Jose Celano)

Pull request description:

  Overhaul core Tracker: review whitelist functionality.

  ### Sub-tasks

  - [x] Introduce submodules for handlers in UDP: `servers::udp::handlers::{announce, scrape}`.
  - [x] Create the missing services (app layer) in the UDP tracker. There is no intermediary level between handlers and the core tracker. It will moved to its own package `udp-tracker-core` later.
  - [x] Move the service `services::announce::invoke()` in the HTTP tracker to the `http-tracker-core` package.
  - [x] Move the service `services::announce::invoke()` in the UDP tracker to the `udp-tracker-core` package.
  - [x] Move logic from the handler (in the framework level - delivery layer) to the application service in the `http-tracker-core` package.
    - [x] For the `announce` request
    - [x] For the `scrape` request
  - [x] Move logic from the handler (controller level - delivery layer) to the application service in the `udp-tracker-core` package.
    - [x] For the `announce` request
    - [x] For the `scrape` request
  - [ ] ~~Add version module also for the UDP tracker. I don't see any reason to use `v1` in the http tracker but not in the UDP tracker.~~ I will leave this until we introduce a new major version.

  ### Sub-tasks for a new PR

  I've left these tasks for a new [issue](#1270). This PR is just moving things and the new tasks imply changing function signatures.

  - [ ] In the tracker-core announce handler return a `Result<AnnounceData, AnnounceError>` when the torrent is not included in the whitelist.
  - [ ] In the tracker-core scrape handler return a `Result<ScrapeData, ScrapeError>` so we are able to return errors in the future without breaking the public API.

ACKs for top commit:
  josecelano:
    ACK eca5c59

Tree-SHA512: d3ee37ffa806e8a86813fe564e3840fab7bfc44d2072f85bc2eba84ac3402c95c0f6a5beb2725071cb0498415f55915431b656e98c71b3a6bf469de961c37f03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
- Developer - Torrust Improvement Experience Code Cleanup / Refactoring Tidying and Making Neat
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant