]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/controllers/tracker.ts
Use different p2p policy for embeds and webapp
[github/Chocobozzz/PeerTube.git] / server / controllers / tracker.ts
index 2ae1cf86c5d979225929685b5a65c81c980413af..6d60639b880e66da7a213abe58b0273881d46736 100644 (file)
@@ -1,16 +1,14 @@
+import { Server as TrackerServer } from 'bittorrent-tracker'
+import express from 'express'
+import { createServer } from 'http'
+import proxyAddr from 'proxy-addr'
+import { WebSocketServer } from 'ws'
+import { Redis } from '@server/lib/redis'
 import { logger } from '../helpers/logger'
-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 } from '../initializers/config'
 import { TRACKER_RATE_LIMITS } from '../initializers/constants'
 import { VideoFileModel } from '../models/video/video-file'
-import { parse } from 'url'
 import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist'
-import { CONFIG } from '../initializers/config'
-
-const TrackerServer = bitTorrentTracker.Server
 
 const trackerRouter = express.Router()
 
@@ -22,7 +20,6 @@ const trackerServer = new TrackerServer({
   http: false,
   udp: false,
   ws: false,
-  dht: false,
   filter: async function (infoHash, params, cb) {
     if (CONFIG.TRACKER.ENABLED === false) {
       return cb(new Error('Tracker is disabled on this instance.'))
@@ -31,18 +28,18 @@ const trackerServer = new TrackerServer({
     let ip: string
 
     if (params.type === 'ws') {
-      ip = params.socket.ip
+      ip = params.ip
     } else {
       ip = params.httpReq.ip
     }
 
     const key = ip + '-' + infoHash
 
-    peersIps[ ip ] = peersIps[ ip ] ? peersIps[ ip ] + 1 : 1
-    peersIpInfoHash[ key ] = peersIpInfoHash[ key ] ? peersIpInfoHash[ key ] + 1 : 1
+    peersIps[ip] = peersIps[ip] ? peersIps[ip] + 1 : 1
+    peersIpInfoHash[key] = peersIpInfoHash[key] ? peersIpInfoHash[key] + 1 : 1
 
-    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}`))
+    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}`))
     }
 
     try {
@@ -51,10 +48,19 @@ const trackerServer = new TrackerServer({
       const videoFileExists = await VideoFileModel.doesInfohashExistCached(infoHash)
       if (videoFileExists === true) return cb()
 
-      const playlistExists = await VideoStreamingPlaylistModel.doesInfohashExist(infoHash)
+      const playlistExists = await VideoStreamingPlaylistModel.doesInfohashExistCached(infoHash)
       if (playlistExists === true) return cb()
 
-      return cb(new Error(`Unknown infoHash ${infoHash}`))
+      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)
@@ -78,7 +84,7 @@ trackerRouter.get('/tracker/announce', (req, res) => onHttpRequest(req, res, { a
 trackerRouter.get('/tracker/scrape', (req, res) => onHttpRequest(req, res, { action: 'scrape' }))
 
 function createWebsocketTrackerServer (app: express.Application) {
-  const server = http.createServer(app)
+  const server = createServer(app)
   const wss = new WebSocketServer({ noServer: true })
 
   wss.on('connection', function (ws, req) {
@@ -87,11 +93,24 @@ function createWebsocketTrackerServer (app: express.Application) {
     trackerServer.onWebSocketConnection(ws)
   })
 
-  server.on('upgrade', (request, socket, head) => {
-    const pathname = parse(request.url).pathname
+  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
+          }
 
-    if (pathname === '/tracker/socket') {
-      wss.handleUpgrade(request, socket, head, ws => wss.emit('connection', ws, request))
+          // FIXME: typings
+          return wss.handleUpgrade(request, socket as any, 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