marque / bloodhound
BitTorrent tracker (announce/scrape) for Marque platform
Requires
- php: ^8.2
- illuminate/queue: ^12.0
- illuminate/redis: ^12.0
- illuminate/routing: ^12.0
- illuminate/support: ^12.0
- marque/threepio: @dev
- marque/trove: @dev
Requires (Dev)
- mockery/mockery: ^1.6
- orchestra/testbench: ^10.0
- pestphp/pest: ^4.0
README
BitTorrent tracker for the Marque platform. Handles announce/scrape with Redis-backed peer storage, client validation, and anti-cheat detection.
Installation
Requires marque/trove.
composer require marque/bloodhound
Publish the config and run migrations:
php artisan vendor:publish --tag=bloodhound-config php artisan migrate
How It Works
Bloodhound registers two endpoints:
| Endpoint | Purpose |
|---|---|
GET /announce/{passkey} |
Peer announces (start, stop, complete) |
GET /scrape/{passkey?} |
Swarm statistics |
Users authenticate via their passkey (auto-generated by Trove's HasTrackerStats trait). Peer data is stored in Redis for performance - no database queries on the announce hot path.
Announce Flow
- Passkey validated, user looked up
- Torrent identified by info_hash
- Anti-cheat checks run
- Client validated against whitelist
- Peer upserted in Redis, stats calculated
- Upload/download deltas queued for database update
- Bencoded peer list returned to client
Peer Storage
All peer data lives in Redis with configurable key prefix. Peers auto-expire after the configured TTL (default: 1 hour). Seeder/leecher counts are maintained as atomic counters.
Configuration
Published to config/bloodhound.php:
Timing
| Key | Default | Description |
|---|---|---|
announce_interval |
1800 |
Seconds between announces (sent to clients) |
min_announce_interval |
300 |
Minimum allowed interval |
peer_expiry |
3600 |
Seconds before inactive peers are removed |
Redis
| Key | Default | Description |
|---|---|---|
redis.connection |
default |
Laravel Redis connection name |
redis.prefix |
bloodhound: |
Key namespace |
Peer Response
| Key | Default | Description |
|---|---|---|
max_peers_per_announce |
50 |
Max peers returned per announce |
peer_response_format |
auto |
auto, compact, or dictionary |
Client Validation
Bloodhound validates BitTorrent clients by peer ID. Default mode is whitelist with 17 pre-configured clients including qBittorrent, Deluge, Transmission, rTorrent, libtorrent, Vuze, and others.
| Key | Default | Description |
|---|---|---|
client_validation.enabled |
true |
Enable client checks |
client_validation.mode |
whitelist |
whitelist or blacklist |
client_validation.whitelist |
(see config) | Allowed clients with version ranges |
client_validation.blacklist |
(see config) | Blocked clients (Xunlei, etc.) |
Each whitelist entry specifies a peer ID pattern, version format, and allowed version range. You can add custom clients or adjust version requirements.
Anti-Cheat
| Key | Default | Description |
|---|---|---|
anti_cheat.enabled |
true |
Master switch |
anti_cheat.max_upload_speed |
104857600 |
100 MB/s cap |
anti_cheat.max_download_speed |
104857600 |
100 MB/s cap |
anti_cheat.min_announce_gap |
60 |
Min seconds between announces |
anti_cheat.max_connections_per_torrent |
3 |
Per user, per torrent |
anti_cheat.max_connections_per_ip |
10 |
Per IP address |
Anti-cheat runs these checks on every announce:
- Port blacklist - Blocks known P2P/ISP-blocked ports
- Announce frequency - Prevents tracker hammering
- Connection limits - Per user and per IP
- Speed checks - Flags impossibly fast transfers
- Data consistency - Validates reported download vs torrent size
- Swarm consistency - Samples 5% of announces for coordinated inflation
Violations fire a CheatDetected event and are logged to Redis for admin review.
Stats Queue
| Key | Default | Description |
|---|---|---|
queue.enabled |
true |
Queue user stat updates |
queue.connection |
null |
Queue connection (null = default) |
queue.queue |
tracker |
Queue name |
Upload/download deltas are dispatched as queued jobs to avoid database writes on the announce path.
Port Blacklist
Default blocked ports include Direct Connect (411-413), Kazaa (1214), eMule (4662), Gnutella (6346-6347), and legacy BitTorrent defaults (6881-6889).
Events
| Event | Fired When | Properties |
|---|---|---|
TorrentCompleted |
Peer finishes download | userId, torrentId, ip, userAgent |
CheatDetected |
Anti-cheat violation | type, userId, torrentId, reason |
TorrentCompleted automatically records a snatch (completion record) via the built-in listener.
Listen to these in your app for custom behaviour:
use Marque\Bloodhound\Events\CheatDetected; Event::listen(CheatDetected::class, function ($event) { // Ban user, notify admin, etc. });
Middleware
Bloodhound applies BlockBrowsers middleware to tracker endpoints. This rejects requests from web browsers (detected by cookies, Accept-Language headers, and user agent strings) - only BitTorrent clients should hit these endpoints.
Requirements
- PHP 8.2+
- Laravel 12+
- Redis
- marque/trove
License
MIT