X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fcontrollers%2Ftracker.ts;h=915981f6754285a1cc4eb3a3a51323b2497cc161;hb=c7027c06e9a73dad99d3f9bd9937a41a763850ce;hp=53f1653b5bcd5fea221917feb2221ea4fa82bd74;hpb=cef534ed53e4518fe0acf581bfe880788d42fc36;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/controllers/tracker.ts b/server/controllers/tracker.ts index 53f1653b5..915981f67 100644 --- a/server/controllers/tracker.ts +++ b/server/controllers/tracker.ts @@ -1,11 +1,14 @@ -import { logger } from '../helpers/logger' +import * as bitTorrentTracker from 'bittorrent-tracker' import * as express from 'express' import * as http from 'http' -import * as bitTorrentTracker from 'bittorrent-tracker' import * as proxyAddr from 'proxy-addr' import { Server as WebSocketServer } from 'ws' -import { CONFIG, TRACKER_RATE_LIMITS } from '../initializers/constants' +import { Redis } from '@server/lib/redis' +import { logger } from '../helpers/logger' +import { CONFIG } from '../initializers/config' +import { TRACKER_RATE_LIMITS } from '../initializers/constants' import { VideoFileModel } from '../models/video/video-file' +import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist' const TrackerServer = bitTorrentTracker.Server @@ -19,12 +22,15 @@ const trackerServer = new TrackerServer({ http: false, udp: false, ws: false, - dht: false, - filter: function (infoHash, params, cb) { + filter: async function (infoHash, params, cb) { + if (CONFIG.TRACKER.ENABLED === false) { + return cb(new Error('Tracker is disabled on this instance.')) + } + let ip: string if (params.type === 'ws') { - ip = params.socket.ip + ip = params.ip } else { ip = params.httpReq.ip } @@ -34,26 +40,46 @@ const trackerServer = new TrackerServer({ peersIps[ip] = peersIps[ip] ? peersIps[ip] + 1 : 1 peersIpInfoHash[key] = peersIpInfoHash[key] ? peersIpInfoHash[key] + 1 : 1 - if (peersIpInfoHash[key] > TRACKER_RATE_LIMITS.ANNOUNCES_PER_IP_PER_INFOHASH) { - return cb(new Error(`Too many requests (${peersIpInfoHash[ key ]} of ip ${ip} for torrent ${infoHash}`)) + if (CONFIG.TRACKER.REJECT_TOO_MANY_ANNOUNCES && peersIpInfoHash[key] > TRACKER_RATE_LIMITS.ANNOUNCES_PER_IP_PER_INFOHASH) { + return cb(new Error(`Too many requests (${peersIpInfoHash[key]} of ip ${ip} for torrent ${infoHash}`)) } - VideoFileModel.isInfohashExists(infoHash) - .then(exists => { - if (exists === false) return cb(new Error(`Unknown infoHash ${infoHash}`)) + try { + if (CONFIG.TRACKER.PRIVATE === false) return cb() + + const videoFileExists = await VideoFileModel.doesInfohashExistCached(infoHash) + if (videoFileExists === true) return cb() - return cb() - }) + const playlistExists = await VideoStreamingPlaylistModel.doesInfohashExistCached(infoHash) + if (playlistExists === true) return cb() + + cb(new Error(`Unknown infoHash ${infoHash} requested by ip ${ip}`)) + + // Close socket connection and block IP for a few time + if (params.type === 'ws') { + Redis.Instance.setTrackerBlockIP(ip) + .catch(err => logger.error('Cannot set tracker block ip.', { err })) + + // setTimeout to wait filter response + setTimeout(() => params.socket.close(), 0) + } + } catch (err) { + logger.error('Error in tracker filter.', { err }) + return cb(err) + } } }) -trackerServer.on('error', function (err) { - logger.error('Error in tracker.', { err }) -}) +if (CONFIG.TRACKER.ENABLED !== false) { -trackerServer.on('warning', function (err) { - logger.warn('Warning in tracker.', { err }) -}) + trackerServer.on('error', function (err) { + logger.error('Error in tracker.', { err }) + }) + + trackerServer.on('warning', function (err) { + logger.warn('Warning in tracker.', { err }) + }) +} const onHttpRequest = trackerServer.onHttpRequest.bind(trackerServer) trackerRouter.get('/tracker/announce', (req, res) => onHttpRequest(req, res, { action: 'announce' })) @@ -61,14 +87,36 @@ trackerRouter.get('/tracker/scrape', (req, res) => onHttpRequest(req, res, { act function createWebsocketTrackerServer (app: express.Application) { const server = http.createServer(app) - const wss = new WebSocketServer({ server: server, path: '/tracker/socket' }) + const wss = new WebSocketServer({ noServer: true }) + wss.on('connection', function (ws, req) { - const ip = proxyAddr(req, CONFIG.TRUST_PROXY) - ws['ip'] = ip + ws['ip'] = proxyAddr(req, CONFIG.TRUST_PROXY) trackerServer.onWebSocketConnection(ws) }) + server.on('upgrade', (request: express.Request, socket, head) => { + if (request.url === '/tracker/socket') { + const ip = proxyAddr(request, CONFIG.TRUST_PROXY) + + Redis.Instance.doesTrackerBlockIPExist(ip) + .then(result => { + if (result === true) { + logger.debug('Blocking IP %s from tracker.', ip) + + socket.write('HTTP/1.1 403 Forbidden\r\n\r\n') + socket.destroy() + return + } + + return wss.handleUpgrade(request, socket, head, ws => wss.emit('connection', ws, request)) + }) + .catch(err => logger.error('Cannot check if tracker block ip exists.', { err })) + } + + // Don't destroy socket, we have Socket.IO too + }) + return server }